Hi, I have a programming project in which I have to create a game where the user can select the upper bound of numbers and difficulty they want and then guess the secret number within that bound and difficulty.
So far, this is my code. It compiles and allows the user to select the upper bound.
However, I am having trouble adding difficulty levels to my game. The difficulty levels limit the number of guesses the user has: easy giving 20 guesses, medium giving 10, hard giving 5.
The user must be able to choose the difficulty as a command line parameter. Thus if the program is run as "./guess -d easy" it will play the easy mode. Does anyone have any ideas on how I should do this?

I tried doing an if statement with:
if (argc=='easy') but I don't know where to go from there.
or a for loop with:
for (int guesses=10; guesses <=10; guesses--) but it doesn't work.

#include <iostream>
#include <time.h>
#include <cmath>
using namespace std;
int main(int argc, char **argv)
{
	cin >> argc;
	if (argc== argc)
		do {

	int secret_number;
	int guesses;
	int user_guess;
	srand ( time(NULL) );
	int upper_bound=argc;
	secret_number= rand () % upper_bound;
	cout << secret_number;
	do
	{
	cout << "I'm thinking of a number between 0 and " << upper_bound <<". Can you guess it?" << endl;
	cin >> user_guess;
	if (user_guess>secret_number)
		cout << "I'm thinking of a smaller number. Please try again" << endl;

	else if (user_guess<secret_number)
		cout << "I'm thinking of a larger number. Please try again" << endl;
	}
	while (user_guess!=secret_number);
		cout << "Correct! You guessed the secret number!" << endl;
		return 0;
}
while (argc==argc);

}

Thanks

OK, from the top...

You should use #include <cmath> , not #include <math.h> . The latter is what you'd do in C, not C++. argc stores the number of parameters passed on the command line, not the actual parameters, these are passed in argv . So, in this case you can see that a statement like argc == 'easy' will never make sense, since argc is an int . Additionally, the single quotes indicate a char , which is basically a single letter, not a string of letters. To indicate a string, use double quotes, like

char myChar = 'e';        /* single character*/
char myString[] = "easy"  /* string of characters */

In this context if(argc == argc) is not really what you want, since this will always be true.

To do what you want to do (i.e. get arguments from the command line) you need a loop that looks like:

for(unsigned i = 0; i < argc; i++){
    /* Check through things in argv here */
}

