My C Blackjack program got stuck [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define CARD_MAX 52
typedef int Deck[CARD_MAX];
Deck deck;
int cardnumber = 0;
int playerwin = 0, dealerwin = 0, tie = 0;
int game();
void setupDeck(Deck deck);
void shuffleDeck(Deck deck);
void printCard(int card);
int pickCard(Deck deck, int cardnum);
void endProgram();
void playAgain();
main()
{
char yn;
srand(time(NULL));
setupDeck(deck);
shuffleDeck(deck);
again:
printf("Welcome! Do you wanna try your luck in a Blackjack Game? If so type 'y'.\n");
printf("If not type 'n' to close the program: ");
scanf_s("%c", &yn);
getchar();
if (yn == 'y')
game();
else if (yn == 'n')
{
printf("Looks like you aren't feeling lucky today! Comeback tomorrow!\n");
system("pause");
}
else
{
printf("Unknown character! Try again!\n");
goto again;
}
}
int game()
{
int card, cardvalue = 0, cardtype = 0, tcvp = 0, tcvd = 0;
int aceflagp = 0, faceflagp = 0, aceflagd = 0, faceflagd = 0, bjp = 0, bjd = 0;
int loopcounter;
char hitorpass;
system("cls");
printf("Your cards:\n");
for (loopcounter = 0; loopcounter < 2; loopcounter++)
{
card = pickCard(deck, cardnumber);
cardnumber++;
cardvalue = card % 13;
cardtype = card / 13;
printCard(cardvalue, cardtype);
if (cardvalue == 1)
{
aceflagp++;
cardvalue = 11;
}
else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
{
faceflagp = 1;
cardvalue = 10;
}
else
cardvalue = cardvalue;
tcvp += cardvalue;
}
if (aceflagp == 1 && faceflagp == 1)
bjp = 1;
printf("Dealers cards:\n");
card = pickCard(deck, cardnumber);
cardnumber++;
cardvalue = card % 13;
cardtype = card / 13;
printCard(cardvalue, cardtype);
if (cardvalue == 1)
{
aceflagd++;
cardvalue = 11;
}
else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
{
faceflagd = 1;
cardvalue = 10;
}
else
cardvalue = cardvalue;
tcvd += cardvalue;
card = pickCard(deck, cardnumber);
cardnumber++;
cardvalue = card % 13;
cardtype = card / 13;
if (cardvalue == 1)
{
aceflagd++;
cardvalue = 11;
}
else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
{
faceflagd = 1;
cardvalue = 10;
}
else
cardvalue = cardvalue;
tcvd += cardvalue;
if (aceflagd == 1 && faceflagd == 1)
bjd = 1;
if (bjp == 1 && bjd == 1)
{
printf("Both sides has Blackjack! Tie!\n");
tie++;
playAgain();
}
else if (bjp == 1)
{
printf("Player Blackjack!\n");
playerwin++;
playAgain();
}
else if (bjd == 1)
{
printf("Dealer Blackjack!\n");
dealerwin++;
playAgain();
}
printf("Your card total is %d.\n", tcvp);
again:
printf("If you want to hit type 'h'. If you want to pass type 'p'");
scanf_s("%c", &hitorpass);
getchar();
if (hitorpass == 'h')
{
card = pickCard(deck, cardnumber);
cardnumber++;
cardvalue = card % 13;
cardtype = card / 13;
printCard(cardvalue, cardtype);
if (cardvalue == 1)
{
aceflagp++;
cardvalue = 11;
}
else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
{
faceflagp = 1;
cardvalue = 10;
}
else
cardvalue = cardvalue;
tcvp += cardvalue;
if (tcvp > 21)
{
if (aceflagp > 0)
{
tcvp -= 10;
aceflagp--;
printf("Your card total is %d.\n", tcvp);
goto again;
}
else
{
printf("Your hand busted. You lost!\n");
dealerwin++;
playAgain();
}
}
else if (tcvp == 21)
{
printf("You have 21 in your hand can't hit more!\n");
goto dealersturn;
}
else if (tcvp < 21)
{
printf("Your card total is %d.\n", tcvp);
goto again;
}
}
else if (hitorpass == 'p')
{
dealersturn:
printf("Dealers turn:\n");
if (tcvd < 17)
{
card = pickCard(deck, cardnumber);
cardnumber++;
cardvalue = card % 13;
cardtype = card / 13;
printCard(cardvalue, cardtype);
if (cardvalue == 1)
{
aceflagd++;
cardvalue = 11;
}
else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
{
faceflagd = 1;
cardvalue = 10;
}
else
cardvalue = cardvalue;
tcvd += cardvalue;
if (tcvd > 21)
{
if (aceflagd > 0)
{
tcvd -= 10;
aceflagd--;
goto dealersturn;
}
else
{
printf("Dealers has a total of %d. Dealers hand busted!\n", tcvd);
playerwin++;
playAgain();
}
}
else if (tcvd < 17)
goto dealersturn;
else
{
if (tcvp > tcvd)
{
printf("Player has %d, dealer has %d. Player won!", tcvp, tcvd);
playerwin++;
playAgain();
}
else if (tcvp == tcvd)
{
printf("Both player and the dealer has %d. Tie!", tcvd);
tie++;
playAgain();
}
else
{
printf("Player has %d, dealer has %d. Dealer won!", tcvp, tcvd);
dealerwin++;
playAgain();
}
}
}
}
else
{
printf("Unknown character. Try again!");
goto again;
}
system("pause");
}
void endProgram()
{
printf("Thanks for playing my blackjack game! The results are:\n");
printf("Player won %d times!\n", playerwin);
printf("Dealer won %d times!\n", dealerwin);
printf("There have been a tie %d times!\n", tie);
system("pause");
}
void playAgain()
{
char chardummy;
again:
printf("Would you like to play again? Type 'y' for Yes and 'n' for No.\n");
scanf_s("%c", &chardummy);
getchar();
if (chardummy == 'y')
{
if (cardnumber >= 48)
{
printf("There is not enough card left in the deck!");
endProgram();
}
else
game();
}
else if (chardummy == 'n')
endProgram();
else
{
printf("Unknown character. Try again!");
goto again;
}
}
void setupDeck(Deck deck)
{
int i;
for (i = 0; i<CARD_MAX; i++)
{
deck[i] = i;
}
}
void shuffleDeck(Deck deck)
{
for (int i = 52 - 1; i >= 0; --i) {
int r = rand() % (i + 1);
int t = deck[i];
deck[i] = deck[r];
deck[r] = t;
}
}
void printCard(int cardvalue, int cardtype)
{
char cardtype2;
if (cardtype == 0)
cardtype2 = 'C';
else if (cardtype == 1)
cardtype2 = 'D';
else if (cardtype == 2)
cardtype2 = 'H';
else if (cardtype == 3)
cardtype2 = 'S';
switch (cardvalue)
{
case 0:
{
printf("*******\n");
printf("* *\n");
printf("* %c *\n", cardtype2);
printf("* K *\n", cardvalue);
printf("* *\n");
printf("*******\n");
break;
}
case 1:
{
printf("*******\n");
printf("* *\n");
printf("* %c *\n", cardtype2);
printf("* A *\n");
printf("* *\n");
printf("*******\n");
break;
}
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
{
printf("*******\n");
printf("* *\n");
printf("* %c *\n", cardtype2);
printf("* %2d *\n", cardvalue);
printf("* *\n");
printf("*******\n");
break;
}
case 11:
{
printf("*******\n");
printf("* *\n");
printf("* %c *\n", cardtype2);
printf("* J *\n", cardvalue);
printf("* *\n");
printf("*******\n");
break;
}
case 12:
{
printf("*******\n");
printf("* *\n");
printf("* %c *\n", cardtype2);
printf("* Q *\n", cardvalue);
printf("* *\n");
printf("*******\n");
break;
}
}
}
int pickCard(Deck deck, int cardnum)
{
if (cardnumber == 52)
{
printf("There is not enough cards left to complete the game!");
endProgram();
}
else
return deck[cardnum];
}
Here is my code for a simple blackjack game. For some reason after some rounds Dealers turn does not work. I would be gratefull if you could find the reason as I couldn't. And feel free to give tips about improving my code.

You have the following problems in your code that I could see from compiler warnings/errors.
The declaration of printCard does not match its usage and its implementation. Change the declaration to:
void printCard(int cardvalue, int cardtype);
Make the return type of main explicit. Change it to:
int main () ...
Change the lines that print K, J, and Q. You don't need the additional argument to printf in those lines.
printf("* K *\n");
printf("* J *\n");
printf("* Q *\n");
Of the above, the first one is the most crucial fix. With those changes, I was able to run your program without any problem. My test platform: Linux, gcc 4.8.4.
Increase your warning level so you can detect such warnings/errors and fix them in future programming efforts.

Since you asked... :-)
In addition to what R Sahu called out...
The biggest problem (challenge?) I noticed is that I don't see how your endProgram() function actually 'ends' anything. It calls system("pause") and then resumes:
void endProgram()
{
printf("Thanks for playing my blackjack game! The results are:\n");
printf("Player won %d times!\n", playerwin);
printf("Dealer won %d times!\n", dealerwin);
printf("There have been a tie %d times!\n", tie);
system("pause);
}
Which means code like the following in the pickCard() function has unpredictable behavior:
int pickCard(Deck deck, int cardnum)
{
if (cardnumber == 52)
{
printf("There is not enough cards left to complete the game!");
endProgram(); // once we get here what do we return to the caller?
}
else
return deck[cardnum];
}
By "unpredictable" I specifically mean: What will pickCard() return to for cardnumber = 52 ?
I suspect pickCard() is going to call endProgram(), whch being a void function won't do anything but return, then pickCard will fall out of the if-else statement and try to return an integer to the caller, and it will probably be choosing some garbage off the call stack to send back which may (or may not) be a valid card value.
It turns out you call pickCard() in roughly 5 different places, sometimes for the player, sometimes the dealer.
What happens to that logic if pickCard() returns a value that is way out of bounds?
Since you only call shuffleDeck() once at the beginning of main(), eventually you're going to 'exhaust' the deck and get an undefined card value returned from pickCard().
Which kind of fits your symptoms of "it breaks in Dealer after a while...".
So... for general cleanup...
I would take most the variables you have in the game() method and make them globals.
I would add a LOT of print statements for debugging so you can verify the code is doing what you think it will do.
Your calls to system() are a challenge for me on the linux side of the fence:
system("cls");
system("pause");
Since you're devleoping on Windows I understand why you are using system (reminds me of the ancient days when I used to write dos batch files).
But... I would encourage you to ditch the system() calls and write your own input "helper" function that deals with scanf_s or whatever you want to use.
Maybe something like this that can take a prompt and return whatever character the user types.
char prompt_and_read_char( char *msg );
I would encourage you to rewrite without goto statements.
You do attempt a loop in the game() function for the player to draw cards; the for loop, so bonus points for that.
Your overall style and user interaction goals are sound and suggest you'll eventually make a fun game.
The code in game() is a bit over 200 lines of code, which makes it is harder than it needs to be to read.
I would suggest doing something like this in game() function: the goal is to push all card-drawing into functions just for the player, or the dealer.
// Global Variable definitions...
int gameInProcess = 0; // global, set to false.
int tcvp = -1; // obvious bad
// note for global-var police: yeah, I know globals is not "good style".
// But cut our beginning programmer some slack here... this seems like the easiest way for
// them to get their game running. (Think of it as a first step toward cleaning up the
// game() method if that helps any).
// prototypes here.
// main() here.
...etc...
int game() {
gameInProcess = 1; // set to true.
tcvp = 0;
tcvd = 0;
while( gameInProcess ) {
// add plenty of print statements so you see what is going on; you can clean
// them up later by searching on DEBUG.
printf("DEBUG... game(): tcvp=%d tcvd=%d cardnumber=%d\n", tcvp, tcvd, cardnumber );
game_playerDraws( ); // updates tcvp, may set gameInProcess to 0 if player win or busts.
game_dealerDraws( ); // udpates tcvd, may set gameInProcess to 0 if dealer hits blackjack or goes bust.
...other functions for variations...
}
printf("game over, score: player=%d dealer=%d\n", tcvp, tcvd );
// add logic to decide winner.
// return to caller, maybe let them decide if we'll have another game using the same deck.
}
game_playerDraws( ) {
if( !gameInProcess ) {
printf("game_playerDraws(): gameInProcess=%d, nothing to do.\n", gameInProcess );
return;
}
// draw some cards, update globalcs if player wins or breaks.
}
game_dealerDraws( ) {
... do dealer-approriate things...
}
The upside of this is if you exahust the deck, you can just set gameInProcess = 0; and return and everything gracefully stops.
You might add an option to shuffle a new deck and start another game.
But the big advantage is it will give you a clean way to start and end each game, which is something you're missing in the current version of the code.
Good luck. You clearly enjoy programming and are having fun with the writing game.
Stick with it, I think you'll learn a lot.

Related

Morra - Odds and Even

Im writing a code that evolves the computer and I entering numbers and added them together to see who wins.
There are three problems:
Problem 1: When I try to recall the 'main()' function the 'game()' wont appear.
Problem 2: I can't seem to run the code forever until user decides to stop.
Problem 3: The point system isn't accurate enough.
Any help would be grateful.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int human_fingers;
int comp_fingers;
int menu_choice;
int answer;
int count = 1;
int point1 = 0, point2 = 0;
int total;
void intro() {
printf("Welcome to Morra - Odds and Even!\n\n");
printf("The rules of the game are pretty simple\n");
printf("You and the computer will pick a side each round\n");
printf("You must enter a number and the total sum will determine the winner!\n\n");
}
void example() {
printf("You picked even, by default the computer will be odd this round\n");
printf("You entered 3 and the computer entered 5\n");
printf("3 + 5 = 8, so you win because you choose even!\n");
}
void game() {
while(count < 7)
{
count = count + 1;
printf("Enter a number to choose a side:\n");
printf("Even [1] / Odd [2]\n");
scanf("%d", &menu_choice);
while((menu_choice<1) || (menu_choice>2)){
printf("Invalid entry, please Enter 1-2: ");
scanf("%d",&menu_choice);}
if(menu_choice == 1)
{
printf("The computer will be odd this turn\n");
printf("\nPlease enter an number (1-10)\n");
scanf("%d", &human_fingers);
while((human_fingers<1) || (human_fingers>10)){
printf("Invalid entry, please enter 1-10:");
scanf("%d",&human_fingers);}
printf("Computer is choosing a number....\n");
srand(time(NULL));
comp_fingers = rand() % 10 + 1;
printf("You: %d\n", human_fingers);
printf("Computer: %d\n", comp_fingers);
int result;
result = human_fingers + comp_fingers;
printf("Total is %d\n", result);
total = result % 2;
if(total == 0)
{
printf("This turn goes to You!\n\n");
printf("You: %d\n", point1 + 1);
printf("Computer: %d\n\n", point2 + 0 );
point1++;
}
else
{
printf("This turn goes to Computer!\n\n");
printf("You: %d\n", point1 + 0 );
printf("Computer: %d\n\n", point2 + 1);
point2++;
}
}
if(menu_choice == 2)
{
printf("The computer will be even this turn\n");
printf("\nPlease enter an number (1-10)\n");
scanf("%d", &human_fingers);
while((human_fingers<1) || (human_fingers>10)){
printf("Invalid entry, please enter 1-10:");
scanf("%d",&human_fingers);}
printf("Computer is choosing a number...\n");
srand(time(NULL));
comp_fingers = rand() % 10 + 1;
printf("You: %d\n", human_fingers);
printf("Computer: %d\n", comp_fingers);
int result;
result = human_fingers + comp_fingers;
printf("Total is %d\n", result);
total = result % 1;
if(total == 0)
{
printf("This turn goes to Computer!\n\n");
printf("You: %d\n", point1 + 0);
printf("Computer: %d\n\n", point2 + 1);
point1++;
}
else
{
printf("This turn goes to You!\n\n");
printf("You: %d\n", point1 + 1);
printf("Computer: %d\n\n", point2 + 0 );
point2++;
}
}
}
if(point1 > point2)
printf("You won, you beat the computer!\n");
else
printf("Unlucky the computer won!\n");
}
void end(){
printf("Game has ended!\n");
}
int main()
{
intro();
printf("Would you like an example to demostrate?\n");
printf("Yes [1] / No [2]\n");
scanf("%d", &answer);
if( answer == 1 )
{ example();
printf("\n\n");
game();
}
else
{ printf("\n\n");
game();
}
end();
printf("Would you like play another game?\n");
printf("Yes [1] / No [2]\n");
scanf("%d", &answer);
if( answer == 1)
{
main();
}
else {
printf("Thanks for playing MORRA - ODDS AND EVEN.");
}
return 0;
}
Why not:
int main()
{
for(;;) // Infinite loop. -- equivalent of while(1) if you prefer.
{
intro();
printf("Would you like an example to demostrate?\n");
printf("Yes [1] / No [2]\n");
scanf("%d", &answer);
if( answer == 1 )
{ example();
printf("\n\n");
game();
}
else
{ printf("\n\n");
game();
}
end();
printf("Would you like play another game?\n");
printf("Yes [1] / No [2]\n");
scanf("%d", &answer);
if( answer != 1)
{
printf("Thanks for playing MORRA - ODDS AND EVEN.");
break;
//^___ exit the infinite loop.
}
}
return 0;
}
Recalling the main you should definitely not, in almost any case. Just create loops if you want to repeat everything.

Problem with Rock Scissor Paper program in C

I have a problem with my program. I want it to execute a loop that makes the result of the game and increments the score. But for some reason it doesn't make the exiting loop or shows the correct score. Below is the code. What the problem could there be.?
Is the there something wrong with the function calls. I want to execute ask the player if he wants to continue and in the case he wants to play to shwo the new score.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void game_exit(void);
void game_playing(void);
void game_choice_menu();
int algorithm(int *player_choice, int *computer_choice);
int main()
{
system("clear");
printf("\n|==============================|\n| ROCK-SCISSORS-PAPER |\n|==============================|\n");
printf("\n1.Start Playing!\n2.Exit!\n\nWhat you wanna do: (pick 1 or 2): ");
int input;
scanf("%d",&input);
switch (input)
{ case 1:
game_playing();
game_exit();
break;
case 2:
game_exit();
break;
default:
printf("WRONG INPUT!! TRY AGAIN!!!");
game_exit();
break;
}
}
void game_choice_menu(void)
{
static int player,computer;
player =0;
computer = 0;
system("clear");
printf("PLAYER : %d COMPUTER: %d \n", player, computer);
printf("===============================");
printf("\nRock, Scissors or Paper? (1 for Rock, 2 for Scissors and 3 for Paper) ");
int answer;
do{
scanf("%d",&answer);} while (answer<=1 && answer>=3);
int computer_choice = rand()% 3;
int result;
result = algorithm(&answer,&computer_choice);
if (result==0) {
player++;
//system("pause 3");
printf("\n YOU WON!!!\n");}
else {
//system("pause 3");
printf("\n YOU LOSE!!!\n");
computer++;}
}
int algorithm(int *player_choice, int *computer_choice)
{
if ( *player_choice < *computer_choice)
{
if ( (*computer_choice - *player_choice)==2)
return 1;
else if ((*computer_choice - *player_choice)==1)
return 0;
}
else if (*player_choice > *computer_choice)
{
if ((*player_choice - *computer_choice)==2)
return 1;
if ((*player_choice - *computer_choice)==1)
return 0;
}
}
void game_playing(void)
{
for (;;)
{
game_choice_menu();
//printf("\n Want to play again? (Y for yes, N for no)");
//char reply;
//scanf("%c",&reply);
//if (reply == 'y' || reply == 'Y')
// continue;
//else if (reply == 'n' || reply == 'N')
// break;
}
}
void game_exit(void)
{
system("clear");
printf("THANK YOU FOR PLAYING!!!");
printf("\n");
}

How to simplify this code and make it into functions?

I am just beginning to code, and I'm trying to recreate the Monty Hall Problem game show. My program gives the user a choice between game mode, research mode, and exiting the game. I'm trying to simplify my code and put game mode and research mode into functions, but all of the research I'm doing isn't really making much sense to me. I would appreciate some help, thank you!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int winning (int win);
float PERCENTAGE (float win,float playedgames);
int RANDOM ();
int main (void)
{
int choice, choice2, Ngames, Ngames2,chosendoor,chosendoor2;
int gamesplayed,gamesplayed2,winningdoor,winningdoor2,revealeddoor;
int switcheddoor, revealeddoor2,stayeddoor, doorchoice,winningdoor3;
int revealeddoor3, choice3, switcheddoor2;
float percent,percent2;
float win = 0,win2 = 0;
int gamesplayed3 = 0,win3 = 0;
srand(time(NULL)); //randomizes based on time
while (choice!=3)
{
printf ("Please enter one of the following options\n\n1. Research mode\n2. Game mode\n3. Exit\n\n");
scanf ("%d", &choice);
switch(choice)
{
case 1:
printf ("\nYou have chosen research mode.\n");
printf ("Please indicate whether you will always us the always- switch strategy or the never-switch strategy.\n");
printf ("1. Always switch doors\n2. Never switch doors\n\n");
scanf ("%d", &choice2);
switch (choice2)
{
case 1:
printf ("\nYou have chosen to always switch doors.\n");
printf ("How many games would you like to play?\n\n");
scanf ("%d", &Ngames);
for (gamesplayed = 0;gamesplayed <= Ngames;gamesplayed++)
{
winningdoor = RANDOM();
chosendoor = 1;
do
{
revealeddoor = RANDOM();
} while (revealeddoor == chosendoor || revealeddoor == winningdoor);
do
{
switcheddoor = RANDOM();
} while (switcheddoor == chosendoor || switcheddoor == revealeddoor);
if (switcheddoor == winningdoor)
{
win = winning(win);
}
}
percent = PERCENTAGE(win,gamesplayed);
printf ("\nYou have chosen the winning door %f percent of the time.\n\n", percent);
win = 0;
break;
case 2:
printf ("\nYou have chosen to never switch doors.\n");
printf ("How many games would you like to play?\n\n");
scanf ("%d", &Ngames2);
for (gamesplayed2 = 0;gamesplayed2 <= Ngames2; gamesplayed2++)
{
winningdoor2 = RANDOM();
chosendoor2 = 1;
do
{
revealeddoor2 = RANDOM();
} while (revealeddoor2 == winningdoor2 || revealeddoor2 == chosendoor2);
do
{
stayeddoor = RANDOM();
} while (stayeddoor != chosendoor2);
if (stayeddoor == winningdoor2)
{
win2 = winning(win2);
}
}
percent2 = PERCENTAGE(win2,gamesplayed2);
printf ("\nYou chose the winning door %f percent of the time.\n\n", percent2);
win2 = 0;
break;
default:
printf ("You have entered an incorrect value.");
break;
}
break;
case 2:
printf ("\nYou have chosen game mode.\n");
winningdoor3 = RANDOM();
printf ("Which door will you choose? (Door 1,2, or 3)\n\n");
scanf ("%d", &doorchoice);
if (doorchoice < 1 || doorchoice > 3)
{
printf ("That value is not a door.\n\n");
break;
}
do
{
revealeddoor3 = RANDOM();
} while (revealeddoor3 == doorchoice);
printf ("\nDoor %d was opened and there was no prize behind it.\n", revealeddoor3);
printf ("Would you like to:\n1. Switch doors?\n2. Stay with your current door?\n\n");
scanf ("%d", &choice3);
switch (choice3)
{
case 1:
printf ("\nYou have chosen to switch doors.\n\n");
do
{
switcheddoor2 = rand()%2 + 1;
} while (switcheddoor2 == doorchoice);
if (switcheddoor2 == winningdoor3)
{
printf ("Good choice! You have won!\n\n");
win3 = winning(win3);
}
else
{
printf ("Unfortunately, you lost.\n\n");
}
++gamesplayed3;
printf ("You have played a total of %d games and you won a total of %d games.\n", gamesplayed3, win3);
break;
case 2:
printf ("\nYou have decided to stay with your current door.\n");
if (doorchoice == winningdoor3)
{
printf ("Good choice! You have won!\n\n");
win3 = winning(win3);
}
else
{
printf ("Unfortunately, you lost.\n\n");
}
gamesplayed3 = gamesplayed3 + 1;
printf ("You have played a total of %d games and you won a total of %d games.\n\n", gamesplayed3, win3);
break;
default:
printf ("You have entered an incorrect value.\n\n");
break;
}
break;
case 3:
printf("Thanks for playing!");
exit(0);
default:
printf ("You have entered an incorrect value.\n\n");
break;
}
}
return 0;
}
int winning (int win)
{
int newwin;
newwin = win + 1;
return (newwin);
}
float PERCENTAGE (float win,float playedgames)
{
float percentage;
percentage = (win/playedgames)*100;
return (percentage);
}
int RANDOM ()
{
int random;
random = rand()%3;
return (random);
}
Here is an example, to convert one of your switch cases...
Here is your code
case 1:
printf ("\nYou have chosen to always switch doors.\n");
printf ("How many games would you like to play?\n\n");
scanf ("%d", &Ngames);
for (gamesplayed = 0; gamesplayed <= Ngames; gamesplayed++)
{
winningdoor = RANDOM();
chosendoor = 1;
do
{
revealeddoor = RANDOM();
}
while (revealeddoor == chosendoor || revealeddoor == winningdoor);
do
{
switcheddoor = RANDOM();
}
while (switcheddoor == chosendoor || switcheddoor == revealeddoor);
if (switcheddoor == winningdoor)
{
win = winning(win);
}
}
percent = PERCENTAGE(win, gamesplayed);
printf ("\nYou have chosen the winning door %f percent of the time.\n\n", percent);
win = 0;
break;
Here is how the same looks after the function is extracted
case 1:
printf ("\nYou have chosen to always switch doors.\n");
printf ("How many games would you like to play?\n\n");
scanf ("%d", &Ngames);
percent = PERCENTAGE(win, kernel(Ngames));
printf ("\nYou have chosen the winning door %f percent of the time.\n\n", percent);
win = 0;
break;
Here is how the function looks like
int kernel (int Ngames)
{
int gamesplayed;
for (gamesplayed = 0; gamesplayed <= Ngames; gamesplayed++)
{
int winningdoor = RANDOM();
int chosendoor = 1;
int revealeddoor,switcheddoor;
do
{
revealeddoor = RANDOM();
}
while (revealeddoor == chosendoor || revealeddoor == winningdoor);
do
{
switcheddoor = RANDOM();
}
while (switcheddoor == chosendoor || switcheddoor == revealeddoor);
if (switcheddoor == winningdoor)
{
win = winning(win);
}
}
return gamesplayed;
}
Now when you look at the particular switch case, you can understand its meaning much better. Only if you need to know the logic of kernel you have to go inside.
I would say that, if you are computing something which has a real meaning move it out as a function. If you reuse some code, make it a function. If your function is long or have too much loop (while, for) or conditional nesting (if, switch) then it is time to modularize your code.

If and if else statements working, but not else

I am making a number guessing game program and am having some trouble with my else statements. In the main block where the number is trying to be guessed, the if and if else statements work, but the else statement does nothing. I am trying to make it where a number outside of the range 0 < number < 100 trigger the else statement.
Furthermore, I am trying to make the game repeat itself if '1' is entered but no matter what is entered, the program crashes.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/*Number guessing game: The number that needs to be guessed is 52*/
int guess;
int attempt = 6;
int playAgain = 1;
printf("Guess the integer that I am thinking of between 1 and 100\n");
printf("I will tell you if you guess too high or too low\n");
printf("You have 6 attempts\n");
printf("What is your first guess?\n");
if (playAgain == 1)
{
while (attempt > 0)
{
scanf_s("%d", &guess);
if (guess > 0)
{
if (guess < 52)
{
attempt--;
printf("Sorry! Too low! You have %d more tries:\n", attempt);
}
}
else if (guess <100)
{
if (guess > 52)
{
attempt--;
printf("Sorry! Too high! You have %d more tries:\n", attempt);
}
}
else if (guess == 52)
{
printf("Correct! You win!\n");
attempt = 0;
}
else
{
printf("Invalid input: Please enter an integer between 1 and 100:\n");
}
}
printf("Enter '1' to play again or anything else to terminate\n");
scanf_s("%d", playAgain);
attempt = 6;
}
else
{
printf("Thanks for playing!\n");
}
return 0;
}
When you use if else if without brackets, make sure it can't be ambigous.
When you do :
if (true)
if (true)
{
}
else if (false)
{
}
How to know if the else if correspond to the first or the second if ? That's why everyone yell at you to put brackets.
if (true)
{
if (true)
{
}
}
else if (false)
{
}
Corrected and simplified version :
Your program crashes because you forgot the & sign inscanf("%d", &playAgain);.
The logic in your program is wrong, you intermix the test if the number is lower, equal or higher than the input with the test if the input is lower than 0 or higher than 100.
In this corrected version the "invalid input" problem is separated from the actuel "number guessing" problem.
Furthermore the number to be guessed (52) is nor longer hard coded but a variable numbertobeguessed is used instead. Later you should enhance the program so that a random number is generated.
int main(void)
{
/*Number guessing game: The number that needs to be guessed is 52*/
int numbertobeguessed = 52 ;
int guess;
int attempt = 6;
int playAgain = 1;
printf("Guess the integer that I am thinking of between 1 and 100\n");
printf("I will tell you if you guess too high or too low\n");
printf("You have 6 attempts\n");
printf("What is your first guess?\n");
if (playAgain == 1)
{
while (attempt > 0)
{
scanf_s("%d", &guess);
if (guess < 0 || guess > 100)
{
printf("Invalid input: Please enter an integer between 1 and 100:\n");
}
else
{
if (guess < numbertobeguessed)
{
attempt--;
printf("Sorry! Too low! You have %d more tries:\n", attempt);
}
else if (guess > numbertobeguessed)
{
attempt--;
printf("Sorry! Too high! You have %d more tries:\n", attempt);
}
else
{
printf("Correct! You win!\n");
attempt = 0;
}
}
}
printf("Enter '1' to play again or anything else to terminate\n");
scanf_s("%d", &playAgain);
attempt = 6;
}
else
{
printf("Thanks for playing!\n");
}
return 0;
}
the else statement which gives message "Invalid input: Please enter an integer between 1 and 100:\n" is considered as the else part of inner most if-else-if statement. there fore that statement is never executed as the execution enters that if-else-if statement only if 0 < guess < 100. so use {} properly to make the proper combination of if-else statements.
Your nesting is wrong. Put brackets for each if and else to make your code work (quickfix), and use proper indentation to make it readable to humans (if you wish).
Here's an example of how things can go wrong (pseudo code):
a = 4
if (a > 0)
if (a < 3)
a = 2
else
a = 3
What do you expect is the end value of a?
Anyway, your:
if (guess > 0)
if (guess < 52)
should become this:
if (guess > 0 && guess < 52)
and your:
else if (guess <100) // this is where the problems start
if (guess > 52)
should become:
else if (guess < 100 && guess > 52)
and your code will work.
hope this helps
#include <stdio.h>
#include <stdlib.h>
int main()
{
int guess; //variable to hold the number from player
int attempts = 6;
char play = 'y';
do
{
while(attempts)
{
printf("\nEnter you guess: "); scanf("%d", &guess);
attempts--;
if(guess>0 && guess <100 )
{
if(guess>52)
printf("\nThat's not it. Try something lower than that.");
else if(guess<52)
printf("\nThat's not the number. Try something higher than that.");
else if(guess==52)
{ printf("\nYou got it!. You won the game.");
attempts = 0; //we're setting it to zero; we don't want the loop to run anymore
}
}
else
printf("\nNumber enter is not in range!");
}//end of while loop
printf("\nDo you want to play again? (y/n): "); scanf("%c", &play);
}while(play=='y' || play=='Y'); //run till player enter 'Y'
return 0;
}

