Hangman Game using C issues - c

Newbie to C language and I'm trying to make a hangman game. I have the following code:
int main(void) {
char userResponse;//This is the response from the user on rather they want to continue or not.
do {
startGame();
printf("Do you want to continue (y or n): ");
scanf("%c", &userResponse);
} while(userResponse == 'y');
return 0;
}
int startGame(void) {
int num_letters = 0; //length of word array
int count = 0;
int tries = 0; //total tries player has used
int correctGuesses = 0; //number of correct guesses
int correctLetter = 0; //flag to check if the letter guessed was correct.
int repeatLetter = 0; //flag to check if the letter guessed was already guessed before.
int randomWord = 1+(rand()%6); //setting a variable that will pick a word from the word array at random.
char word[] = {"spot", "physicist", "penny", "klingon", "bazinga", "continuum"}; // should these be all lower char or does it matter?
char guess;
char incorrectGuesses[5] = " "; // all the incorrect letters chosen by the player will be stored in this array.
char gameWord[num_letters]; //starts to fill out the word as the player guesses correctly
srand(time(NULL)); // Don't really understand this line but the interweb said I needed it. Can you tell me why?
num_letters = strlen(word);
gameWord[num_letters] = '\0';
//This will show the player what letter they have typed incorrectly.
for(count = 0; count < num_letters; count++)
gameWord[count] = '-'; // This will display the length of the word represented with a "-".
printf("Welcome to Big Bang Hangman!\n\n");
printf("Time to guess the word!");
draw_hangman(tries);
while(tries < NUM_TRIES_ALLOWED) { //Player only gets 7 guesses. Found this on the interweb.
printf("Here is your word: %s\n", gameWord);
printf("Incorrect Letters: %s\n", incorrectGuesses);
printf("\nGuess a letter (and press 'Enter'): ");
fgets(&guess, sizeof(guess), stdin);
//This compares the current guess with the previous guesses so that you won't affect a turn if you pick the same incorrect letter.
for(count = 0; count < num_letters; count++)
if(guess == gameWord[count] || guess == incorrectGuesses[count]) { // If the player guess is equal to the size of the word or if its equal to the
repeatLetter = 1;
correctLetter = 1;
break;
}
if(repeatLetter == 0) // setting the flag back to 0 tells the compiler the game is over.
//Checks for matches in string
for(count = 0; count < num_letters; count++) {
if(guess == word[count]) { // can't understand why I'm getting this warrning.
gameWord[count] = guess;
correctGuesses++;
//if (correctGuesses == count) {
//printf("\n\nCONGRATULATIONS! You guessed the word %s!", gameWord);
//exit(0);
//}
if(correctGuesses == num_letters) {
printf("\n\nCONGRATULATIONS! You guessed the word %s!", gameWord);
exit(0);
}
correctLetter = 1;
}
}
if(correctLetter == 0) {
incorrectGuesses[tries] = guess;
tries++;
}
// reset both flags
repeatLetter = 0;
correctLetter = 0;
//startGame(); // Start the game over when the flag is reset.
}
printf("Sorry but you did not guess the word.\n");
printf("The word is: %s\n\n", gameWord);
return 0;
}
It is outputting the following:
Welcome to Big Bang Hangman!
Time to guess the word!
___
|
|
|
|
|
---
Here is your word: ----
Incorrect Letters:
Guess a letter (and press 'Enter'): Here is your word: ----
Incorrect Letters:
The last two lines continue on forever until I stop it. I'm completely lost.
Any advice would be great.

You have multiple (and I really mean that) problems in your code. But lets just pick one
char guess;
fgets(&guess, sizeof(guess), stdin);
is not the correct way to get the user to enter a letter. Maybe
scanf("%c", &guess);
would work better for you.
But really your approach is all wrong. Start again, write a few lines of code, get them working and then write a few more. You've written loads of code, lots of which is wrong. That's not a productive way to program.

Related

C - While loop runs twice when it shouldn't

