I have this program to write thats a guessing game. the user specifies the amount of rounds and only 5 attempts per round is allowed a round is over when the user guesses correctly or the number of attempts are up. A Message is displayed to inform the user whether he/she is cold, hot or warm based on a certain criteria:

#include <stdio.h> 
#include <stdlib.h>

/*Funtion Prototypes*/

int genRandom(void);


int main(void)

{
/*Declare variables*/

int rounds;
int ranNum;
int guess;
int attempts=5;
int score;


printf("\nEnter the desired number of rounds\n");
scanf("%d",&rounds);

  
do{ 
  ranNum=genRandom();/*Call random function*/

  printf("Your rannum is %d\n", ranNum);

  do{
  printf("Guess the value of the random number\n");
  scanf("%d",&guess);

 if(guess>100)
  {
   printf("Invalid!!!Your source base must be less than 100\n\n");

  }
   
  attempts=attempts-1;


 if (ranNum==guess)
{
   printf("Congratulations,You are correct!\n"); 

}


if ((ranNum-guess) >40)
{
   printf("You are Cold\a\n");
}
else if (10<=(ranNum-guess)<=40)
{	
   printf("You are Warm\a\n"); 

}
else if ((ranNum-guess) < 10)
{
   printf("You are Hot!\a\n");

}
  }while(attempts!=0);

}while(rounds!=0);


score=5*(5-attempts);

printf("Your score is %d\n", score);

}/* end of main*/

int genRandom(void)
{
  return rand()%100;
}

1. How do I work with only absolute or positive values for my criteria (say number is less than guess)
2. I want to break out of the loop when the guess is correct or when the attempts are up.

Some points:

  • To guarantee that a particular integer will always be postive (absolute), declare it as an unsigned int .
  • You check to see if the value the user entered was larger than 100, but you never checked if it was smaller than 0.
  • You can use break to jump out of a loop if you need to, although a better way would be simply to keep checking the value of a boolean variable which represents if it's time to exit the loop.
  • This statement makes no sense:
    if (10<=(ranNum-guess)<=40)

    Since you already checked that the difference is smaller than 40, just check that the difference isn't smaller than 10.

  • Proper code indentation is a code habit to practice. Many editors have a built-in feature, so you don't even have to think about it. And it makes code much easier to read and understand.

Some points:

  • To guarantee that a particular integer will always be postive (absolute), declare it as an unsigned int .

  • what if I typecast it
((unsigned int)(ranNum-guess) >40)
  • You can use break to jump out of a loop if you need to, although a better way would be simply to keep checking the value of a boolean variable which represents if it's time to exit the loop.

  • Do you mean like if (attempts>0=1&&rounds>0=1) ?


Proper code indentation is a code habit to practice. Many editors have a built-in feature, so you don't even have to think about it. And it makes code much easier to read and understand.

I been trying to work on my indentation and I thought I was getting better can you suggest a good code editor that would help?

Thanks.

here is the revised code

#include <stdio.h> 
#include <stdlib.h>

/*Funtion Prototypes*/
int genRandom(void);

int main(void)

{
/*Declare variables*/

int rounds;
int ranNum;
int guess;
int attempts=5;
int score;


printf("\nEnter the desired number of rounds\n");
scanf("%d",&rounds);
do{
ranNum=genRandom();/*Call random function*/
--rounds;
  do{
printf("Guess the value of the random number\n");
scanf("%d",&guess);
--attempts;

		if((guess>100)||(guess<0))
		{
		  printf("Invalid!!!your number must less than 100 or more than 0\n\n");
		continue;
		}
   
		if (ranNum==guess)
		{
	      printf("Congratulations,You are correct!\n"); 
		break;
		}
		
		if ((unsigned int)(ranNum-guess) >40)
		{
	      printf("You are Cold\n");
		}
		else if (10<=(unsigned int)(ranNum-guess))
		{	
	      printf("You are Warm\n"); 
		}
		else if ((unsigned int)(ranNum-guess) < 10)
		{
		  printf("You are Hot!\n");
		}
	}while(attempts!=0);
 }while(rounds!=0);

score=5*(5-attempts);

printf("Your score is %d\n", score);

}/* end of main*/