Is there any way to avoid using exit(0)?

I wanted to practice a little with separating logic into functions and using basic recursion in a primitive "Guess my number game", just as a sort of way to see where I'm at in my C programming.
Here's the code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
char playAgain()
{
printf("\nDo you wanna play again? ");
char resp = 0;
while (TRUE) {
scanf("%c", &resp);
if (resp == 'y') break;
if (resp == 'n') break;
}
return resp;
}
void play()
{
srand((int)time(NULL));
int num = rand() % 10 + 1;
int guess = 0;
int flag = 0;
int attempts = 0;
printf("\nGuess the number: \n");
while (TRUE) {
scanf("%d", &guess);
if (num > guess)
{
printf("Too low! ");
attempts++;
}
else if (num < guess)
{
printf("Too high! ");
attempts++;
}
else if (num == guess)
{
attempts++;
printf("You won! You did it in %d attempts", attempts);
char yo = playAgain();
if (yo == 'y') play();
else if (yo == 'n') exit(0);
else {
printf("Error!");
exit(1);
}
}
}
}
int main()
{
return play();
}
Everything works but I've only managed to make it quit when the user says 'n', by using exit(0) and I've heard it's bad practice. But having spent a couple of hours just noodling around and trying all the other ways I could think of (using flags, for example), I just couldn't make it work. It works for 'y', but as soon as I enter 'n', it doesn't quit and just calls the playAgain() function one more time, or freezes altogether (nothing happens).
I feel ashamed for not being able to solve this, but I'm out of ideas. Is there any other way, other than exit(0), to make it jump out of play() straight to return 0 in main()? The problem seems to be that I have an infinite game loop, so when the answer is 'n', I need to break out of the loop AND out of the play() function, and that has proven to be problematic. I remember being able to do this easily when I had no functions, but just all the relevant code in main(), but the whole point of this is to use functions. For example, I can't figure out how to make use of a return type of play(), so that it knows when to quit.
P.S. As always, seeing how often people get accused of this, I assure you this is not homework because I am, and always have been, doing programming strictly as a hobby. There's no professor I answer to, apart from you :-) And trust me that I did try to figure out a solution, but nothing seems to work. It's a question of good vs. bad design, so it's especially important for my self-teaching. exit(0) seems to be a hackish solution and serves no educational purpose.
P.P.S. By the way, I'm using xCode, and the program runs in its output window. Probably not, but maybe that's the reason quitting with 'n' doesn't work?
SUMMARY: The code works fine except when the answer is 'n', in which case it just asks "Do you wanna play?" again, or doesn't do anything at all.
Make your play function return a result:- int play( void ) {
then instead of exit(1) and exit(0); use return 1; and return 0;
at the end of play put return 0;
then in main
{
return play();
}
instead of recursion, just make a loop
int play( void)
{
srand((int)time(NULL));
int num;
int guess;
int flag;
while(1)
{
num = rand() % 10 + 1;
guess = 0;
flag = 0;
printf("\nGuess the number %d: \n", num);
while (1) {
scanf("%d", &guess);
if (num > guess)
{
printf("Too low! ");
}
else if (num < guess)
{
printf("Too high! ");
}
else if (num == guess)
{
printf("You won!");
char yo = playAgain();
if (yo == 'y') break;
else if (yo == 'n') return 0;
else {
printf("Error!");
return 1;
}
}
}
}
}
and if you want more of a game engine type approach
enum {
GUESS,
GAMEOVER,
QUIT,
} GAME_STATES;
typedef struct
{
enum GAME_STATES state;
int num;
int game_over;
} guessing_game_t;
void init_game(guessing_game_t* g)
{
g->state = GUESS;
g->game_over = 0;
g->num = rand() % 10 + 1;
}
void evaluate_guess(guessing_game_t* g, int guess)
{
if(g->num == guess)
{
printf("You won!");
g->state = GAMEOVER;
}
else if (g->num > guess)
{
printf("Too low! ");
}
else if (g->num < guess)
{
printf("Too high! ");
}
}
int input_guess( void )
{
int guess;
scanf("%d", &guess);
return guess;
}
void play_again( guessing_game_t* g)
{
char resp = 0;
printf("\nDo you wanna play again? ");
scanf("%c", &resp);
if (resp == 'y') init_game(g);
if (resp == 'n') g->state = QUIT;
}
void play( guessing_game_t* g)
{
while(g->state != QUIT)
{
switch(g->state)
{
case GUESS:
evaluate_guess(g, input_guess());
break;
case GAMEOVER:
play_again(g);
break;
}
}
}
int main()
{
guessing_game_t game;
init_game(&game);
play(&game);
}
You can put a flag before going on with the loop
Change the while(true) to while (continue_play), continue_play is the name of flag for an example
Then,
if (yo == 'n') exit(0);
can be change to
if (yo == 'n') continue_play=false;
and do the similar for the exit(1) case
continue_play then will be a flag to exit from the function.
You have one more thing that the program will end: the logic of your code is made like that u can also use break; instead of exit(0) and exit(1) because you use while loop and you will break it and the program will end.
Since you may recursive call you play() function, I think exit it with exit(0) is a proper choose.
Acutall, I do not think using recursion to implement play() is a good idea at all, two infinite loops are enough. You could implemet it like this:
void play(void)
{
srand((int)time(NULL));
int num;
int guess = 0;
int attempts = 0;
int try_again = 1;
while (try_again) {
num = rand() % 10 + 1;
printf("\nGuess the number: \n");
while (TRUE) {
scanf("%d", &guess);
if (num > guess)
{
printf("Too low! ");
attempts++;
}
else if (num < guess)
{
printf("Too high! ");
attempts++;
}
else if (num == guess)
{
attempts++;
printf("You won! You did it in %d attempts", attempts);
char yo = playAgain();
if (yo == 'n') try_again = 0;
break;
}
}
}
}

Resources