Hi I'm making a simple Hangman game in C
I have a while Loop that is suppose to wait for the user to input a character. However, it skips pass that on the 2nd iteration.
void startGuessing(char *word){
char dummyWord[13];
strcpy(dummyWord, word);
int dummyWordLength = strlen(dummyWord);
for (size_t i = 0; i < dummyWordLength; i++)
{
dummyWord[i] = '_';
}
int remaindingChances = 7;
while(remaindingChances > 0){
printf("Player 2 has so far guessed: %s\n", dummyWord);
printf("Player 2, you have %d guesses remaining. Enter your next guess:\n", remaindingChances);
char guess;
guess = getchar();
int wordLength = strlen(word);
for (size_t i = 0; i < wordLength; i++)
{
if(guess == word[i]){
dummyWord[i] = word[i];
}
}
remaindingChances--;
}
}
The following is the output I'm seeing:
Player 2 has so far guessed: ___
Player 2, you have 7 guesses remaining. Enter your next guess:
c
Player 2 has so far guessed: c__
Player 2, you have 6 guesses remaining. Enter your next guess:
Player 2 has so far guessed: c__
Player 2, you have 5 guesses remaining. Enter your next guess:
Am i doing something wrong? O.o I can't seem to figure out this issue.
The simplest fix is probably to consume whitespace by replacing the guess = getchar() with something like:
int guess;
while( isspace(guess = getchar()) ) { ; }
(Note that getchar returns an int, and you should get in the habit of declaring the variable as an int.)
If you want to allow words that contain whitespace, you could use while( (guess = getchar()) != '\n' ) or similar. Whatever logic you want to use, you need to handle all the data, including the newlines. (and be aware of the possibility of \r\n on the input)
Consider using
scanf(" %c", &guess);
for your input.
You can implement further logic to to make sure the input is a letter, but this should fix your current problem

I'm trying to make a program in C in which you can play hangman but as soon as it prints the option to guess the letter the program terminates