int genRandom(void)
{
  return rand()%100;
}

The score is noncumulative and is suppsed to show at the end of each round

You are getting incorrect output since you fail to reset the attempts value to 5 again i.e. at the end of the nested do while loop, set the value of attempts again to 5.

Also it is better to decrement the value of attempts at the end of the second do while loop, only after the successful completion of the loop since you seem to be using continue.

And btw, read this thread for getting a good IDE.

Thanks a bundle. It works now except when I'm correct I can't break out of the loop and print the score, also It isn't starting another round after the failed attempts.

Thanks a bundle. It works now except when I'm correct I can't break out of the loop and print the score, also It isn't starting another round after the failed attempts.

Hmm... the "break" statement works fine for me, except that you aren't calculating the score correctly. You should calculate the score right after the round finishes, and before you reset the attempts.

Like this:

}while(attempts!=0);
        score+=5*(5-attempts);

Notice that I put += instead of just =, since the score is supposed to be accumlative. Which means you're going to have to initalize score at the beginning of your program.

You may want to print a "you failed" message before the round ends so that the user knows that he/she ran out of attempts, and additionally, print out the number of attempts remaining after each guess.

I been trying to work on my indentation and I thought I was getting better

Here's a tutorial about code formatting. Concentrate on whitespace as well as indentation. A differnt IDE won't do it all for you, and knowing how to format is extremely important.

Thanks a bundle. It works now except when I'm correct I can't break out of the loop and print the score, also It isn't starting another round after the failed attempts.

Post the updated code so I can see what you have come up with...

#include <stdio.h> 
#include <stdlib.h>

/*Funtion Prototypes*/
int genRandom(void);

int main(void)

{
/*Declare variables*/

int rounds;
int ranNum;
int guess;
int attempts=5;
int score;


printf("\nEnter the desired number of rounds\n");
scanf("%d",&rounds);
do{
ranNum=genRandom();/*Call random function*/
--rounds;
  do{
printf("Guess the value of the random number\n");
scanf("%d",&guess);


		if((guess>100)||(guess<0))
		{
		  printf("Invalid!!!your number must less than 100 or more than 0\n\n");
		continue;
		}
   
		if (ranNum==guess)
		{
	      printf("Congratulations,You are correct!\n"); 
		break;
		}
		
		if ((unsigned int)(ranNum-guess) >40)
		{
	      printf("You are Cold\n");
		}
		else if (10<=(unsigned int)(ranNum-guess))
		{	
	      printf("You are Warm\n"); 
		}
		else if ((unsigned int)(ranNum-guess) < 10)
		{
		  printf("You are Hot!\n");
		}
		--attempts;
	}while(attempts!=0);

	score+=5*(5-attempts);
  attempts=5;

 }while(rounds!=0);

printf("Your score is %d\n", score);

}/* end of main*/

int genRandom(void)
{
  return rand()%100;
}

Now I'm going on infinitely instead of breaking after five attempts. A noncumulative score has to be displayed at the end of each round but once the rounds are up a cumulative score is then displayed.

You need to initialize the score variable to zero. If you want to print out the score after each round, print the score at the end of the inner while loop.

I don't see as such something wrong with your code other that those mentioned by me...

I decided to be a beta tester of you code :)

This is the output of the test.

Enter the desired number of rounds
3
The random number is 41
Guess the value of the random number
2
You are Warm
Guess the value of the random number
3
You are Warm
Guess the value of the random number
4
You are Warm
Guess the value of the random number
5
You are Warm
Guess the value of the random number
6
You are Warm
The random number is 67
Guess the value of the random number
7
You are Cold
Guess the value of the random number
8
You are Cold
Guess the value of the random number
9
You are Cold
Guess the value of the random number
10
You are Cold
Guess the value of the random number

Right after the generation of the random number in the first do{}while loop I included a printf for debugging to see what the number generated was. That's the 41 you see. And look at the warn/ cold algorithm. It doesn't make sense.
Most like you would have to double check the logic behind it, again.

Also, you don't need to add (unsigned int) to every statement after the if,
you could just added to the function like this:

int genRandom(void)
{
  return (unsigned) rand()%100;
}

By the way, I think your code is a perfect candidate for a switch instead of
all those if and if else.

