I am having a problem with my program getting stuck on waiting for input after using getchar(). I used a loop to clear the buffer and the same functionality appears four times in my program but only on two instances of this while loop it gets stuck and I cannot understand why.
In the two working instances, the only difference is the missing else if statement but when I remove it from the non-working instances, the problem is not solved and they are still stuck on waiting for a second ENTER.
If I enter anything else than 'y' or 'Y', I am getting the 'invalid input' message and then I am asked for an input again so this functionality works. However, when I enter 'y' or 'Y', followed by ENTER, a new line appears and nothing happens. If I enter invalid input again, I am getting the 'invalid input' message and with correct input, I still get a new line and nothing happens. Only after a second ENTER after a correct input the code continues as it should.
A non-working instance:
printf("Play a game? (Y/N): ");
while (!is_valid) {
user_choice = getchar();
char ch;
while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer
if (user_choice == 'y' || user_choice == 'Y') {
is_valid = true;
play_game();
}
else if (user_choice == 'n' || user_choice == 'N') break;
else {
printf("Invalid input. Try again.\n");
}
}
A working instance:
printf("Roll dice ('R')\n");
while (!is_valid) {
first_roll = getchar();
char ch;
while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer
if (first_roll == 'r' || first_roll == 'R') {
is_valid = true;
}
else {
printf("Invalid input. Try again.\n");
}
}
Full code:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h> // For rand()
/*
2025年02月19日
RULES
Come-Out Roll:
You roll two dice.
- If the sum is 7 or 11, you win right away.
- If the sum is 2, 3, or 12 (called "craps"), you lose immediately.
- If the sum is 4, 5, 6, 8, 9, or 10, that number becomes your point.
Point Phase:
Once a point is set, you keep rolling the dice.
- If you roll the point number again before rolling a 7, you win.
- If you roll a 7 before the point, you lose.
*/
int roll_dice(void);
bool play_game(void);
int main() {
int roll = 0;
char user_choice;
bool is_valid = false;
// Game loop
printf("Play a game? (Y/N): ");
while (!is_valid) { // In this loop it waits for a second ENTER
user_choice = getchar();
char ch;
while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer
if (user_choice == 'y' || user_choice == 'Y') {
is_valid = true;
play_game();
}
else if (user_choice == 'n' || user_choice == 'N') break;
else {
printf("Invalid input. Try again.\n");
}
}
return 0;
}
int roll_dice(void) {
// Generate 2 random numbers 1-6
int dices = (rand() % 12 + 1);
// Sum the numbers
return dices;
}
bool play_game(void) {
bool result = false;
bool is_valid = false;
bool game_has_ended = false;
char first_roll;
char user_choice;
int roll_result;
getchar();
// One dice roll
printf("Roll dice ('R')\n");
while (!is_valid) { // This loop goes fine
first_roll = getchar();
char ch;
while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer
if (first_roll == 'r' || first_roll == 'R') {
is_valid = true;
}
else {
printf("Invalid input. Try again.\n");
}
}
roll_result = roll_dice();
int roll = 1;
int point = 0;
// Evaluate roll
if (roll == 1)
{
switch (roll_result) {
// Immediate win
case 7: {
result = true;
point = 0;
break;
};
case 11: {
result = true;
point = 0;
break;
};
// Immediate lose
case 2: {
result = false;
break;
};
case 3: {
result = false;
break;
};
case 12: {
result = false;
break;
};
// Point
case 4: {
roll = 2;
point = 4;
result = true;
break;
};
case 5: {
roll = 2;
point = 5;
result = true;
break;
};
case 6: {
roll = 2;
point = 6;
result = true;
break;
};
case 8: {
roll = 2;
point = 8;
result = true;
break;
};
case 9: {
roll = 2;
point = 9;
result = true;
break;
};
case 10: {
roll = 2;
point = 10;
result = true;
break;
};
}
}
// Roll 1 results
if (result == false) {
printf("Roll 1: %d\n", roll_result);
printf("You lose!\n");
game_has_ended = true;
}
else if (result == true && roll == 1 && point == 0) {
printf("Roll 1: %d\n", roll_result);
printf("You win!\n");
game_has_ended = true;
}
else {
// Roll 2
if (roll == 2 && point > 0) {
printf("Point: %d\n", roll_result);
char roll_2;
bool is_valid = false;
while (!is_valid) { // This loop goes fine
printf("Press 'R' to roll again.\n");
roll_2 = getchar();
char ch;
while ((ch = getchar()) != '\n' && ch != EOF) {}
if (roll_2 == 'r' || roll_2 == 'R') {
is_valid = true;
}
else {
printf("Invalid input. Try again.\n");
}
}
// Roll 2 results
switch (roll_dice()) {
case 7: {
result = false;
printf("Roll 2: %d\n", roll_dice());
printf("You lose!\n");
game_has_ended = true;
break;
}
default: {
result = true;
printf("Roll 2: %d\n", roll_dice());
printf("You win!\n");
game_has_ended = true;
break;
}
}
}
}
// Recursion
is_valid = false;
printf("Play another game? (Y/N): ");
while (!is_valid) { // In this loop it waits for a second ENTER
user_choice = getchar();
char ch;
while ((ch = getchar()) != '\n' && ch != EOF) {}
if (user_choice == 'y' || user_choice == 'Y') {
is_valid = true;
play_game();
}
else if (user_choice == 'n' || user_choice == 'N') return game_has_ended;
else {
printf("Invalid input. Try again.\n");
}
}
return game_has_ended;
}
Can you give me a hint of what I am doing wrong?