The program isn't printing after giving me the first chance to guess.
#include <stdio.h>
#include <string.h>
int main() {
char menu;
int c = 0, flag = 0, life = 8;
printf("\nWelcome to Hangman!!!");
printf("\nThis is a game of hangman.");
printf("Player 1 enters a random word and the other has to guess it.");
printf("You get 8 lives in total i.e. you can have a maximum of 8 wrong guesses.");
printf("\n");
printf("Press n for new game\n");
printf("Press q to quit\n");
printf("\n");
scanf("%c", &menu);
int i = 0, j = 0;
char w[20], ch;
if (menu == 'q') {
printf("Exiting...");
printf("Thanks for playing");
}
else if (menu == 'n') {
printf("Player 1 enters a word\n");
scanf("%s", w);
int len = strlen(w);
for (int i = 0; i < len; i++) {
toupper(w[i]);
}
printf("\e[1;1H\e[2J");
char arr[len - 1];
for (int i = 0; i < len - 1; i++) {
arr[i] = '_';
printf("%c", arr[i]);
}
printf("\n");
while (life != 0) {
for (int i = 0; i < len - 1; i++) {
if (arr[i] == '_') {
flag = 1;
break;
}
else {
flag = 0;
}
}
if (flag == 0) {
printf("You Won!!\n");
printf("You Guessed The Word: %s", w);
break;
}
else {
char ans;
printf("Enter a letter between A-Z");
scanf("%c", ans);
toupper(ans);
for (int j = 0; j < len; j++) {
if (ans == w[j]) {
arr[j] = ans;
c++;
}
}
if (c == 0) {
life--;
}
c = 0;
for (int j = 0; j < len; j++) {
printf("%c", arr[j]);
}
printf("\n Lives Remaining= %d \n", life);
}
}
if (life == 0) {
printf("\n You Lost!!! \n");
printf("The Word Was: %s", w);
}
}
else {
printf("Invalid Character");
}
}
Output:
Welcome to Hangman!!!
This is a game of hangman.Player 1 enters a random word and the other has to >guess it.You get 8 lives in total i.e. you can have a maximum of 8 wrong >guesses.
Press n for new game
Press q to quit
n
Player 1 enters a word
Hello
Enter a letter between A-Z
PS C:\Users\arora\Desktop\Programs\C>
There are quite a few problems with your program. Here are the major ones:
You want to use use space prefix in the format string for scanf(" %c", ...) to ensure previous newlines are ignored.
scanf("%c", ans); should be &ans. It causes scanf() to fail rendering the remain of the program non-interactive. Without input from the user the core game logic doesn't work.
Here are some of the other issues:
#include <ctype.h>.
(not fixed) Consider changing the menu logic so 'q' quits, and any other letter starts a game.
Game prompt contains long lines that are hard to read for the player(s).
You use a printf() per line which makes it hard to read. Use a single call and multi-line strings as input.
Try to branch your code less by making use of early return. It makes it easier to read.
Check the return value of scanf(). If it fails then whatever variable it read doesn't have a well defined value.
Ensure that scanf() read no more than 19 bytes into a 20 byte array w. It takes a little macro magic to generate the 19 so I didn't make this change but it's a good idea to #define constants for magic values like the 20.
arr is not \0 terminated (len-1). Most c programmers expect a string so it's not worth the confusion to save 1 byte.
Use a function or macro for the ANSI escape to clear the screen.
Eliminate unused variables i, j.
Reduce scope of variables (declare variables close to where you use them).
The calculation of the flag variable is cumbersome.
(not fixed) The prompt "Enter a letter between A-Z" is somewhat ambiguous. Suggest "... between A and Z".
It's generally a good idea to leave user input as you read. If you care about the repeated toupper() you can create a copy of the user input with letters in upper case, and create another variable to hold the upper case version of the player's guess. This avoid you saying things like you entered the word "BOB" when the actual input was "bob".
You attempt to use toupper() to convert each letter to upper case but don't assign the result to anything so it does not do anything constructive.
Consider some functions to document what each your code does. I added some comments for now.
(mostly not fixed) Consider using better variable names (c, w, arr, flag).
(not fixed) Should you reject a word with your magic '_' value? In general should you validate that the word is reasonable (a-z, len > 0, len < 20)?
(not fixed) Consider, in arr, just storing if a letter was correctly guess (boolean). When evaluating the state show the letter from w if it is already guessed otherwise the _.
(not fixed) If you guess a correct letter again, it's considered a good guess. Should it?
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define clear() printf("\e[1;1H\e[2J")
int main() {
printf(
"Welcome to Hangman!!!\n"
"\n"
"This is a game of hangman.\n"
"Player 1 enters a random word and the other has to guess it.\n"
"You get 8 lives in total i.e. you can have a maximum of 8 wrong guesses.\n"
"\n"
"Press n for new game\n"
"Press q to quit\n"
);
char menu;
if(scanf(" %c",&menu) != 1) {
printf("scanf failed\n");
return 1;
}
switch(menu) {
case 'q':
printf(
"Exiting..."
"Thanks for playing\n"
);
return 0;
case 'n':
break;
default:
printf("Invalid Character");
return 1;
}
printf("Player 1 enters a word\n");
char w[20];
if(scanf("%19s", w) != 1) {
printf("scanf failed\n");
return 1;
}
clear();
char arr[20];
int len=strlen(w);
for(int i=0;i<len;i++) {
arr[i]='_';
}
arr[len] = '\0';
int life=8;
for(;;) {
printf("%d Lives Remaining\n", life);
// read a guess from player
for(int i = 0; i < len; i++) {
printf("%c", arr[i]);
}
printf(" Enter a letter between A-Z ");
char guess;
if(scanf(" %c", &guess) != 1) {
printf("scanf failed\n");
return 1;
}
// determine if any of the letters are in the secret word
int c = 0;
for(int i=0; i<len; i++) {
if(toupper(guess) == toupper(w[i])) {
arr[i]=guess;
c = 1;
}
}
if(c==0) {
life--;
}
// game over?
int flag = 0;
for(int i = 0; i<len; i++) {
if(arr[i]=='_') {
flag=1;
break;
}
}
if(flag==0) {
printf("You Won!!\n");
printf("You Guessed The Word: %s\n",w);
break;
}
if(life==0) {
printf("\n You Lost!!!\n");
printf("The Word Was: %s\n", w);
break;
}
}
}

A Hangman game is not working when entering a guess, but a random word form list work

