Random guessing game stuck - c

I am practicing the basics of C programming using the book SAMS Teach yourself C in 21 days.
On one of the type and run sections, they have the find the number (or guess the number) program, I typed it and run it, however the program on the console gets stuck showing the following:
Getting a random number
I waited for some time but nothing happens, even pushing some keys it doesn't do anything.
I am not familiar yet with the srand(), time() and rand() routines so I don't know how to fix it and make it run properly.
below is the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NO 0
#define YES 1
int main (void)
{
int guess_value = -1;
int number;
int nbr_of_guesses;
int done = NO;
printf("\nGetting a random number\n");
/*use the time to seed the random number generator*/
srand( (unsigned) time(NULL));
number = rand();
nbr_of_guesses = 0;
while (done == NO);
{
printf("\nPick a number between 0 and %d>", RAND_MAX);
scanf("%d", &guess_value); /*get a number*/
nbr_of_guesses++;
if (number == guess_value)
{
done = YES;
}
else
if (number < guess_value)
{
printf("\nYou guessed high!");
}
else
{
printf("\nYou guessed low!");
}
}
printf("\nCongratulations! you guessed right in %d Guesses!", nbr_of_guesses);
printf("\n\nThe number was %d", number);
return 0;
}

I can see 2 problems.
There is a semicolon on the while that's causing the program to hang.
There is nothing that ensures that the output buffer is flushed before you read the guess.
I have put comments to indicate the code changes.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NO 0
#define YES 1
int main (void)
{
int guess_value = -1;
int number;
int nbr_of_guesses;
int done = NO;
printf("\nGetting a random number\n");
/*use the time to seed the random number generator*/
srand( (unsigned) time(NULL));
number = rand();
nbr_of_guesses = 0;
while (done == NO) // Removed the ;
{
printf("\nPick a number between 0 and %d>", RAND_MAX);
fflush(stdout); // stdout is line buffered, and since there is no \n in the printf we need an explicit call to fflush,
scanf("%d", &guess_value); /*get a number*/
nbr_of_guesses++;
if (number == guess_value)
{
done = YES;
}
else
if (number < guess_value)
{
printf("\nYou guessed high!");
}
else
{
printf("\nYou guessed low!");
}
}
printf("\nCongratulations! you guessed right in %d Guesses!", nbr_of_guesses);
printf("\n\nThe number was %d", number);
return 0;
}

Related

Can you Help me correct this simple c program's little mistake?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int num, rnum, times = 1;
srand(4383);
rnum=rand() % 300 + 1;
while(times <=8)
{
printf("Guess the numper random number between 1-300: ");
scanf("%d", &num);
if (num<rnum)
{
printf("The random number is biger\n");
}
if (num>rnum)
{
printf("The magic number is smaller\n");
}
if (num == rnum)
{
printf("RIGHT!");
break;
}
times++;
}
printf("FAILURE!");
return 0;
}
The point of the task is to make a program for a user to type and try to guess a numper from 1–300 with 8 attempts. If you find the number it shows RIGHT! and if not it guides you by telling that the number is biger/smaller. If you fail in your 8 atemts then it shows failure. The problem is that it shows failure when you fail to guess in your 8 atempts but when you find the number it prints both RIGHT & FAILURE. What should i correct for the program to print failure only when you cant’t find the number within your 8 tries?
My 2 cents, path of least resistance is to simply return rather than break when the user guesses correctly:
if (num == rnum)
{
printf("RIGHT!");
return 0; // program exits here, no FAILURE print
}
You should also seed the rand function with a changing number, like time. With a constant, you'll find your number to guess is the same every time.
srand(time(NULL)); // randomize seed
You should check if they exceeding the 8 try limit before executing the print statement:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int num, rnum, times = 1;
srand(4383);
rnum=rand() % 300 + 1;
while(times <=8)
{
printf("Guess the numper random number between 1-300: ");
scanf("%d", &num);
if (num<rnum)
{
printf("The random number is biger\n");
}
if (num>rnum)
{
printf("The magic number is smaller\n");
}
if (num == rnum)
{
printf("RIGHT!");
break;
}
times++;
}
if (times > 8)
{
printf("FAILURE!");
}
return 0;
}
I think you should write return 0; instead of break; after printing RIGHT. because if you guess the rnum it will print RIGHT and breaks out and after that it will print FAILURE too but if you write return 0; it will end the program.
When you break; out after having printed RIGHT! you end up where you print FAILURE! so you need to check this somehow.
Here's my take on it:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int num = 0, rnum;
// This game will get boring with a static seed.
// I'm assuming you use this seed for testing only.
srand(4383);
rnum = rand() % 300 + 1;
for(int times = 0; times < 8; ++times) { // simpler loop
printf("Guess the random number between 1-300: ");
// if the user fails to enter a number - make it print FAILURE
if(scanf("%d", &num) != 1) break;
if(num < rnum)
puts("The random number is bigger");
else if(num > rnum) // added "else"
puts("The magic number is smaller");
else
break; // neither less nor greater than rnum so it must be correct
}
if(num == rnum) // added check
printf("RIGHT!\n");
else
printf("FAILURE!\n");
}

