Thread: Either my loop is bad or my function is messed up

1. When doing a flowchart, you do not need to mess around with the technicalities of do/while/for.
Write the flow of the code as it makes most sense. Then we translate it into code.

2. How does the logic look for this -

Code:
```BEGIN MAIN
declare variables
give option to view rules

if the game is not over or we are playing again
BEGIN LOOP1
BEGIN LOOP2
roll dice
print outcome, calculate points, determine status
END LOOP2

If status = 1, then ask to play another round
if answer is yes, then begin loop again
if answer is no then switch player and BEGIN LOOP1  as other player

else if status = 0
switch players and BEGIN LOOP1 as other player

if the game is over
print totals for both players
END LOOP1
give option to play again
if yes, then begin LOOP1
if no, then STOP
END MAIN```
crazychile

3. I think you are beginning to get somewhere, but I am concerned because you seem to have lots of conditions all over the place. It is never a good thing.
There is something about the logic that I cannot quite puzzle... especially that first...
"if the game is not over or we are playing again"
...is it really necessary?

4. Originally Posted by Elysia
I think you are beginning to get somewhere, but I am concerned because you seem to have lots of conditions all over the place. It is never a good thing.
There is something about the logic that I cannot quite puzzle... especially that first...
"if the game is not over or we are playing again"
...is it really necessary?
Wouldn't that be the condition in which the loop would need to be executed?

As to the others, I don't understand how to simplify the conditions any more.

I'm completely open to suggestions....

Thank you,
crazychile

5. Code:
```BEGIN MAIN
declare variables
give option to view rules

if the game is not over or we are playing again
BEGIN LOOP1
BEGIN LOOP2
roll dice
print outcome, calculate points, determine status
END LOOP2

If status = 1, then ask to play another round
if answer is yes, then begin loop again
if answer is no then switch player and BEGIN LOOP1  as other player

else if status = 0
switch players and BEGIN LOOP1 as other player

if the game is over
print totals for both players
END LOOP1
give option to play again
if yes, then begin LOOP1
if no, then STOP
END MAIN```
The green bit really really really really really really really really needs to be inside LOOP2 -- since currently LOOP2 never stops, and of course you can't repeat it once you've left it. Similarly, the conditions for restarting LOOP1 aren't that complicated, nor should they appear in a bunch of different places -- you restart LOOP1 unless they say "no I don't want to play another game". So that's your check on that loop. And again, that needs to be inside LOOP1, because you can't repeat it once you've left it. So you have LOOP1 that works on the game level, LOOP2 that gets you through a single turn, and you probably need to have LOOP3 that repeats turns until somebody wins.

6. Thank you.

The way I currently have it written the green stuff actually was inside that loop for the turn.

I have revised my chart a bit. I'm not really sure about the 3rd loop. I think I am essentially doing the same thing with two loops, but maybe not. It may be a matter of placing the final print statement.

My revised diagram:
Code:
```BEGIN MAIN
declare variables
give option to view rules

if the game is not over or we are playing again
BEGIN GAME LOOP
BEGIN TURN LOOP
roll dice
print outcome, calculate points, determine status
If status = 1, then ask to play another round
if answer is yes, then begin loop again
END  TURN LOOP

if answer is no , or status = 0, switch player and BEGIN TURNLOOP

if the game is over
print totals for both players
END GAME LOOP
BEGIN GAME LOOP unless condition is no
END MAIN```
Thanks for the guidance,
crazychile

7. Code:
```BEGIN MAIN
declare variables
give option to view rules

BEGIN GAME LOOP
BEGIN TURN LOOP
roll dice
print outcome, calculate points, determine status
IF status = 1
ask to play another round
if answer is yes, then BEGIN TURNLOOP
IF answer is no, switch player and BEGIN TURNLOOP
ELSE
switch player and BEGIN TURNLOOP
END IF
END  TURN LOOP

if the game is over print totals for both players
LOOP WHILE user wants to play again
END MAIN```
I would be looking at something like this.
I am still confused as to what the Turn loop does.
I do not know what status is, and regardless of what happens, the loop begins anew again. Should the user not be able to choose if to play another round or not, and if not, another round should not be played?