if ((unsigned int)(ranNum-guess) > 40)

The unsigned int is necessary. Let me show you an example. Let's say that the random number was 50, and the guess was 100.
ranNum-guess would then equal -50, which is NOT what we want. We want how far away the guess is from the random number, not the exact difference (plus or minus).


By the way, I think your code is a perfect candidate for a switch instead of
all those if and if else.

I want to correct myself. A switch would not work here since the evaluation in a switch has to be iquals to a integer expression and not conditional.

However I want to point some things in your code. I commented.

#include <stdio.h> 
#include <stdlib.h>

/*Funtion Prototypes*/
int genRandom(void);

int main(void)
{
/*Declare variables*/

    int rounds;
    int ranNum;
    int guess;
    int attempts=5;
    int score;


    printf("\nEnter the desired number of rounds\n");
    scanf("%d",&rounds);
    do{
        ranNum=genRandom();/*Call random function*/
        --rounds;
          do{
            printf("Guess the value of the random number\n");
            scanf("%d",&guess);


            if((guess>100)||(guess<0))
            {
                printf("Invalid!!!your number must less than 100 or more than 0\n\n"); /* zero is not excluded, zero is a posibility */
                  continue;
            }
   
            if (ranNum==guess)
            {
                printf("Congratulations,You are correct!\n"); 
                  break;
            }
        
            if ((unsigned int)(ranNum-guess) >40) /* lest's say ranNum-guess is 45. 45 is greater than 40. This statement applys */
            {
                  printf("You are Cold\n");
            }
            else if (10<=(unsigned int)(ranNum-guess)) /* if ranNum-guess is 45, 10 is less or iquals to 45. This statement applays too */
            {    
                  printf("You are Warm\n"); 
            }
            else if ((unsigned int)(ranNum-guess) < 10) /* ranNum-guess is 45, 45 is less than 10?. No. */
            {
                printf("You are Hot!\n");
            }
            --attempts;
        }while(attempts!=0);

        score+=5*(5-attempts);
          attempts=5;

    }while(rounds!=0);

    printf("Your score is %d\n", score);

}/* end of main*/

int genRandom(void)
{
  return rand()%100;
}

I don't know if you have noticed but every time you execute this
code the same random numbers ocurre. This happens because there
is nothing random for a computer. To work around this problem you could generate a seudo-random number using the time in your computer as a seed.

here's my take of your genRandom function:

int genRand()
{
     int number;
     
     srand ((unsigned) time(NULL)); /* seed using computer time */
     number = (rand() % 100) + 1; /* this will create a number from 1 to 100, and not from 0 to 99 like before */
     return number;
}
if ((unsigned int)(ranNum-guess) >40) /* lest's say ranNum-guess is 45. 45 is greater than 40. This statement applys */

Why is that incorrect? If the guess was 45 off the random number, of course it should print cold! If the difference is less than 40 the statement is not printed, which is correct.

else if (10<=(unsigned int)(ranNum-guess)) /* if ranNum-guess is 45, 10 is less or iquals to 45. This statement applays too */

True, but you forgot that this is an else if() statement. If the difference was larger than 40, it would have been caught in the first expression. Since we know that the difference is less than 40, we don't have to test for it multiple times.

else if ((unsigned int)(ranNum-guess) < 10) /* ranNum-guess is 45, 45 is less than 10?. No. */

No, but that is also correct. A difference of less than 10 would mean that the user is very close. It's appropriate to print out such a statement.

I don't know if you have noticed but every time you execute this
code the same random numbers ocurre. This happens because there
is nothing random for a computer. To work around this problem you could generate a seudo-random number using the time in your computer as a seed.

here's my take of your genRandom function:

int genRand()
{
     int number;
     
     srand ((unsigned) time(NULL)); /* seed using computer time */
     number = (rand() % 100) + 1; /* this will create a number from 1 to 100, and not from 0 to 99 like before */
     return number;
}

Don't do it like that. You only need to seed the random number generator at the top of the program, seeding it multiple times is unnecessary and usually leads to nonrandom numbers.

Why is that incorrect? If the guess was 45 off the random number, of course it should print cold! If the difference is less than 40 the statement is not printed, which is correct.