taking the avg in C program

#include <stdio.h>
int main(int argc, char** argv)
{
int n;
int numbers;
int i=0;
int sum=0;
double average;
printf("\nPlease Enter the elements one by one\n");
while(i<n)
{
scanf("%d",&numbers);
sum = sum +numbers;
i++;
}
average = sum/n;
printf("\nSum of the %d Numbers = %d",n, sum);
printf("\nAverage of the %d Numbers = %.2f",n, average);
return 0;
}
i get the output "exited, floating point exception"
im not sure how to fix it.
i found online to add before the while loop
printf("\nPlease Enter How many Number you want?\n");
scanf("%d",&n);
but i dont want that there
Hint: you want the user to be able to signal to your application that they finished entering the elements. So you'd start with n=0 and then increment it each time the user provides a new element, and exit the loop when the user does "something" that you can detect.
For starters, let's say that the user closes the input by pressing Ctrl-Z on Windows, or Ctrl-D on Unix. The input will fail with EOF then - scanf() won't return 1 anymore. So you can check for this:
#include <stdio.h>
int main(int argc, char** argv)
{
int n = 0;
int sum = 0;
printf("\nPlease Enter the elements one by one. ");
#ifdef _WIN32
printf("Press Ctrl-Z to finish.\n");
#else
printf("Press Ctrl-D to finish.\n");
#endif
for (;;)
{
int number;
int result = scanf("%d", &number);
if (result == 1) break;
sum = sum + number;
n ++;
}
double average = (double)sum / n;
printf("\nSum of %d number(s) = %d\n",n, sum);
printf("Average of %d number(s) = %.2f\n",n, average);
return 0;
}
But this also ends the input when anything non-numeric is entered. Due to how scanf() is designed, you need to do something else to skip invalid input - usually by consuming input character-by-character until an end of line is reached. Thus, the variant that would not stop with invalid input, but allow the user another chance, needs to differentiate between scanf() returning EOF vs it returning 0 (invalid input):
#include <stdio.h>
void skip_input_till_next_line(void)
{
for (;;) {
char c;
if (scanf("%c", &c) != 1) break;
if (c == '\n') break;
}
}
int main(int argc, char** argv)
{
int n = 0;
int sum = 0;
printf("\nPlease Enter the elements one by one. ");
#ifdef _WIN32
printf("Press Ctrl-Z to finish.\n");
#else
printf("Press Ctrl-D to finish.\n");
#endif
for (;;)
{
int number;
int result = scanf(" %d", &number);
if (result == EOF) break;
if (result != 1) {
// We've got something that is not a number
fprintf(stderr, "Invalid input. Please try again.\n");
skip_input_till_next_line();
continue;
}
sum = sum + number;
n ++;
}
double average = (double)sum / n;
printf("\nSum of %d number(s) = %d\n",n, sum);
printf("Average of %d number(s) = %.2f\n",n, average);
return 0;
}
As a learner I'd recommend you to think about the pseudo code rather than the actual code.
Answers above are really good. I just want to add few things:
As a programmer you've to teach the hardware what you want it to do. Think:
Have you told your program how many numbers it takes as input? Is it limited or unlimited?
How will your program knows when to stop taking inputs?
I hope you agree that (sum n)/n would throw an error if user
doesn't enter anything or only enters 0?
What will happen if User enters characters instead?
Another important thing is that you need to clearly specify why you don't want to do certain thing in your code? This might help us understand better what are the limitations.
If you think about these things before and ask questions you'll learn better. Community is here to help you.