This can go through the things passed on the command line one-by-one and do what you want with them. The other thing to remember about things passed through the command line is that argv is defined as char **argv (although I don't know if this has to be the case). So, if you want to get a number that you can use from it, you need to convert from a C-style string to a number. A simple way to do this is using atoi() or atof() , so something like:

#include <iostream>

int main(int argc, char **argv){
    int myNumber = ( argc > 1 ? atoi(argv[1]) : 0 );
    std::cout << "number = " << myNumber << std::endl;
    return 0;
}

This sets myNumber to the second argument passed on the command line (we start counting at zero and, if you're writing a simple terminal application, the first argument is the program name), if there's no argument passed, it's set to zero.

To set the number of guesses (decided from the command line arguments) then you were right to think you needed a for loop, something like:

int allowedGuesses = 10;
for(int i = 0; i < allowedGuesses; i++){
    /* have game here */
}

Hope that get you started on the right track.

Edited 5 Years Ago by ravenous: made text clearer

You're using the argc all wrong.

The int main initialization as shown:

int main(int argc, char ** argv)

Assigns the numbers of arguments in the console during the executing to argc and creates an array of arrays of characters (basically an array of strings) containing each argument, the 0th array being the file name itself.

Examine:

#include<iostream>


int main(int argc, char * argv []) //This does the same thing, but is more clear.
{
 std :: cout << argv[0] << std::endl; 
 return 0;
}

Save, compile and run this.

With this knowledge hopefully your goal will seem a little simpler.

Er, isn't that what I said?

It seems that way, I hit reply before you edited your post to include that, however. Your post wasn't updated until after I submitted my post.

thanks for the thorough response ravenous and red goose.

I have a quick question regarding your reply ravenous, when you said:

/* Check through things in argv here */

what exactly do you mean? I'm confused as to how I check things through.
Thanks!

thanks for the thorough response ravenous and red goose.

I have a quick question regarding your reply ravenous, when you said:

/* Check through things in argv here */

what exactly do you mean? I'm confused as to how I check things through.
Thanks!

argv[] is an array. Check argv[1], then argv[2], and so on until you run out, based on the value of argc.

regarding the

int main(int argc, char **argv){
int myNumber = ( argc > 1 ? atoi(argv[1]) : 0 );
std::cout << "number = " << myNumber << std::endl;
return 0;
}

I set

myNumber

to

upper_bound

because I use the number input from the user as the upper bound of the guessing game.
When I put it into my code, the part giving me trouble is:

int upper_bound = ( argc > 1 ? atoi(argv[2]) : 100 );
	int secret_number;
	int user_guess;
	srand ( time(NULL) );
	secret_number= rand () % upper_bound;
	cout << secret_number;
	do
	{
	cout << "I'm thinking of a number between 0 and " << upper_bound <<". Can you guess it?" << endl;

the program runs but doesn't give a chance for the user to input an upper bound of their choice, it automatically defaults to 100. How do I allow the program to wait for the user to input a number to set the bound to, and if no number is set then and only then default to 100?

the program runs but doesn't give a chance for the user to input an upper bound of their choice, it automatically defaults to 100. How do I allow the program to wait for the user to input a number to set the bound to, and if no number is set then and only then default to 100?

From the code that you have put in your last post, you tried to set upper_bound from the command line, since you do

int upper_bound = ( argc > 1 ? atoi(argv[2]) : 100 );

(actually, you have used argv[2] , when I think you meant to use argv[1] ). However, I think in your original post, you wanted to set the difficulty level via the command line, using a -d switch. So I think you may have got a little confused somewhere. If you want the user to set upper_bound by a user input, then somewhere in your code, you need to do something like

std::cout << "Enter upper limit" << std::endl;
std::cin >> upper_bound;

For different difficulty levels, you might have different number of guesses so, after the above code, you might have a for loop that asks the user to enter their guesses:

int userGuess;
for(unsigned i = 0; i < allowedGuesses; i++){
    std::cout << "Take a guess!" << std::endl;
    std::cin >> userGuess;
    
    if(userGuess == number){
        std::cout << "Congratulations!" << std::endl;
        break;
    }    
}

This a very basic code, with a number of problems that I'll leave up to you to solve. For example, you might want the first time that it prints out the instruction to be different from the subsequent times (i.e. it could say "OK, take a guess!" the first time, but something like "Bad luck! Try again." on the subsequent times). Or, you might want it to give "higher/lower" type hints between guesses.

OK, to get the difficulty level from the command line, you'll need to loop through argv[] to look for -d and then get the next element of argv[] after that. This is much easier simpler to code with std::string than it is with a C-style char array, so something like

char argument[256];
unsigned allowedGuesses = 10;
for(unsigned i = 1; i < argc; i++){
    for(unsigned j = 0; j < 256; j++)
        argument[j] = '\0';
    strcpy(argument,argv[i]);
    if(!strcmp(argv[i], "-d") && argc > i + 1){
        if(!strcmp(argv[i + 1],"easy"))
            allowedGuesses = 20;
        else if(!strcmp(argv[i + 1],"hard"))
            allowedGuesses = 5;
        break;
    }
}

I haven't tested this, so you might have to correct some bits, but that's the general idea.

You'd probably want to do this near to the start of the program (I tend to get command line options fairly near to the start usually, but I think that's just personal preference. Anyway, have a go at putting all that together and see how you go. If you don't know what any of the functions do then it's fairly easy to look them up on the internet (I find cplusplus.com a really good reference, as they have example code for all the functions there. eg. find out about strcmp() here).

Sorry, just realised that you can do

memset(argument,'\0',256);

instead of

for(unsigned j = 0; j < 256; j++)
    argument[j] = '\0';

on lines 4 & 5 of the final code snippet. Always nice to save a line of code!

I also went on about using std::string and then proceeded to use a char array, so sorry about any confusion there! I shouldn't respond to forum threads before breakfast :)

Edited 5 Years Ago by ravenous: Added extra explanation

Always nice to save a line of code!

Not always -- not if it makes the code harder to read.

for(unsigned j = 0; j < 256; j++)
    argument[j] = '\0';

is far superior to

memset(argument,'\0',256);

The former shows exactly what's going on in the context of the program.

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