Please can someone check that I have understood this part of the code for my game or advise a better way of showing this?

//--------------------------------
//          DIFFICULTY
//--------------------------------

void Difficulty()
{
  Top_Border();
  cout << "\n   Choose computer difficulty level.\n"
  "   (E)asy\n"
  "   (A)verage\n"
  "   (H)ard\n\n"
  " ? ";

  cin >> ans;

  if(ans == 'E' || ans == 'e') { diff = 1; }
  else if(ans == 'A' || ans == 'a') { diff = 2; }
  else if(ans == 'H' || ans == 'h') { diff = 3; }
  else Difficulty();
}
  1. We don't know what you understand and what you don't.
  2. Line 20. I as the user obviously typed in something wrong. Perhaps give me a hint on where I screwed up so I won't do it again? Might not be necessary. The hint/instructions are on lines 10 to 12.

in your code ans & diff are undeclared but there is no problem in lines 10 to 12;

I would change everything. More specifically, stop the recursion. Here is a sample :

#include <cctype>
//#include ...
//returns the difficulty level else returns string::npos if fails
int getDifficultyLevel(const char *msg){
 const std::string difMap = "EAH";
 char ans = 0;
 cout << msg;
 return difMap.find( toupper(ans) ) + 1; //add one since index starts at 0
}
int main(){
 std::string difficultPromptMsg = "\nChoose computer difficulty level.\n(E)asy\n(A)verage\n(H)ard\n\n? ";
 int difLevel = string::npos;
 while(difLevel <= 0){
   Top_Border();
   difLevel = getDifficultyLevel( difficultPromptMsg );
   if(difLevel <= 0) cout << "\nInvalid options, please try again\n";
 }
}

That might not be perfect but its a general approach to it

Edited 5 Years Ago by firstPerson: n/a

Gotta disagree with you firstPerson, or at least disagree with you halfway. I guess I'll start where I agree with you. I agree with you that you should change the function from a void function that sets a global variable to a function that returns the chosen level. The calling function can set the level as it wishes from that return value.

But I think passing the prompt to the function and checking for a valid return value outside of the function is not something desirable. It's better to have the prompt and error checking inside the function unless there is a reason not to. It's a short enough function. It doesn't have much to do, so let it handle the prompt and error checking. All I want to do from main is something like this...

int level = Difficulty();

Edited 5 Years Ago by VernonDozier: Grammar

Yea but the thing is, one might want to handle errors differently. So a better solution would be to create a error handling function and pass in the prompting function, in which the call could possibly look like so :

int level = tryPrompt( Difficulty ,errMsg, 5 ); //tries to prompt 5 times before quiting, displays errMsg if invalid input

in anyway, I feel the error handling should be outside the function for more flexibility.

Edited 5 Years Ago by firstPerson: n/a

I am going to ask about firstPerson's code here. So first some initial thoughts, first I always like to separate output from function, i.e. don't do logic/maths in the same place as you are telling the user what happens or what is wanted. Especially, as often initially you develop going onto the terminal, and later into a GUI or some logging system.

That tells me that int getLevel(const char); look like the correct prototype and use -ve or 0 as a error code. Alternatively, int getDefLevel(const char,const int); , and the second integer is the default level if nothing/junk is entered.


Second I have two comments + a question about firstPerson's code:

int getDifficultyLevel(const char *msg)
{
  const std::string difMap = "EAH";

  // Doesn't this just set ans to zero ???? 
  char ans = 0;        

  // This should have been done outside of the call
  cout << msg;              

  // this returns std::string::npos+1 :
  return difMap.find( toupper(ans) ) + 1; 
}

The first is I don't really think that msg should be a char* but much rather a std::string& since we are using them already.

Second doesn't ans have to come from the calling function?

Finally, [the real reason for posting].

So I cannot decide if I am certain that std::string::npos+1 is ALWAYS equal to zero. Obviously, the method find, returns std::string::npos if there is not match to the find. I found that std::string::npos is beyond the maximum number of characters in a std::string. But I could not find anything saying that it is guaranteed to actually be the max unsigned int that it is in gcc and the portland versions of the std library. Do you know if the standard guarantees that ??

[Apologies in advance, if you think this should have been a new post, not a reply.]

Edited 5 Years Ago by StuXYZ: n/a

Yea there are some bugs in the code, It should be something like this :

size_t getDifficultyLevel(const std::string& msg)
{
  const std::string difMap = "EAH";
 
  // Doesn't this just set ans to zero ????  //Yes it does, but we aren't returns 'ans'
  char ans = 0;        
 
  // This should have been done outside of the call
  cout << msg;              
  cin >> ans;
  int level = difMap.find( toupper(ans) ); 
  return level != string::npos ? level  + 1 : level; 
}

Like I said before, that would be the general approach I would take. I didn't guarantee that the code was bug free. Anyway as for the comment about line 10, it could have definitely been done outside the function call, but to me it seems natural to do it inside the getDifficulty function, else the parameter isn't necessary. Another reason why I left line 10 there is for convenience. If the user wanted to getDifficultLevel again, it would have to cout the message again before calling the getDifficultLevel function. This leaves the chance for the user to forget that he has to print a prompt message before calling that function, whereas it is automated in the function I suggested.

And as for your question, size_t can only take positive values. When you assign it a negative value, because of the way binary works it gets overflowed and thus the number wraps around like a circular wheel. Since stl's set string::npos to be -1, it gets wrapped around and thus becomes the largest possible value a size_t can be. Thus if we add 1 to it, it gets wrapped again, and starts at 0.
Thats the way binary works usually, and I believe thats how it works on all most machines, if not, then the output should be at least the same, regardless of how an architecture develops it. But thats just my thinking, so take it with a grain of salt.

Edited 5 Years Ago by firstPerson: n/a

This article has been dead for over six months. Start a new discussion instead.