Program start-over function

I'm a beginner in C programming and i would appreciate if i could get some tips on how to set a program to restart? I'm currently building a guessing game, where the user has 10 attempts to guess the secret number which is provided randomly. I want the program to be able to offer the user a new round of game from start (Attempt number 1 Guess the number:), meaning re-run the program.
Here is the program:
#include <stdlib.h>
#include <time.h>
#define guessLimit 10
int main()
{
int secret_number;
int guess;
int guessCount = 0;
int outofGuesses = 0;
int i;
setbuf(stdout, NULL);
srand(time(0));
secret_number = rand() % 100;
printf("\n---GUESS THE SECRET NUMBER---\n");
for(i=1; i < 11; i++){
printf("Attempt number %d Guess a number: ", i);
scanf("%d", &guess);
if(guess == secret_number){
printf("Correct number!\n");
break;
}
if(guess < secret_number){
printf("sorry, number too small.\n");
}
else if(guess > secret_number){
printf("Sorry, number too big.\n");
}
if(i==10){
printf("Out of Attempts");
}
if(guess>99 || guess<0){
printf("Out of Range.\n");
}
}
return 0;
}
You could encapsulate your for loop in a while loop and have the conditional be an input from the console to indicate the user is done playing.
The best thing to do is to wrap the primary routine within a while loop and use a condition to determine if you want to either repeat or exit the loop. In this case, the do while construct works nicely. Simply ask the user if they would like to play again at the end of the loop. If not, then exit. Otherwise, repeat the code. Be mindful not to call srand(time(0)) within your loop or you reset the random sequence.
#include <stdlib.h>
#include <time.h>
#define guessLimit 10
int main()
{
int secret_number;
int guess;
int guessCount = 0;
int outofGuesses = 0;
int i;
char play;
srand(time(0));
do {
secret_number = rand() % 100;
printf("\n---GUESS THE SECRET NUMBER---\n");
for(i=1; i < 11; i++){
printf("Attempt number %d Guess a number: ", i);
scanf("%d", &guess);
if(guess == secret_number){
printf("Correct number!\n");
break;
}
if(guess < secret_number){
printf("sorry, number too small.\n");
}
else if(guess > secret_number){
printf("Sorry, number too big.\n");
}
if(i==10){
printf("Out of Attempts");
}
if(guess>99 || guess<0){
printf("Out of Range.\n");
}
}
printf("\nPlay again? (y/n): ");
scanf(" %c", &play);
} while (play == 'y');
return 0;
}
As a side note - giving the user 10 chances to guess a number in the range 1-100 is too generous if you're providing "higher/lower" feedback. If my calculations are correct, a binary search would find the answer in maximally log2(100)=6.64... attempts. In other words, you should be able to find the answer in no more than 7 attempts if you know what you're doing. A binary search works of course by guessing the number in between the bounds and then adjusting the bounds according to your feedback.

C random number producing garbage value

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(0));
int random = 0, guess, guesses = 1;
random = rand() % 100 + 1;
printf("The number has been generated. Input 0 to quit.\n");
do {
scanf("%d", &guess); //takes user input for guess
if (guess > random && guess != 0)
printf("Lower!\n");
else
if (guess < random && guess != 0)
printf("Higher!\n");
else
if (guess == random) {
printf("Bingo!");
return 0;
} else
if (guess == 0) {
printf("Thanks for playing, the number was %d\n", &random);
return 0;
}
guesses++;
} while (guesses != 6); //maximum of 5 guesses
printf("Thanks for playing, the number was %d\n", &random);
return 0;
}
Whenever I display the random variable when it has already generated a number a garbage value will be outputted. But the code snippet works of checking the comparison between the guess and the random number, I just can't seem to output the random number correctly.
%d in printf expects an argument of int data type. You are passing int * data type (&random).
Remove & before random in last two printfs.
printf("Thanks for playing, the number was %d\n", random);
You should pass the value of random instead of its address:
printf("Thanks for playing, the number was %d\n", random);
Note also that you should check the return value of scanf(): if you type a letter, the program will have undefined behavior, it may exit after iterating 5 times, or iterate forever or do something else entirely...
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int random, guess, guesses;
srand(time(0));
random = rand() % 100 + 1;
printf("The number has been generated. Input 0 to quit.\n");
for (guesses = 0; guesses < 5; guesses++) {
// take user input for guess
if (scanf("%d", &guess) != 1 || guess == 0)
break;
if (guess > random) {
printf("Lower!\n");
} else
if (guess < random) {
printf("Higher!\n");
} else {
printf("Bingo!\n");
return 0;
}
}
printf("Thanks for playing, the number was %d\n", random);
return 0;
}

