Logical Operators in C causing issue with my loop? - c

I am making a game for an assignment where there are 2 players and each turn the player rolls 2 die. When I ask the player if they want to roll again everything goes south from there. I'm confused because even if I change my rollAgain character to 'n' it still plays my loop where I want it to run only if rollAgain is 'y' or 'Y'. This is my first program in C, I have only programmed in Java previously. I feel like I must be checking the logical operators incorrectly in my while loop but idk what I'm doing wrong, I've looked over all the code several times now.
Here is my code:
#include <stdio.h>
#include <stdlib.h> // NULL constant, srand() & rand() functions
#include <time.h> // access your computer’s clock time
// function prototype statements
int rollDice();
int calcPoints(int die1, int die2);
char checkOne(int die1, int die2);
int main()
{
int p1Score = 0;
int p2Score = 0;
int turnTotal = 0;
char rollAgain = 'Y';
char rolled1 = 'N';
int die1;
int die2;
printf("Welcome to the Pig Game. Each turn the player rolls two dice repeatedly until a single 1 is rolled or the player holds.\n\n");
printf("If a single 1 is rolled all points are lost. If the player holds, all earned points are kept.\n");
printf("If double 1's are rolled 25 points are earned, if any other doubles are rolled the value is doubled.\n");
printf("Player 1 has an advantage because they get to go first, the youngest player gets to be Player 1.\n\n");
printf("First player to 100 points wins, let the games begin!!!\n\n");
do
{
//----------------------P1's turn starts----------------------------------------
while ((rollAgain == 'Y' || rollAgain == 'y') && rolled1 == 'N')
{
die1 = rollDice(); //roll die 1
die2 = rollDice(); //roll die 2
printf("Player 1 rolls %d, and %d\n", die1, die2);
rolled1 = checkOne(die1, die2); //check if turn ending 1 is rolled if they did the below while loop will not run and the current while loop will end.
if(rolled1 == 'N') //if a single 1 wasn't rolled calculate total for the turn
{
turnTotal += calcPoints(die1, die2);
printf("Player 1 your turn total so far is %d. Would you like to roll again?\n", turnTotal);
fflush(stdin);
scanf_s("%c", &rollAgain);
}
}
//-------------------------P1's turn is now over---------------------------------
if (rolled1 == 'Y') //turnTotal isn't added to p1Score
{
printf("Sorry Player 1 your turn is over because you rolled a 1 on a single die :(\n");
printf("Your total score is now: %d.\n", p1Score);
}
else //player1 must have held
{
printf("Congratulations on scoring %d point this turn Player 1!\n", turnTotal);
p1Score += turnTotal;
printf("Your total score is now: %d.\n", p1Score);
}
//reset variables to start p2s turn
turnTotal = 0;
rolled1 = 'N';
rollAgain = 'Y';
//----------------------P2's turn starts----------------------------------------
while ((rollAgain == 'Y' || rollAgain == 'y') && rolled1 == 'N' && p1Score < 100) //player2's turn should not start if player 1 has already won the game so we must check p1's score as well
{
int die1 = rollDice(); //roll die 1
int die2 = rollDice(); //roll die 2
printf("Player 2 rolls %d, and %d\n", die1, die2);
rolled1 = checkOne(die1, die2); //check if turn ending 1 is rolled if it was the below while loop will not run and the current while loop will end.
if(rolled1 == 'N') //if a single 1 wasn't rolled calculate total for the turn
{
turnTotal += calcPoints(die1, die2);
printf("Player 2 your turn total so far is %d. Would you like to roll again?\n", turnTotal);
fflush(stdin);
scanf_s("%c", &rollAgain);
}
}
//-------------------------P2's turn is now over---------------------------------
if (rolled1 == 'Y' && p1Score < 100) //turnTotal isn't added to p1Score
{
printf("Sorry Player 2 your turn is over because you rolled a 1 on a single die :(\n");
printf("Your total score is now: %d.\n", p2Score);
}
if (rolled1 == 'N' && p1Score < 100) //player2 must have held, use an if statement rather than else because we don't want this code to play if p1 has already won
{
printf("Congratulations on scoring %d point this turn Player 2!\n", turnTotal);
p2Score += turnTotal;
printf("Your total score is now: %d.\n", p2Score);
}
//reset variables for p1's turn
turnTotal = 0;
rolled1 = 'N';
rollAgain = 'Y';
//if either player's score is > 100 the game is now over so the game ending code will now play
} while (p1Score < 100 && p2Score < 100);
if (p1Score >= 100) //player 1 has won, congratulate them
printf("Congratulations Player 1, you have won the game! Pat yourself on the back!\n");
else //player 1 didn't win so player 2 must have won since there are no draws
printf("Congratulations Player 2, you have won the game! You are awesome!\n");
return 0; //end main
}
//function rollDice rolles the dice for the player using a random number between 1-6.
int rollDice()
{
// seed the random number generator using the computers clock
srand(time(0));
//generate a random number between 1-6
int num = (rand() % 6) + 1;
return num;
}
//function calcPoints that calculates how many points the player earned.
int calcPoints(int die1, int die2)
{
int points;
if (die1 == die2) //check if doubles were rolled
{
//snake eyes = 25 points
if (die1 == 1)
points = 25;
//regular doubles = the value on the dice *2
else
points = (die1 + die2) * 2;
}
else //doubled weren't rolled
points = die1 + die2;
return points;
}
//function checkOne that checks if the player rolled a single 1 during their turn.
char checkOne(int die1, int die2)
{
if (die1 == 1 && die2 != 1)
return 'Y';
else if (die1 != 1 && die2 == 1)
return 'Y';
else
return 'N';
}
The players turn is supposed to end if a single 1 is rolled.
I would really appreciate any help I'm not sure where I am going wrong. The code just has a mind of its own after it asks if I want to roll again.
Player 1 rolls 2, and 2
Player 1 your turn total so far is 8. Would you like to roll again?
y
Player 1 rolls 3, and 3
Player 1 your turn total so far is 20. Would you like to roll again?
Congratulations on scoring 20 point this turn Player 1!
Your total score is now: 20.
Player 2 rolls 3, and 3
Player 2 your turn total so far is 12. Would you like to roll again?
this is the output I get if I say yes to rolling again. At the end of this output it allows me to input if I want to roll again.
Player 1 rolls 3, and 3
Player 1 your turn total so far is 12. Would you like to roll again?
n
Congratulations on scoring 12 point this turn Player 1!
Your total score is now: 12.
Player 2 rolls 1, and 1
Player 2 your turn total so far is 25. Would you like to roll again?
Congratulations on scoring 25 point this turn Player 2!
Your total score is now: 25.
Player 1 rolls 1, and 1
Player 1 your turn total so far is 25. Would you like to roll again?
this is the output I get if I say no to rolling again. At the end of this output it allows me to input if I want to roll again.