True, but you forgot that this is an else if() statement. If the difference was larger than 40, it would have been caught in the first expression. Since we know that the difference is less than 40, we don't have to test for it multiple times.

No, but that is also correct. A difference of less than 10 would mean that the user is very close. It's appropriate to print out such a statement.

I was not say it was wrong. I was pointing out the logic and perhaps the fact that the first two over-lapped.

However I think I would do it like:

if ((ranNum-guess) >= 40)
           {
               printf("You are Cold\n");
           }
           else if ((ranNum-guess) > 10 && (ranNum-guess) < 40)
           {    
               printf("You are Warm\n"); 
           }
           else if ((ranNum-guess) <= 10)
           {
               printf("You are Hot!\n");
           }

Don't do it like that. You only need to seed the random number generator at the top of the program, seeding it multiple times is unnecessary and usually leads to nonrandom numbers

Good to know about that little quirck ;)

> However I think I would do it like:

That's redundant. It won't affect performance in a little program like this, but there are certain assumptions you should get into the habit of making, and this is one of them. The only way the else if() statement executes is if the if() statement evaluated as false.

Also, you forgot to use (unsigned int) casts in your expressions, so it would evaluate incorrectly.

Also, you forgot to use (unsigned int) casts in your expressions, so it would evaluate incorrectly.

I don't need (unsigned int) if I'm using it at the function level. Don't I?

srand ((unsigned) time(NULL));

I don't need (unsigned int) if I'm using it at the function level. Don't I?

Did you read my previous post?

The issue here is not that the generated number is positive (although it should be positive), the thing is that the difference between the random number and the guess has to be positive in order for the expressions to work properly.

The OP realized this, and that is why this thread was created.


The issue here is not that the generated number is positive (although it should be positive), the thing is that the difference between the random number and the guess has to be positive in order for the expressions to work properly.

I stand corrected. Thank you. :cheesy:

I forgot to mention that if you deside to use srand ((unsigned) time(NULL)); at the begining of the code, to seed the generator of random number you need #include <time.h> .

A use of cast to unsigned int would be a poor choice to make, especially when there are inbuilt functions which does the same thing as [search]abs[/search]. Using standard functions is much better a choice over the unsafe and buggy casts.

Ok, so I should have mentioned that the random function was provided so I can't change it so were the condition for the messages. I added the score after the inner while loop and it works like a charm though I don't fully understand the logic behind the hot and cold messages. if the number generated it 41 and I choose 45 shouldn't that be hot?

Ok, so I should have mentioned that the random function was provided so I can't change it so were the condition for the messages. I added the score after the inner while loop and it works like a charm though I don't fully understand the logic behind the hot and cold messages. if the number generated it 41 and I choose 45 shouldn't that be hot?

I hope I didn't confuse you. All that I was trying to point out was, that I noticed in your second code posted, these lines of code would overlap for some values.

if ((unsigned int)(ranNum-guess) >40) /* lest's say ranNum-guess is 45. 45 is greater than 40. This statement applys */
            {
                  printf("You are Cold\n");
            }
            else if (10<=(unsigned int)(ranNum-guess)) /* if ranNum-guess is 45, 10 is less or iquals to 45. This statement applays too */
            {    
                  printf("You are Warm\n"); 
            }

And I used 45 as an example, to show that it would be applicable for both if statements, in fact any number higher than 40 would be applicabe to both statements. However as joeprogrammer said: 45 would hit the first if statement and would not have a chance of being analized by the else if, even when that one would accept it as true.

That said: I still think that it would be better if the logic could be written more exact. It doesn't take much. Something like:

/*
 *  Modified by me from
 *    boujibabe @ Doniweb.com
 *    myguess.c
 */

#include <stdio.h> 
#include <stdlib.h>

/*Funtion Prototypes*/
int genRandom(void);