8. Points are awarded per the roll combination. There are combinations where no points are awarded and the roll automatically goes to the other player. In cases where the roll yields a scoring combination, the player must decide if they want to continue. If they choose not to continue they keep all the points earned for the round and it goes to the next player. If they continue and then roll a non-scoring combination, they lose any points they had gained for the round and the turn passes to the other player.

The status (1) is a way to trigger a function to offer another roll for that player (it returns y/n). If the status is (0) then the function to offer another roll does not return a value and it goes to the next player. I coded the status in the various if/else statements in that loop.

So my thinking was to use something like "while (turnAgain(status) == 'y')" to re-execute the loop for another roll, and if(turnAgain(status) == 'n'), then it would just total up the amount for the round and change to the other player.

It seems simple enough but I always get compiler errors when I try this. (usually it expects something more before the closing brackets).

I've probably spent 50-60 hours on this project and its due on Tuesday (whats worse is that I have to present it to the class) So the pressure is pretty intense at this point. I think if I can get it to switch players under these conditions then I should be able to figure out the rest. All of my functions are written and should need minimal tweaking to work once I get my loop structure down.

Thanks for all your guidance everyone.
crazychile

9. Do you have a current version that you can post up?

10. Well, then how about:
Code:
```BEGIN MAIN
declare variables
give option to view

BEGIN GAME LOOP
BEGIN ROLL LOOP 1
BEGIN ROLL LOOP 2
roll dice
print outcome, calculate points, determine status
IF roll was a scoring combination, ask to play another round
LOOP IF users wants to play another round
Switch user
LOOP IF loop has executed 2 times

if the game is over print totals for both players
LOOP WHILE user wants to play again
END MAIN```
This looks more like a flowchart that is not complex nor hard to implement.
Of course, you can change the whole switch player to two loops if that makes it easier for you.

You have to think in how you would do it in real life instead of in code!
Code comes after you have thought out the flowchart.
Does this flow make sense to you?

11. Thanks Elysia, the flow does make sense.

Here is the current code: (yes, I know the spacing is messed up)