There are multiple classic issues in your code:
fflush(stdin); has undefined behavior. Just remove this statement, it does not consume the pending input in stdin.
scanf_s("%c", &rollAgain); will read the pending newline in the input stream. To skip it, you can just add a space in the format string and you must test if scanf_s succeeded to avoid undefined behavior at end of file:
if (scanf_s(" %c", &rollAgain) != 1) {
exit(1); // unexpected end of file or some other error
}
You should not reinitialize the random number generator every time you roll a die, just once at the beginning of the program (move the srand() function call to the beginning of the main function, and pass it clock() that varies much more rapidly than time(NULL)):
//function rollDice rolls the die for the player using a random number between 1-6.
int rollDice() {
//generate a random number between 1-6
return (rand() % 6) + 1;
}

Related

all functions being skipped and code is running without them

I have fixed my code style and have updated what it looks like, but it's skipping all the rounds and inputs I want to make
If I formatted the returns wrong(Which is what I'm thinking), or I didn't nest my functions properly, those are the only issues I can imagine would be wrong
#define ROUNDS 3
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
//Greets the user at the start of the round
void greeting();{
printf("Welcome to the Toothpick Game!\n");
printf("Here are the rules.\n");
printf("There are currently 31 toothpicks on the table.\n");
printf("You and I will each get a turn to pick either 1, 2, or 3 toothpick off the table.\n");
printf("The player that gets to puck the last toothpicks looses the game!\n");
printf("Sounds easy right? Well lets see if you can beat me!\n");
printf("Ready to play?... Here we go!\n");
} //display welcome message to user
for(int x = 0; x < ROUNDS; ++x)
{
int result = playRound(x + 1); //call playRound and assign result the value function returns
void winnerAnnouncment(int user);{//overall winner of round announcement
}
}
printf("********************************************************\n");
printf("Thank you for playing!\n");
return 0;
}
int playRound(int round)
{
int toothpicks = 31; //number of toothpicks to start with
int winner, taken, choice, leftover;
printf("Welcome to a new round %d!\n", round);
printf("You may go first!\n");
int leftOnTable(int toothpicks, int taken);{ //calculate number of toothpicks left
toothpicks = toothpicks - taken;
while(toothpicks != 0)//loop to control playing of the game
{
int humanPick();{ //retrieve the user's guess
int userchoice;
printf("How many toothpicks do you want to take? ");
scanf("%d", &taken);
printf("Okay... You took %d off the table", taken);
if (toothpicks = 1)
winner = 0;
int computerPick(int choice, int leftover);{ //computer makes its pick
if (toothpicks > 4){//Caculates what the computer will take based off of the users choice
choice = 4 - userchoice;
toothpicks = toothpicks - choice;
leftover = choice;
printf("I am taking %d toothpicks off the table.", choice);
}
if(toothpicks = 2 || 3 || 4)//calculates how many toothpicks the computer will take to leave one left on the table
if (toothpicks == 2){
choice = toothpicks - 1;
leftover = 1;
printf("I am taking %d toothpicks off the table.", choice);
}
if (toothpicks == 3){
choice = toothpicks - 1;
printf("I am taking %d toothpicks off the table.", choice);
}
if (toothpicks == 4){
choice = toothpicks - 1;
leftover = 1;
printf("I am taking %d toothpicks off the table.", choice);
}
if (toothpicks = 1){
choice = 1;
leftover = 0;
toothpicks = leftover;
winner = 1;
printf("I will take the last toothpick.");
}
}
}
return toothpicks;
}
}
return round;
}
Multiple times throughout the code used is an assignment operator = instead of the == likely intended.
In addition, the following:
userchoice is never initialized to a value.
Nested functions aren't supported by the C standard.
Numerous semicolons are found before the function definitions (e.g. void greeting();{...}).
This declares, but doesn't define the function. The following is code that executes in a new code block (new scope).
Incorrect || operator usage in conditionals (Broken:toothpicks == 2 || 3 || 4 Fixed: toothpicks == 2 || toothpicks == 3 || toothpicks == 4).
This condition would always be true. The conditional toothpicks == 2 is tested, if this proves untrue the conditional 3 is tested. 3 is true, and so this condition is always true.
The functions leftOnTable and greeting are never called.
Additional unused variables include: result and winner
Other logical errors may exist.
This should answer, if only partially, why the program isn't working as expected. Perhaps with more information about why nested functions are being used and the intended functionality of the program, I could provide a working code fix to every present issue.