Random number generator game in C

I have started C recently and am having trouble make the computer think of a random number.
This is the code so far. I need help!
#include <stdio.h>
#include <stdlib.h>
int main ()
{
time_t t;
int userin;
printf("Guess a number from 1 to 10\n");
scanf("%d", userin);
int r = rand() % 11;
if (r == userin)
{
printf ("you are right");
}
else
{
printf("Try again");
}
return 0;
}
Thx a lot guys it worked out!!!!
In your code, r will be a random number from 0 to 10. For a random number between 1 and 10, do this:
int r = rand() % 10 + 1;
Also, you should call
srand(time(NULL));
at the beginning of main to seed the random number generator. If you don't seed the generator, it always generates the same sequence.
There is issue in your scanf statement as well.
You should use
scanf("%d", &userin);
instead of
scanf("%d", userin); /* wrong - you need to use &userin */
scanf needs the address of variables at which it will store the value. For a variable, this is given by the prefexing the variable with &, as in &userin.
There are few issues in your code.
not reading into the address & of your variable using scanf
not considering "legitimate" values of input, result of rand()%11 can also be 0
not checking against "illegal" input values, which can "alias" the result.
not properly initializing seed of the pseudo-random rand() function, so it always returns the same result.
Using printf for debugging your code, as in the following example, based on your code can help a lot:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DEBG 1
int main (void)
{
time_t t;
int userin;
printf("Guess a number from 1 to 10\n");
if(scanf("%d", &userin) != 1){ // read into the variable's address
printf("Conversion failure or EOF\n");
return 1;
}
if(userin < 1 || userin > 10){ // check against "illegal" input
printf("Offscale, try again\n");
return 1;
}
srand(time(NULL)); // initialize the seed value
int r = 1 + rand() % 10; // revise the formula
if (DEBG) printf("%d\t%d\t", r, userin); //debug print
if (r==userin){
printf ("you are right\n");
}else{
printf("Try again\n");
}
return 0;
}
Please, also consult this SO post.
Problems :
scanf("%d", userin); //you are sending variable
This is not right as you need to send address of the variable as argument to the scanf() not the variable
so instead change it to :
scanf("%d", &userin); //ypu need to send the address instead
and rand()%11 would produce any number from 0 to 10 but not from 1 to 10
as other answer suggests, use :
(rand()%10)+1 //to produce number from 1 to 10
Solution :
And also include time.h function to use srand(time(NULL));
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(NULL));
int userin;
printf("Guess a number from 1 to 10\n");
scanf("%d", &userin);
int r = (rand() % 10)+1;
if (r==userin)
{
printf ("you are right");
}
else
{
printf("Try again");
}
return 0;
}
Why use srand(time(NULL)) ?
rand() isn't random at all, it's just a function which produces a sequence of numbers which are superficially random and repeat themselves over a period.
The only thing you can change is the seed, which changes your start position in the sequence.
and, srand(time(NULL)) is used for this very reason
This should work
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int userIn = 0; //I like to initialize
printf("Guess a number from 1 to 10\n");
scanf("%d", &userIn);
srand(time(NULL)); //seed your randum number with # of seconds since the Linux Epoch
int r = (rand()%10)+1; //rand%11 gives values 0-10 not 1-10. rand%10 gives 0-9, +1 makes sure it's 1-10
if (r == userIn)
{
printf ("you are right\n");
}
else
{
printf("Try again\n");
}
return 0;
}
Edit: You may want to implement code to verify that the user input is in fact an integer.

Resources