Code:
```#include <stdio.h>   // for interactive input and output
#include <stdlib.h>  // for the rand() function
#include <ctype.h>   // for tolower() macro
#define SIDES 6

typedef enum {doublesPoints, onesPoints, noPoints, singlesPoints} status;

// function: prnRules
// pre: none
// post: prints the rules
void prnRules(void)
{
printf("%s\n",
"The goal is to be the first player to reach 100 points.\n\n"
"On a turn, a player rolls the two dice repeatedly until either a 1 is rolled \n"
"or the player chooses to hold and stop rolling.\n\n"
"If a 1 is rolled, that player's turn ends and no points are earned for the round.\n"
"If the player chooses to hold, all of the points rolled during that round are added to their score.\n\n"
"If a player rolls double 1s, that counts as 25 points.\n"
"Other doubles are worth 2x double points, so that a 2-2 is worth 8 points; 3-3 is worth 12; \n"
"4-4 is worth 16; 5-5 is worth 20; and 6-6 is worth 24.\n\n"
"When a player reaches a total of 100 or more points, the game ends and that player is the winner.\n");
}

int rollDie ()
// function: rollDie
// pre: none
// post: generates a random number for the die
{
int d;

d = rand() % SIDES + 1;
return d;
}

status turnPoints(int die1, int die2)
// function: turnStatus
// pre: dice have been rolled
// post: returns the status of the roll (doublesPoints, onesPoints, no Points, singlesPoints)
{
if (die1 == die2 && !(die1 == 1 && die2 == 1))
return doublesPoints;

else if (die1 == 1 && die2 == 1)
return onesPoints;

else if ((die1 == 1 || die2 == 1) && !(die1 == 1 && die2 == 1))
return noPoints;

else
return singlesPoints;
}

int turnAgain(int status)
// function: turnAgain
// pre: Player must have rolled a non disqualifying point combination
// post: returns a valid (y or n) answer
{
char ans;

if (status == 1)
{
printf("TURNAGAIN Would you like to risk the points for this round and continue? (y or n)? ");
getchar();
ans = getchar();
} //while (tolower(ans) != 'y' && tolower(ans) != 'n');
}

//to switch the current player when the turn is over
int switchPlayer(int currentPlayer)
{
if (currentPlayer == 1)
return 2;
else
return 1;
}

char playAgain(int choice)
// function: playAgain
// pre: none
// post: returns a valid (y or n) answer
{
char ans;

do
{
if (choice == 1)
printf("PLAYAGAIN-Play another game (y or n)? ");
if (choice == 2)
printf("PLAYAGAIN-Do you want to risk it all and roll again (y or n)? ");
ans = getchar();
getchar();
} while (tolower(ans) != 'y' && tolower(ans) != 'n');
}
// function: gameOver
// pre:  none
// post: returns a '1' if either total exceeds 100
int gameOver (int p1Total, int p2Total)
{
if (p1Total || p2Total >= 100)
{
return 1;
}
else
{
return 0;
}
}

//The final print statement with all the totals
void finalOutput(int p1Total, int p2Total)
{
printf("\n");
printf("WE HAVE A WINNER!!!\n");
printf("Player 1 your final score was %d\n", p1Total);
printf("Player 2 your final score was %d\n", p2Total);
}

int updatePlayerTotal(int currentPlayer, int turnTotal, int playerTotal)
{

printf("UPDATEPLAYERTOTALPlayer %d, your total at the start of this turn was %d .\n",
currentPlayer, playerTotal);
playerTotal = playerTotal + turnTotal;
printf("Your total at the end of this turn is %d.\n", playerTotal);
return playerTotal;
}

int main (void)
{
// variable declarations
int sum;                  // for sum of two dice
char answer;              // for yes/no questions
int tempTotal = 0;        // temporary player total for the round
int p1Total = 0;	        // running total for player 1
int p2Total = 0;		     // running total for player 2
int total = 0;		        // player total after each round
int die1 = 0;             // the roll value of die1
int die2 = 0;             // the roll value of die2
int currentPlayer = 1;	  // start with Player 1
int status = 1;           // ability to choose to continue
int gameStatus = 1;

srand(time(NULL));       // seed random # generator

//do // play at least one game
{
//give option to view the rules
printf("Welcome to the game of Pig. Would you like to view the rules? (y or n)?\n");
getchar();
if (answer == 'y')
prnRules();

while (turnAgain(status) == 'y')
{
die1 = rollDie();
die2 = rollDie();
sum  = (die1 + die2);
printf("Die 1 is a %d.\n", die1);
printf("Die 2 is a %d.\n", die2);

//award points (rolled a double but not double 1's)
if (turnPoints(die1, die2) == doublesPoints)
{
printf(" Player %d, you rolled a double %d!\n ", currentPlayer, die1);
printf(" That's worth %d points.\n", (sum * 2));
tempTotal = (tempTotal + total + (sum * 2));
status = 1;
}

//award points (rolled double 1's)
else if (turnPoints(die1, die2)  == onesPoints)
{
printf(" Player %d, You rolled a double 1!\n ", currentPlayer);
printf(" That's worth 25 points.\n");
tempTotal = (tempTotal + total + 25);
status = 1;
}

//award  no points (one of the two dice = 1)
else if (turnPoints(die1, die2) == noPoints)
{
printf("Sorry Player %d, you rolled a single 1. You do not earn any points this round\n", currentPlayer);
printf("Your current total is %d\n", total);
tempTotal = 0;
total = total + tempTotal;
status = 0;
}

//award points (rolled singles)
else if (turnPoints(die1, die2) == singlesPoints)
{
printf("Player %d, your roll totals %d points.\n", currentPlayer, sum);
tempTotal = tempTotal + (total + sum);
status = 1;
}

}

if (turnAgain(status) == 'n')//(answer == 'n')
{
total = (tempTotal + total);
if (currentPlayer == 1)
{
p1Total = updatePlayerTotal(currentPlayer, tempTotal, p1Total);
}
else
{
p2Total = updatePlayerTotal(currentPlayer, tempTotal, p2Total);
}
currentPlayer = switchPlayer(currentPlayer);
}

//total the points for the player and switch to other player
/* (turnAgain(status) == 'n')//(answer == 'n')
{
total = (tempTotal + total);
if (currentPlayer == 1)
{
p1Total = updatePlayerTotal(currentPlayer, tempTotal,
p1Total);
}
else
{
p2Total = updatePlayerTotal(currentPlayer, tempTotal,
p2Total);
}
currentPlayer = switchPlayer(currentPlayer);
}*/

// if (gameOver(p1Total, p2Total) == 1)
//	 finalOutput (p1Total, p2Total);

// see if they want to play another game