I am trying to write the logic for the Hangman game.
I want to be able to enter a word and to get a random word from a list.
The part in which that I choose a random word works great without a problem. The problem starts when I enter a word. No matter if I am guessing the correct char it will still count as a strike.
What is the explanation for why this is happening?
int main()
{
int option=5, randomword;
bool loop = true;
// here you choose if you want a random word or to enter one by yourself.
while (loop)
{
printf("choose an option:\n0 to enter a word.\n1 for the computer to choose a word for you.\n");
scanf("%d", &option);
// start the loop over again if the value that got scan is not 0 or 1;
if (option == 0 || option == 1)loop = false;
}
char EnterdWord[128];
// if you choose to enter a word it will scan it and enter it to a string. I am using fgets so you can enter space
if (option == 0)
{
printf("enter a word:\n");
getchar();
fgets(EnterdWord , 128, stdin);
}else // if you want a random word, this will make a random number, so later it will choose a random word from a list.
{
srand(time(NULL));
randomword = rand() % 20 ;
}
// random words list
char RanWord[][20] = {"dog", "cat", "sky", "orange", "apple", "movie", "code", "number" ,"ship" ,"google" ,"sushi" , "shower",
"super hero", "job interview" ,"computer" ,"video games" ,"pizza" ,"cell phone", "charger", "bottle"};
char *TempWord = malloc(1024 * sizeof(char));
// remove the \n from the scan in fgets.
if (*EnterdWord && EnterdWord[strlen(EnterdWord)-1] == '\n')EnterdWord[strlen(EnterdWord)-1] = 0;
// give to the string TempWord the word based on the option u choose
if (option == 0) strcpy(TempWord, EnterdWord);
if (option == 1) strcpy(TempWord, RanWord[randomword]);
//this is the string that you are going to scan your right guess.
char *NiceWord = malloc(1024 * sizeof(char));
if (NiceWord == NULL) return 0;
// copy temp word to nice word
strcpy(NiceWord, TempWord);
// finding the length of the word for the loop below (I know I can use while != \0)
int lengh = strlen(TempWord);
int i=0;
// this part is for aesthetics. I could have just changed all the characters to space.
while(i < lengh)
{
if (TempWord[i] != ' ')NiceWord[i]='_';
if (TempWord[i] == ' ')NiceWord[i]=' ';
i++;
}
loop = true;
char guess;
// bool verb to check for strikes.
bool CheckStrike = true;
int y, strikes=0;
// print so you can see how many characters the word is.
printf("\n%s\n", NiceWord);
while (loop == true)
{
y=0;
//scan your guess.
printf("enter your guess:\n");
getchar();
scanf("%c", &guess);
// reset the strike checker in case you where right for the last guess
CheckStrike = true;
// check if your guess is correct or not.
while(TempWord[y] != '\0')
{
if ( TempWord[y] == guess)
{
NiceWord[y] = guess;
CheckStrike = false;
}
y++;
}
// if your guess was false, add one strike
if (CheckStrike == true)strikes++;
printf("you have %d strikes left\n", 10-strikes);
printf("%s\n", NiceWord);
// check if you lost
if (strikes == 10)
{
printf("the word was: %s\nyou lost :( ", TempWord);
loop = false;
}
// check if you won
if (strcmp (NiceWord, TempWord) == 0)
{
printf("\n\n\n\nu won :) with %d strikes left!\n\n\n\n\n", 10-strikes);
loop = false;
}
}
return 0;
}
Use:
printf("enter your guess:\n");
if (option == 1)
getchar();
scanf("%c", &guess);
if (option == 0)
getchar();
This solves the problem.

Letter Guessing Game in C