Craps game in c

First of all, I'm really sorry for my bad English
I tried to explain the problem as much as I can
Craps game in c
The computer rolls two dice and if the result is 7 or 11 you directly win or the result is 2,3 and 12 you directly lose.
if the sum is 4,5,6,8,9 or 10 it wants you to roll the dice again. and this time you have to find the same sum 4,5,6,8,9 or 10
if you get 7 or 11 before finding the same number you lose. (This is where the problem is, even if the computer finds the same number twice. it doesn't print out as "you won."
https://imgur.com/KL358Fi
Examples:
dices are rolling... 11 You won.
do you want to play again (y/Y – n/N)? y
dices are rolling... 3 You Lose
do you want to play again (y/Y – n/N)? y
dices are rolling... 12 Kaybettiniz
Yeni oyun oynansin mi (y/Y – n/N)? y
dices are rolling... 7 You Won.
do you want to play again (y/Y – n/N)? y
dices are rolling... 7 you won
do you want to play again(y/Y – n/N)? y
dices are rolling... 9 result is unclear, dice will be rolled again. roll (r/R)?
dices are rolling... 8 result is unclear, dice will be rolled again. roll(r/R)?
Dices are rolling... 11 result is unclear, dice will be rolled again. roll (r/R)? R
dices are rolling... 9 You won.
Yeni oyun oynansın mı (y/Y –(n/N)? e
Zarlar atiliyor... 5 result is unclear, dice will be rolled again. roll (r/R) r
Zarlar atiliyor... 10 result is unclear, dice will be rolled again. roll (r/R) r
Zarlar atiliyor... 7 You lose.
do you want to play again (y/Y – n/N)? N
CRAPS has ended.
#include<stdio.h>
#include <time.h>
int main()
{
char ynd;
int kazan=0;
int sonuc=0;
char yoyun;
do{
printf("dice is rolling ");
srand(time(NULL));
kazan = rand()%11+1;
kazan++;
if( kazan==7 || kazan==11 )
{
printf(" %d you won.\n",kazan);
}
else if( kazan==2 || kazan==3 || kazan==12 )
{
printf(" %d you lose.\n",kazan);
}
sonuc=kazan;
if( kazan==4 || kazan==5 || kazan==6 || kazan==8 || kazan==9 || kazan==10 )
{
do{
printf("%d result is unclear, dice will be rolled again roll(r/R) ",kazan);
scanf(" %s",&ynd);
printf("dice is rolling ");
kazan = rand()%11+1;
kazan++;
if(kazan == sonuc)
{
printf("%d you won",kazan);
break;
}
else if(kazan==7){
printf("%d You lose",kazan);
break;
}
}
while(ynd=='r' || ynd=='R');
}
printf("want to play a new game ( y/Y-n/N )");
scanf(" %s",&yoyun);
} while(yoyun=='y' || yoyun=='Y');
printf("craps has ended");
return 0;
}
The code you posted does appear to print out "you won" if it finds the original number before finding 7. Perhaps you fixed your error in translation?
However, it does not result in a loss if it rolls 11 before finding the duplicate.
I also see some potential improvements:
You should #include <stdlib.h> to use srand and rand (gcc automatically fixes this for you). See here. In general try to resolve warnings produced by the compiler (search for them online if you don't understand).
I recommend only using srand(time(NULL)) at the beginning of the program because if the user plays the game rapidly they will end up with identical games until the second has elapsed.
You could use rand()%6+rand()%6+2 to simulate the distribution of dice rolls (for example, 7 is more likely than any other number). Simply using rand()%11+1 results in a uniform distribution.
You incremented the dice roll with ++ and 1 directly after you called rand. It would be more straightforward to just add 2 after you call rand.
No need to check if the dice roll is indeterminate. Simply use a final else and move sonuc=kazan into the block.
You may want to look into using a jump table rather than if statements because it could be more efficient in cases like this where the input (dice roll) is tightly packed integers.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
char ynd;
int kazan=0;
int sonuc=0;
char yoyun;
srand(time(NULL));
do {
printf("dice is rolling ");
kazan = rand()%6+rand()%6+2;
if( kazan==7 || kazan==11 )
{
printf(" %d you won.\n",kazan);
}
else if( kazan==2 || kazan==3 || kazan==12 )
{
printf(" %d you lose.\n",kazan);
}
else
{
sonuc=kazan;
do {
printf("%d result is unclear, dice will be rolled again roll(r/R) ",kazan);
scanf(" %s",&ynd);
printf("dice is rolling ");
kazan = rand()%6+rand()%6+2;
if(kazan == sonuc)
{
printf("%d you won.\n",kazan);
break;
}
else if(kazan==7 || kazan==11){
printf("%d You lose.\n",kazan);
break;
}
} while (ynd=='r' || ynd=='R');
}
printf("want to play a new game ( y/Y-n/N )");
scanf(" %s",&yoyun);
} while(yoyun=='y' || yoyun=='Y');
printf("craps has ended.\n");
return 0;
}

I want a counter to add each time matrix[yVal][xVal] == 5

I have the following code:
do{
int health = 3;
int xVal;
int yVal;
printf("Enter an x value from 0 to 9\n");
scanf("%d", &xVal);
printf("You entered '%d'\n",xVal);
printf("Enter a y value from 0 to 9\n");
scanf("%d", &yVal );
printf("You entered '%d'\n",yVal);
printf("Value at '%d', '%d' is '%d'\n", yVal , xVal, matrix[yVal][xVal]);
if ( matrix[yVal][xVal] == 5 )
{
health = health - 1;
printf("Ouch... You have found a 5 and lost a point\n If you lose %d more, you will lose.\n", health);
}
if (health == 0)
{
isGameOver = true;
printf("You have lost.\n");
}
if ( matrix[yVal][xVal] == 9 )
{
isGameOver = true;
printf("You have won.\n");
}
} while(isGameOver != true);
The problem comes each time I find a five in the array, it only subtracts from the health counter once.
If I find 2 fives, it will stay as a 2 rather than counting down to one, the whole point of my game is that if you find 3 "5"s, you lose.
The problem is you are declaring health = 3 inside the loop, so each time it loops it resets it to 3. Move it to before the loop (ie before the "do" statement)

How to store / re-roll dices in Dice Roll simulator in C

I have searched all around when trying to search for previous questions and answers, but I can't seem to find what I am looking for. At least not for plain C, so here I go.
As part of a University Task, I am writing a Roll Dice simulator in C. I have managed the initial task to make it possible to choose up to three players/users, and I have made it possible to roll the dices three times for each player/user.
Most probably it is possible to make it even easier (with less code), but so far it is working. The next part of the task is to make it possible to save dices, and only reroll some of them. I was thinking of making integers/variables like p1_keep1 (Player 1 Dice 1), p1_keep2 (Player 1 Dice 2), and so forth, but I am really stuck in how to implement it in the code to make it possible to save some dices and reroll the rest.
I thought about making a second loop under RollingDiceP1, RollingDiceP2 and RollingDiceP3 (see the code below for refference) where the dices are rolled, but I am unsure how to implement it, without making ittoo complicated. I tried with a while loop inside the do-while loop, but it became so complicated with ten of nested 'if else', so I deleted it, convinced there has to bea better way, though I have not manage to find/spot it yet.
In order to find a solution, is there something I can do to make my initial code "easier", or in other words, can I get the same result with less code?
If I could compress the code somehow, maybe it would be easier to spot/see the solution on how to save some of the dices, while re-rolling the rest.
As I said above, I did try a while loop inside the do-while loop, but it quickly became so vast and complicated that I could not manage to tag along, and I am convinced that there are better ways, though I have not managed to spot them yet. Any tip/help or push in the right direction would be appreciated. As you might spot in the code below, this is my third week with c, and as part-time student I have not been able to work that much with c yet. I am convinced there has to be a loop of some kind though, just not sure if while, do-while or for, is the most suitable one.
This is the challenge I am currently stuck in:
Challenge: Future implement your dice program so that the user can save some dice, and then only rolling the amount of dice that they haven't saved.Like you would normally do in Yahtzee.
My present code, looks like this, and help/tip or push in the right direction are highly appreciated:
/*
Author: Thorbjørn Elvestad
Student ID: XXXXX
E-mail: XXXXXXXXXXXXX#XXXXX.XXX
This is a Roll the Dice (for Yahtzee) simulation, where the computer rolls the dice,
and present the result to the users. Only the result is presented. The
user does not physically see the dice rolled. There can be a set number
of players, and each players got three rolls each before the next player
role.
This is Activity 1 of the Week 3 weekly activity.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Setting all functions to be used in the program */
void players (void);
void RollingDiceP1 (void);
void RollingDiceP2 (void);
void RollingDiceP3 (void);
/* Loading all global variables to be available for all functions in the program */
/* Setting variable for amount of players */
int numberPlayers = 0;
/* Setting variables for player 1-3 dices */
int p1_dice1 = 0, p1_dice2 = 0, p1_dice3 = 0, p1_dice4 = 0, p1_dice5 = 0;
int p2_dice1 = 0, p2_dice2 = 0, p2_dice3 = 0, p2_dice4 = 0, p2_dice5 = 0;
int p3_dice1 = 0, p3_dice2 = 0, p3_dice3 = 0, p3_dice4 = 0, p3_dice5 = 0;
/* Seting variable for allowed rounds of rolling the dice */
int rolldice_counter = 1;
char press_enter;
/*Initiating the main function */
int main(void)
{
/* Loading the Random Number generator */
srand(time(NULL));
printf("Howdy! \n");
printf("\n Welcome to the Roll a Dice Yahtzee Simulator, \n");
/* Loading functions for choosing amount of players */
players();
printf("Let us roll some dice! \n");
RollingDiceP1();
/* Checking if there are more players waiting for their turn */
while (1)
{
if (numberPlayers == 3)
{
printf("\n \n \n \n Player two, stay tuned... \n \n");
RollingDiceP2();
printf("\n \n \n \n Player three, stay tuned... \n \n");
RollingDiceP3();
break;
}
else if (numberPlayers == 2){
printf("\n \n \n \n Player 2, stay tuned... \n");
RollingDiceP2 ();}
else
printf("No more players waiting for rolling their dice, thanks for playing! \n");
break;
}
printf("No more players waiting for rolling their dices, thanks for playing! \n");
return 0;
}
/* Lets choose how many players to use the Yahtzee Roll Dice Simulator */
void players()
{
printf("Please type how many players (1-3):");
while (1)
{
scanf("%d", &numberPlayers);
if (numberPlayers == 1)
{
printf("You have selected %d players! ", numberPlayers);
break;
}
else if (numberPlayers == 2)
{
printf("You have selected %d players! ", numberPlayers);
break;
}
else if (numberPlayers == 3)
{
printf("You have selected %d players! ", numberPlayers);
break;
}
else printf("Invalid number of players, please choose 1-3 players:");
}
}
/* Rolling dices for player 1 */
void RollingDiceP1()
{
do
{
/* Rolling the dices, and fetching random numbers between 1-6 for Player 1 dices */
printf("\n Hold tight player 1, I am rolling your dices: \n");
p1_dice1 = rand() % 6 + 1;
p1_dice2 = rand() % 6 + 1;
p1_dice3 = rand() % 6 + 1;
p1_dice4 = rand() % 6 + 1;
p1_dice5 = rand() % 6 + 1;
/* Showing the result for player 1 */
printf("Your dices show:\n Dice 1: %d \n Dice 2: %d \n Dice 3: %d \n Dice 4: %d \n Dice 5: %d \n \n", p1_dice1, p1_dice2, p1_dice3, p1_dice4, p1_dice5);
printf("This is your roll number %d of 3 rolls, press any key and enter to continue \n", rolldice_counter);
scanf("%s", &press_enter);
} while (++rolldice_counter <= 3); /* Ending the do-while loop when rolldice_counter reach 0 */
rolldice_counter = 1;
}
/* Rolling dices for player 2 */
void RollingDiceP2()
{
do
{
/* Rolling the dices, and fetching random numbers between 1-6 for Player 2 dices */
printf("\n Hold tight player 2, I am rolling your dices: \n");
p2_dice1 = rand() % 6 + 1;
p2_dice2 = rand() % 6 + 1;
p2_dice3 = rand() % 6 + 1;
p2_dice4 = rand() % 6 + 1;
p2_dice5 = rand() % 6 + 1;
/* Showing the result for player 2 */
printf("Your dices show:\n Dice 1: %d \n Dice 2: %d \n Dice 3: %d \n Dice 4: %d \n Dice 5: %d \n \n", p2_dice1, p2_dice2, p2_dice3, p2_dice4, p2_dice5);
printf("This is your roll number %d of 3 rolls, press any key and enter to continue \n", rolldice_counter);
scanf("%s", &press_enter);
} while (++rolldice_counter <= 3); /* Ending the do-while loop when rolldice_counter reach 0 */
rolldice_counter = 1;
}
/* Rolling dices for player 3 */
void RollingDiceP3()
{
do
{
/* Rolling the dices, and fetching random numbers between 1-6 for Player 3 dices */
printf("\n Hold tight player 3, I am rolling your dices: \n");
p3_dice1 = rand() % 6 + 1;
p3_dice2 = rand() % 6 + 1;
p3_dice3 = rand() % 6 + 1;
p3_dice4 = rand() % 6 + 1;
p3_dice5 = rand() % 6 + 1;
/* Showing the result for player 3 */
printf("Your dices show:\n Dice 1: %d \n Dice 2: %d \n Dice 3: %d \n Dice 4: %d \n Dice 5: %d \n \n", p3_dice1, p3_dice2, p3_dice3, p3_dice4, p3_dice5);
printf("This is your roll number %d of 3 rolls, press any key and enter to continue \n", rolldice_counter);
scanf("%s", &press_enter);
} while (++rolldice_counter <= 3); /* Ending the do-while loop when rolldice_counter reach 0 */
rolldice_counter = 1;
}

C: Creating a game, but I'm getting an off by one error and an infinite loop error in certain cases

I'm in an intro to C class, and my professor has assigned us to code a game called "tea party" for our current assignment. I've finished coding the game, and it works for the most part, but there are some certain kinks that I can't seem to work out.
The rules of the game are simple: two players take turns spinning the spinner (emulated by entering "0" and pressing enter), and collecting all 7 items for the tea party. The first player to get all 7 items wins. The only catch is that you cannot collect a sandwich, fruit, or dessert unless you have a plate first. If you land on the LOSE A PIECE square, you must give up one of your pieces. Both of the errors come from the lose a piece instance in the game, so I'm thinking the error must originate from the "get_lost_piece" function.
One of them is that the pieces from the "player" array are numbered oddly in that they are 1 value higher than they should be. The other error is that when a player tries to remove their plate while they have an item that requires the plate, it should print out "Sorry, it is bad manners to eat without a plate. Enter another choice:", but instead, I get an infinite loop that reads "You lost item 1."
Here is the code I have:
#include <stdio.h>
#include <time.h>
#define SLOW_MODE 1
#define NUMPLAYERS 2
#define NUMPIECES 7
#define MAXLEN 20
#define NO_WINNER -1
const char CHOICES[NUMPIECES+1][MAXLEN] = {"PLATE", "NAPKIN", "TEA CUP", "CREAM AND SUGAR", "SANDWICH", "FRUIT", "DESSERT", "LOSE A PIECE"};
void update_player(int player[], int square);
int get_lost_piece(int player[]);
int search(int piece_list[], int choice);
int get_spin();
void init_player(int player[]);
int get_winner(int players[][NUMPIECES]);
int get_next_player(int player_num);
int count_pieces(int player[]);
void print_player(int player[], int player_num);
int main() {
srand(time(0));
int players[NUMPLAYERS][NUMPIECES];
// Initialize each player in the game.
int i;
for (i=0; i<NUMPLAYERS; i++)
init_player(players[i]);
int player_number = 0;
// Play until we get a winner.
int status = get_winner(players);
while (status == NO_WINNER) {
int dummy;
// In slow mode, we stop before every spin.
if (SLOW_MODE) {
printf("Player %d, it is your turn. Type 0 and enter to spin.\n", player_number+1);
scanf("%d", &dummy);
}
// Get the current player's spin and print out her pieces.
int square = get_spin();
printf("Player %d, have landed on the square %s.\n", player_number+1, CHOICES[square]);
update_player(players[player_number], square);
print_player(players[player_number], player_number+1);
// Update the game status.
player_number = get_next_player(player_number);
status = get_winner(players);
printf("\n\n");
}
printf("Congrats player %d, you win!\n", status+1);
return 0;
}
// Pre-conditions: player stores the contents of one player and square is in between 0 and 7, inclusive.
// Post-conditions: The turn for player will be executed with the given square selected.
void update_player(int player[], int square) {
if (square == 7) {
if (count_pieces(player) == 0)
{
printf("There is no piece for you to lose. Lucky you, sort of.\n");
return;
}
else{
int q;
q = get_lost_piece(player);
player[q]= 0;
}
return;
}
player[square]=search(player, square);
// Restricted by having no plate!
if (player[0] == 0) {
if(square == 4 || square == 5 ||square == 6){
printf("Sorry, you can't obtain that item because you don't have a plate yet.\n");}
else{
if (player[square] == 0){
player[square]++;
}
}
}
// Process a regular case, where the player already has a plate.
else {
if (player[square] == 0){
player[square]++;
}
}
}
// Pre-conditions: player stores the contents of one player that has at least one piece.
// Post-conditions: Executes asking a player which item they want to lose, and reprompts them
// until they give a valid answer.
int get_lost_piece(int player[]) {
int choice = -1;
// Loop until a valid piece choice is made.
while (1) {
if (choice == -1){
printf("Which piece would you like to lose?\n");
print_player(player,choice);
scanf("%d", &choice);}
if (player[choice] == 0 && choice < 7 && choice >= 0){
printf("Sorry, that was not one of the choices");
scanf("%d", &choice);
}
if (player[0] == 1 && choice == 4 || choice == 5 ||choice == 6){
printf("Sorry, it is bad manners to eat without a plate. Enter another choice:\n");
scanf("%d", &choice);
}
else{
printf("You lost piece %d\n", choice);
}
}
return choice;
}
// Pre-conditions: piece_list stores the contents of one player
// Post-conditions: Returns 1 if choice is in between 0 and 6, inclusive and corresponds to
// an item in the piece_list. Returns 0 if choice is not valid or if the
// piece_list doesn't contain it.
int search(int piece_list[], int choice) {
int i;
for (i=0; i<NUMPIECES; i++){
if(piece_list[i]==choice){
return 1;}
else {return 0;}
}
}
// Pre-condition: None
// Post-condition: Returns a random value in between 0 and 7, inclusive.
int get_spin() {
return rand() % 8;
}
// Pre-condition: None
// Post-condition: Initializes a player to have no pieces.
void init_player(int player[]) {
int j;
for (j=0; j< NUMPIECES; j++)
player[j]=0;
}
// Pre-condition: players stores the current states of each player in the tea party game.
// Post-condition: If a player has won the game, their 0-based player number is returned.
// In the case of no winners, -1 is returned.
int get_winner(int players[][NUMPIECES]) {
int i =0;
for (i=0; i<NUMPLAYERS; i++){
if(count_pieces(players[i]) == NUMPIECES) {
return i;}
}
return -1;
}
// Pre-condition: 0 <= player_num < NUMPLAYERS
// Post-condition: Returns the number of the next player, in numerical order, with
// a wrap-around to the beginning after the last player's turn.
int get_next_player(int player_num) {
player_num++;
if (player_num == NUMPLAYERS){
player_num = 0;
}
return player_num;
}
// Pre-conditions: player stores the contents of one player
// Post-conditions: Returns the number of pieces that player has.
int count_pieces(int player[]) {
int y, counter;
counter = 0;
for ( y = 0; y < 7; y++){
if(player[y] == 1){
counter++;
}
}
return counter;
}
// Pre-conditions: player stores the contents of one player and player_num is that
// player's 1-based player number.
// Post-conditions: Prints out each item the player has, numbered with the numerical
// "codes" for each item.
void print_player(int player[], int player_num) {
int i;
printf("\n");
printf("Player %d\n", player_num);
for (i=0; i < 7; i++){
if (player[i] == 1){
printf("%d. %s\n", i + 1, CHOICES[i]);
}
}
}
Thanks for the help in advance. I get the feeling that the solution is staring me right in the face, but after spending a couple of days on this, I'm having difficulty spotting the problem.
need #include <stdlib.h> for rand(), srand()
add player_number parameter to get_lost_piece() and pass it to print_player.
The following is just one idea for refactoring. It could be done many different ways.
Get input once at the start of the loop.
Use continue keyword in each if statement to redo the loop.
It works fine when I change the logic of get_lost_piece() to:
while...
get choice
if choice < 1 || choice > 7 "1-7 please..." continue
if player[choice - 1] == 0 "sorry..." continue
if choice == 1 (and player[] contains foods) "bad manners..." continue
return choice - 1;
Helpful hints
Loop should be limited and needs to give player a quit option.
Check out FAQ entry: scanf() returns errors, leaves stuff on input stream.
Test early, test often.
Turn up compiler warnings (as suggested by catcall)

Resources