I am trying to relearn the C language and thought making small projects would be a good way to do it. The code I wrote works perfectly as intended.
I am just here to see if there are any better practices to be implemented or any code optimization tips would be highly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int random(int N){
srand(time(NULL));
int value = rand() % N;
return value;
}
int play(int turns, int range){
int num = random(range);
while (turns > 0){
printf("You have %d turns left\n", turns);
printf("Guess the number (0-%d): ", range);
int guess;
scanf("%d", &guess);
if (guess == num){
printf("Congratulations! You guessed the correct number!\n");
return 1;
}
else if (guess < num){
printf("Too low. Try again.\n");
turns--;
}
else {
printf("Too high. Try again.\n");
turns--;
}
}
return 0;
}
int main(int argc, char const *argv[])
{
printf("Welcome to the Guessing Game\n");
while (1){
printf("Choose your difficulty:\n For easy enter (1)\n For medium enter (2)\n For difficult enter (3)\n");
int diff;
scanf("%d", &diff);
switch (diff) {
case 1:
if (play(5, 30) != 1) {
printf("Sorry you ran out of Turns\n");
}
break;
case 2:
if (play(3, 50) != 1) {
printf("Sorry you ran out of Turns\n");
}
break;
case 3:
if (play(1, 100) != 1) {
printf("Sorry you ran out of Turns\n");
}
break;
default:
printf("INVALID Difficulty Please try again!\n");
break;
}
printf("Do you want to play again? (y/n): ");
char choice;
scanf(" %c", &choice);
if (choice != 'y'){
printf("Thanks for playing!\n");
break;
}
}
return 0;
}
3 Answers 3
Good re-learning effort.
Bug (kinda)
printf("Guess the number (0-%d): ", range);
implies that 0 to range
is a possible correct answer (or 1 to range - 1
if one views (...)
as not including the endpoints.), yet rand() % range
only makes for that values 0 to range - 1
.
// Suggest
printf("Guess the number [0-%d]: ", range-1);
// or
// int value = rand() % N;
int value = rand() % (N + 1);
Test success of input functions
scanf("%d", &guess);
returns 1 if a number was entered. But what if a non-number was entered? It returns zero. EOF
is also possible.
Check the return value. Does it differ from expectations?
if (scanf("%d", &guess) != 1) {
printf("Input is not numeric. Quitting.\n");
return EXIT_FAILUE;
}
Formatting
Format is OK, yet looks like it was manually done. Use an auto-formatter for efficiency and consistency.
Simplify
else if (guess < num){
is replaceable with if (guess < num){
as the previous if()
block did a return
.
srand()
call only needed once
srand()
is only needed to call once in the life of the program. Commonly this is done early via main()
.
Avoid naked magic numbers
// if (play(1, 100) != 1) {
#define TURNS_DIFFICULT 1
#define RANGE_DIFFICULT 100
...
if (play(TURNS_DIFFICULT, RANGE_DIFFICULT) != 1) {
Avoid very long lines
Use string literal concatenation.
// printf("Choose your difficulty:\n For easy enter (1)\n For medium enter (2)\n For difficult enter (3)\n");
printf("Choose your difficulty:\n"
" For easy enter (1)\n"
" For medium enter (2)\n"
" For difficult enter (3)\n");
Avoid repeated code
Instead of if (play(x, x) != 1) { printf("Sorry you ran out of Turns\n");
3 times, maybe something like
switch (diff) {
case 1: play(5, 30);
break;
case 2: play(3, 50);
break;
case 3: play(1, 100);
break;
default:
printf("INVALID Difficulty Please try again!\n");
break;
}
.. and put the printf("Sorry you ran out of Turns\n");
in play()
?
Minor: punctuation
// printf("INVALID Difficulty Please try again!\n");
printf("INVALID difficulty. Please try again!\n");
Minor: Tolerate either case
// if (choice != 'y'){
if (choice != 'y' && choice != 'Y'){
Also research tolower()
.
-
\$\begingroup\$ Those are some really great suggestions. Thanks for your advice!! \$\endgroup\$Sarthak Hingankar– Sarthak Hingankar2024年08月20日 13:24:44 +00:00Commented Aug 20, 2024 at 13:24
In addition to the good points in the other answer, here are some other things to consider.
Displayed messages
The messages you display to the user make it clear how to play the game and make it easy to follow the progress. The following are some minor improvements.
You should show the correct number (num
) when the user runs out of turns.
You should not display Try again.
when the user runs out of turns.
This message is grammatically incorrect:
You have 1 turns left
You should display turn
:
You have 1 turn left
Portability
There are 101 ways to compile C code. When I use gcc
in my Linux
operating system, I get an error message like the following:
error: conflicting types for 'random'
int random(int N){
^~~~~~
In file included from ,,,
/usr/include/stdlib.h:321:17: note: previous declaration of 'random' was here
extern long int random (void) __THROW;
^~~~~~
The code compiled and ran without errors when I changed the name of the function
from random
to random_int
.
-
2\$\begingroup\$
random()
does not collide with the standard C library. It is colliding with (common) extensions employed by gcc. If OP compiled without these extensions, no conflict. Still a userrandom()
is asking for trouble. \$\endgroup\$chux– chux2024年08月20日 02:31:50 +00:00Commented Aug 20, 2024 at 2:31
Do not use scanf()
for user input:
Checking the return value alone does not suffice. If the converted input is larger than the maximum value of an int
, the behavior would be undefined.
I would suggest reading the input as a string and then converting it with sscanf()
/strtol()
et cetera.