The error I got was that the number of game wasn't shown correctly.
For example, I chose to play 2 games. I, then, tried to guess the first number correctly. The solution was shown and then jumped to the next game. However, the second game was shown as Game 3 instead of Game 2.
I tried again. This time, I guessed the letter 1 time incorrectly and 1 time correctly. After the second guess, the game showed the solution and then stopped the game despite me choosing to play 2 games and only 1 game was played.
The order of letters in LetterList file is
d
B
G
w
Q
t
r
Y
u
X
So the first game starts with 'd' and then 'B' and then etc....
The error was shown as if the program itself got rid of even numbers.
I don't know what was wrong with it.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>
#define MAXGUESSES 5
void LetterGuessRules();
void GuessTheLetter(char);
char GetTheGuess();
int CompareLetters(char, char);
int main()
{
FILE *inPtr;
int numGames, i = 0;
char letter;
//display the game rule
LetterGuessRules();
printf("\nHow many games do you want to play? (Max 10) >> ");
scanf("%d", &numGames);
printf("\n\n************************************************\n");
inPtr = fopen("letterList.txt", "r");
for (i = 0; i < numGames; i++)
{
//get a solution letter from file - use fscanf
fscanf(inPtr," %c", &letter);
//change the solution to lowercase
letter = tolower(letter);
//print the solution back onto the screen to test
//Close this when play the game to hide the foreseen solution
printf("\nThe letter is %c\n", letter);
//Number of match
printf("\t\tGame %d\n", i += 1);
//call the GuessTheLetter function and pass it the solution
GuessTheLetter(letter);
}
fclose(inPtr);
return 0;
}
void GuessTheLetter(char letter)
{
int win = 0;
int numGuesses = 0;
char myGuess;
while (numGuesses < MAXGUESSES && win == 0)
{
//get a guess from the user by calling the GetTheGuess function
myGuess = GetTheGuess();
//change the guess to lowercase
myGuess = tolower(myGuess);
//win = call the function to compare the guess with the solution
win = CompareLetters(letter, myGuess);
numGuesses++;//count the number of guesses so far
//use conditions to let the user know if they won or lost the round of the game
if (win == 0)
{
printf("\nOops its wrong.\n");
if (myGuess < letter)
{
printf("Your guessed letter -%c- comes before the solution\n", myGuess);
printf("Please guess again :)\n");
}
else if (myGuess > letter)
{
printf("Your guessed letter -%c- comes after the solution\n", myGuess);
printf("Please guess again :)\n");
}
if (numGuesses == MAXGUESSES && win == 0)
printf("Aw you have lost this game!");
printf("\n");
}
else if (win == 1)
{
printf("\nYou have guessed it right!\n");
printf("Wonderful! You ACE'd this match!\n");
printf("\n");
printf("**** If you play more than 1 game, new match will automatically start ****\n");
printf("\tYou only need to keep guessing for the next letter\n");
printf("------------------------------------------------------------------------------");
printf("\n");
}
}
}
char GetTheGuess()
{
char myGuess;
printf("\t_______________________");
printf("\n\t|What's your guess? >> ");
scanf(" %c", &myGuess);
return myGuess;
}
void LetterGuessRules()
{
printf("\n*** Instruction: ");
printf("\nYou will have 5 attempts to guess the right answer");
printf("\nIf you guess it right, the game will end with your victory.");
printf("\nOtherwise, you will have to guess again.");
printf("\nPlease have fun!");
}
int CompareLetters(char letter, char myGuess)
{
if (letter == myGuess)
{
return 1;
}
else
{
return 0;
}
}
The problem is you increment i twice. First in the for loop, and again here:
//Number of match
printf("\t\tGame %d\n", i += 1);
This is probably because you got Game 0 without it. The simple fix is to start the loop at 1 instead of 0.
Since i means something more than the "loop iterator" I'd call it something more descriptive like gameNum.
/* from 1 to numGames */
int gameNum;
for( gameNum = 1; gameNum <= numGames; gameNum++ ) {
...
}
Note that I check gameNum <= numGames rather than gameNum < numGames since we're now starting from 1.
Also you need to check if the file opened, otherwise it crashes if letterList.txt doesn't exist.
#include <errno.h> /* for errno */
#include <string.h> /* for strerror() */
#include <stdlib.h> /* for exit() */
inPtr = fopen("letterList.txt", "r");
if( inPtr == NULL ) {
fprintf(stderr, "Could not open letterList.txt: %s\n", strerror(errno));
exit(1);
}
Finally, I'd recommend against using #define _CRT_SECURE_NO_WARNINGS while learning C. Those security warnings are important.

C Code - Guessing Game - Function Issues