int main(void)
{
/*Declare variables*/
    int rounds;
    int ranNum;
    int guess;
    int attempts=5;
    int score = 0;

    printf("\nEnter the desired number of rounds\n");
    scanf("%d",&rounds);

    do
    {
       ranNum=genRandom();/*Call random function*/
       printf("The random number is %d\n\n", ranNum); /* for debugging purposes delete after everything works*/
       --rounds;
       do
       {
           printf("Guess the value of the random number\n");
           scanf("%d",&guess);

           if((guess>100)||(guess<0))
           {
               printf("Invalid!!!Please enter a number between 0 and 99\n\n");
               continue;
           }
               
           if (ranNum==guess)
           {
               printf("Congratulations,You are correct!\n"); 
               break;
           }
           
           int abs_number = abs(ranNum-guess); /* converts the difference in an absolute number */
           
           if (abs_number >= 40)
           {
               printf("You are Cold\n");
           }
           else if (abs_number <= 10)
           {
               printf("You are Hot!\n");
           }
           else
           {    
               printf("You are Warm\n"); 
           }
           
           
           --attempts;

        }
        while(attempts!=0);
        printf("round %d finished, ", rounds); /* let us know when the rounds finished. Debugging line */
        score += 5*(5 - attempts); 
        printf("score = %d\n", score);

        attempts=5;

    }
    while(rounds!=0);

    printf("Your score is %d\n", score);
    
   return(0);

}/* end of main*/

int genRandom(void)
{
    return (unsigned) rand()%100;
}

Btw, I don't know exactly what you try to do with the score, but I noticed that if you guess the number at the first try your score is 0
and it seems to work properly as long as you enter in the many attempts.

I don't fully understand the logic behind the hot and cold messages. if the number generated it 41 and I choose 45 shouldn't that be hot?

You're confusing the guess and the difference. The difference is what we were talking about. So, the absolute value difference is 41-45 = 4, so the guess would be hot.

That said: I still think that it would be better if the logic could be written more exact. It doesn't take much. Something like:

if (abs_number >= 40)
           {
               printf("You are Cold\n");
           }
           else if (abs_number <= 10)
           {
               printf("You are Hot!\n");
           }
           else
           {    
               printf("You are Warm\n"); 
           }

I disagree completely. It's much harder to read, and there wasn't anything wrong with the previous method. Let's say you had to do a longer list:

if (number > 100)
    printf("Number is larger than 100.\n");

else if (number > 90)
    printf("Number is between 90 and 100.\n");

else if (number > 80)
    printf("Number is between 80 and 90.\n");

else
    printf("Number is less than 80.\n");

Now it's hard for me to imagine how you could write this any differently, and it sure is confusing the way you wrote it: cold statement, hot statement, warm statement. You might as well just throw your code around and see where the lines end up.

No. The best way to write code is to make it organized and logical, and you can start doing that by printing out statements in a somewhat-logical order.

Btw, I don't know exactly what you try to do with the score, but I noticed that if you guess the number at the first try your score is 0
and it seems to work properly as long as you enter in the many attempts.

A logical formula for score can be something like: score += 5 * attempts ; Also for generating good random numbers see this.

Comments
Great information about random numbers

The formula for the score was given as

score = 5 * (total amount of attempts allowed - actual amount of attempts taken)

where the total amount allowed is 5 so if i guess right on the first try the actual amount taken should be 0 making the maximum score 25

So if you want to keep your formula unchanged, just initialize the attempts variable to 1 instead of 5, increment the variable instead of decrementing it.

Something like:

const int MAX_ATTEMPTS = 5 ;
int attempts = 1 ;

while (attempts <= 5)
{
    // your code
    ++attempts ;
}
score += (MAX_ATTEMPTS - attempts) ;

The formula for the score was given as

score = 5 * (total amount of attempts allowed - actual amount of attempts taken)

where the total amount allowed is 5 so if i guess right on the first try the actual amount taken should be 0 making the maximum score 25

if guess is correct at:

first try --> score = 5 * (5 - 5) = 0 points
second try--> score = 5 * (5 - 4) = 5 points
thirt try --> score = 5 * (5 - 3) = 10 points
fourth try --> score = 5 * (5 - 2) = 15 points
fifth try --> score = 5 * (5 - 1) = 20 points

if your intent is reward more points for doing worst in the guess, that's what you have in a sigle round. ;)
Futhermore if the score is not cleared to zero after each round the score is accumulative with the preview round. Which I don't know if that's what you want. Is all up to what you are trying to show. :)

One last thing, how would i display a cumulative score at the end of all of the rounds?

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