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>
CodePudding user response:
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 causesscanf()
to fail instead of reading any input from user so it appears to be non-interactive. Without input from the user the core game logic doesn't work as comparing a guess against the word 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 arrayw
. 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 fromw
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("s", 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;
}
}
}