Ok, been looking at this for hours now and could be just because it's late, but I'm braindead. So the code is supposed to accomplish the following:
Display instructions
Ask user for number of games to play
For each game
a. get a letter from file
b. Play one game
i. While still has guesses
ii. Get guess from player
iii. Compare guess to letter from file
iv. If guess is correct, return 1
v. Else increase counter
vi. Return 0 if 5 guesses incorrect
c. check for win or lose
This is the code I have so far, any ideas how to get this thing to run properly?:
#define _CRT_SECURE_NO_WARNINGS
#define MAXGUESSES 5
#include <stdio.h>
//Pre-Processor Directives
void gameRules();
//Game Instructions
int singleGame(char fileLetter);
//Checks guesses, returns 0 after 5 incorrect attempts
char retrieveGuess();
//Prompts user for guess and returns guess
//Called from inside singleGame function
int guessedIt(char answer, char inputLetter);
//Lets user know if answer comes before or after their guess.
//Returns 1 if answer is correct, and 0 for incorrect.
//Called from inside singleGame function.
int main()
{
char fileLetter = 'a';
FILE* filePtr;
int numOfGames = 0;
int counter = 0;
//run it
//Rules of Game
gameRules();
//File pointer that opens the file, "r" stands for reading the file
filePtr = fopen("lettersin.txt", "r");
/* File checking if-else
if (filePtr == NULL)
{
printf("I don't exist");
}
else
{
printf("I'm alive");
}
*/
printf("How many games would you like to play? (Pick from 1-4)\n");
scanf("%d", &numOfGames);
for (counter = 0; counter < numOfGames; counter++)
{
//Pulls a letter from the file and writes it to variable "fileLetter"
//Note to self: make sure to include "filePtr" so fscanf knows where to pull from
fscanf(filePtr, " %c", &fileLetter);
singleGame(fileLetter);
}
//Closes file, not necessary now, but good for later on in bigger programs that may need more files
fclose(filePtr);
return 0;
}
//Game rules function
void gameRules()
{
printf("Welcome to the Letter Guessing Game\n");
printf("You will enter the number of games you want to play (1-4 games).\n");
printf("You have 5 chances to guess each letter.\n");
printf("Let's begin:\n");
}
//Single Game Function
int singleGame(char fileLetter)
{
int numGuesses = 0;
while (numGuesses < MAXGUESSES)
{
retrieveGuess();
numGuesses = numGuesses + 1;
}
return 0;
}
//Guess retrieval function
char retrieveGuess()
{
char inputLetter;
printf("What is your guess? (Lowercase letters only, please)\n");
scanf(" %c", &inputLetter);
int guessedIt(char fileLetter, char inputLetter);
}
//Correct, or not, function
int guessedIt(char fileLetter, char inputLetter)
{
if (fileLetter == inputLetter)
{
printf("You guessed it!\n");
return '1';
}
else if (inputLetter < fileLetter)
{
printf("The letter comes after your guessed letter.\n");
return '0';
}
else
{
printf("The letter comes before your guessed letter.\n");
return '0';
}
}
A few things:
//Single Game Function
int singleGame(char fileLetter)
{
int numGuesses = 0;
while (numGuesses < MAXGUESSES)
{
retrieveGuess();
numGuesses = numGuesses + 1;
// You should return 1 here if the guess is right, no?
// Something like:
// char guessedChar = retrieveGuess();
// place call for function guessedIt here and if it
// is 1 return the result (if it's 0, don't return, let it keep looping)
}
return 0;
}
This function:
//Guess retrieval function
char retrieveGuess()
{
char inputLetter;
printf("What is your guess? (Lowercase letters only, please)\n");
scanf(" %c", &inputLetter);
int guessedIt(char fileLetter, char inputLetter);
}
Isn't returning anything. You need a return statement for each function that you define as returning something. Also, I don't think the last statement even makes sense, just return inputLetter
This function:
//Correct, or not, function
int guessedIt(char fileLetter, char inputLetter)
{
if (fileLetter == inputLetter)
{
printf("You guessed it!\n");
return '1';
}
else if (inputLetter < fileLetter)
{
printf("The letter comes after your guessed letter.\n");
return '0';
}
else
{
printf("The letter comes before your guessed letter.\n");
return '0';
}
}
Is returning a char ('1'/'0') even though it declares to be returning an int. You want to write return 1;/return 0;. You should place it where I put the comments

Resources