C getchar() hangman game - c

I was given a homework assignment which tasked us with creating a simple hangman game. Below is the code I have. I am currently trying to use if else with getchar() to ask the user to input a lowercase letter and see if it matches one of the letters in the word they are supposed to guess. From my very limited experience the code I have should work and when I step through the program it appears as if it should run properly, but when I actually run the program it seems to skip over the second getchar(). Anyone have any suggestions or help?
#include "stdio.h"
#include "math.h"
int main(void) {
int(a);
int(b);
float(x);
float(c);
float(e);
int word[4] = {116, 101, 115, 116};
int guess[4];
c == 0;
a == 0;
b == 0;
printf("Welcome to Hangman\n");
printf("Input a word--one lower case letter at a time\n");
printf("Enter Guess: ");
x = getchar();
if (x > 122) {
printf(" Error, character must be a lowercase letter");
} else
if (x < 97) {
printf(" Error, character must be a lowercase letter");
} else
if (x == 116) {
printf("t is correct\n");
printf("%d", word[0]);
printf(" _");
printf(" _");
printf(" %d ", word[3]);
e = getchar();
if (e == 101) {
printf("e is correct\n");
printf("%d", word[0]);
printf(" %d", word[1]);
printf(" _");
printf(" %d ", word[3]);
} else
if (e == 115) {
printf("s is correct\n");
printf("%d", word[0]);
printf(" _");
printf(" %d", word[2]);
printf(" %d", word[0]);
} else {
printf(" You guessed wrong");
}
} else
if (x == 101) {
printf("e is correct\n");
printf("_");
printf(" %d", word[1]);
printf(" _");
printf(" _ ");
} else
if (x == 115) {
printf("s is correct\n");
printf("_");
printf(" _");
printf(" %d", word[2]);
printf(" _ ");
} else {
printf(" You guessed wrong");
}
}

When you input a character that you want getchar to read, you end it with the Enter key right? That Enter key will also be put into the input buffer of stdin (which is what getchar reads from) as a newline, '\n'.
That means for each input you give, you actually input two characters.
You need to skip that newline. This can easily be done by just adding a second getchar after the first, like for example
x = getchar();
getchar(); // Read the newline from the Enter key

There is already a good answer, but to clarify the
problem a little bit more, here is a simple piece of code.
The function get_character will return the first entered character
and consume all following characters until the next '\n'.
It is not going to block if one character is EOF.
#include<stdio.h>
int get_character(void);
int main(void)
{
printf("character > ");
int c = get_character();
while(c != EOF && c != 'q')
{
printf("You entered %c\n", c);
printf("character > ");
c = get_character();
}
}
int get_character(void)
{
int c = getchar(), next_c;
if(c == EOF)
{
return EOF;
}
next_c = getchar(); // consume all \n
while(next_c != '\n' && next_c != EOF)
{
fprintf(stderr, "WARNING: consumed non-newline character: 0x%x\n", next_c);
next_c = getchar();
}
return c;
}
By the way: You are able to solve the hangman way faster:
int get_character(void);
#define MAX_TRIALS 3
#define WORD_LEN 4
int main(void)
{
char word[WORD_LEN + 1] = "test";
char correct[WORD_LEN] = {0, 0, 0, 0};
int trials = 0;
while(1)
{
if(trials > MAX_TRIALS)
{
printf("You failed. The word was: %s\n", word);
return 0;
}
printf("character > ");
int c = get_character();
if(c == EOF)
{
printf("bye\n");
return 0;
}
int i, this_char_correct = 0;
for(i = 0; i < WORD_LEN; i++)
{
if(c == word[i])
{
correct[i] = 1;
this_char_correct = 1;
}
if(correct[i])
{
printf("%c", word[i]);
}
else
{
printf("_");
}
}
if(!this_char_correct)
{
trials++;
}
int word_done = 1;
for(i = 0; i < WORD_LEN; i++)
{
word_done &= correct[i];
}
if(! word_done)
{
printf("\nYou have %d trials left\n", WORD_LEN - trials);
}
else
{
printf("\nYou got it.\n");
return 0;
}
}
}
This is just a piece of proof-of-concept code there might be way more elegant ways to solve this.

Related

Repeating error message when trying to receive an integer in a specific range

The function below receives a range and then asks for an integer. It then must test to make sure it is in that range and is not a char. However, whenever I input any letters it just loops the "ERROR: Value must be between %d and %d inclusive: " msg.
void clearStandardInputBuffer(void)//clears character
{
while (getchar() != '\n')
{
;
}
}
int getIntFromRange(int lowbound, int upperbound)
{
int rangenum;
char newline = 'x';
while (1)
{
scanf(" %d%c", &rangenum, &newline);
if (rangenum <= upperbound && rangenum >= lowbound && newline == '\n')
{
return rangenum;
}
else
{
if (rangenum > upperbound || rangenum < lowbound)
{
printf("ERROR: Value must be between %d and %d inclusive: ", lowbound,upperbound);
}
else if (newline != '\n') {
clearStandardInputBuffer();
printf("ERROR: Value must be an integer: ");
}
}
}
return 0;
}
int main(void)
{
getIntFromRange(0, 1);
}
Looking for any help!

While-loop in C re-printing previous statements

when running the code, the while loop is re-printing the prompts asking for the user to pick an option and dimensions before printing the rectangle, when it should print the shape and then iterate through the prompts. What in the while loop would be causing those printf statements to re-print?
Code:
#include "testFile.h"
int draw_rectangle(char sym, int wid, int len){
if((wid == 0) || (len == 0)){
printf("Invalid data provided 2\n");
return 0;
}else{
int i;
int j;
for(i = 1; i <= wid; i++){
for(j = 1; j <= len; j++){
printf("%c", sym);
}
printf("\n");
}
return 1;
}
}
int main(){
int loopTrue = 1;
char character;
int length, width;
int userOption = 4;
while(loopTrue == 1){
printf("Enter 1(rectangle), 2(triangle, 3(other), 0(quit): ");
scanf("%d", &userOption);
if(userOption >= 4){
printf("Invalid data operation 1 \n");
}else if(userOption == 0){
printf("bye bye");
loopTrue = 0;
}else if(userOption == 1){
printf("enter a character, width, and length: ");
scanf("%c %d %d", &character, &width, &length);
draw_rectangle(character, width, length);
}else if(userOption == 2){
printf("not done\n");
}else if(userOption == 3){
printf("not done\n");
}
}
return 0;
}
Heres the Output
If I have understood correctly then you need to change the format string in this call of scanf
scanf("%c %d %d", &character, &width, &length);
to the following
scanf(" %c %d %d", &character, &width, &length);
^^^^
See the blank before the conversion specifier %c. It allows to skip white space characters as for example the new line character '\n' that can appear in the input buffer by pressing the Enter key.

Counting Dashes to Exit a While Loop in C

I made a hangman game using a while loop. I want to use the number of dashes == 0 to break the loop so the player knows that they won. The word is hidden behind "-"s. My word is coding, so it has 6 dashes.
When I run the program, the first guess at the word is an accurate number of dashes. But after the second guess, and so on, it is adding all of the dashes from all the guesses together, not just from that one turn. By the third turn it says I have 9 dashes because that's how many is left over in all of the turns. Any ideas on how to fix?
char word[] = { "Coding" };
char dash[] = {"------"};
char guess;
int numguesses = 10;
int count;
int loopcount;
int i;
int dashcount;
int main()
{
printf("Your Word Is: %s", &dash);
//printf("\nWord: %c", &dash);
loopcount = 10;
count = 1;
while (count <= loopcount)
{
printf("\n\nPick a letter to guess: ");
scanf(" %c", &guess);
printf("\n\nYour Guess Was %c. ", guess);
count = count + 1;
if (guess == 'c')
{
dash[0] = 'c';
printf("\n\n %s", dash);
}
else if (guess == 'o')
{
dash[1] = 'o';
printf("\n\n %s", dash);
}
else if (guess == 'd')
{
dash[2] = 'd';
printf("\n\n %s", dash);
}
else if (guess == 'i')
{
dash[3] = 'i';
printf("\n\n %s", dash);
}
else if (guess == 'n')
{
dash[4] = 'n';
printf("\n\n %s", dash);
}
else if (guess == 'g')
{
dash[5] = 'g';
printf("\n\n %s", dash);
}
else
printf("That Letter Is Not Apart of this Word");
printf("\n\nYou are at Guess Number %d, Your word is at %s", count, dash);
for (i = 0; dash[i]; i++)
{
if (dash[i] == '-')
{
dashcount++;
}
}
printf("\n\nDoes it work ?: %d", dashcount);
}
if (count < numguesses)
{
printf("\n\n\nYou Won the Game, Your Awesome!!");
}
else
{
printf("\n\n\nI'm Sorry, the word was %s.", word);
}
printf("\n\n");
return 0;
}
The issue is that you are not resetting the dashcount variable, so every time it starts with previous value and adds the dashes left
for (i = 0; dash[i]; i++)
{
if (dash[i] == '-')
{
dashcount++;
}
}
You can easily fix this in this way
dashcount=0;
for (i = 0; dash[i]; i++)
{
if (dash[i] == '-')
{
dashcount++;
}
}

Struggles with TicTacToe

I have written a program in C, that when runs, is supposed to allow the user to play a game of tic tac toe - or noughts and crosses, whether it be against the computer, or another user. I have nearly completed it, and it prints the grid out perfectly fine. However, when I go to input which row/column I want to place the symbol in, instead of inserting the symbol, it just removes a space in the grid, aligning it incorrectly. I have tried to put a loop in the main method which fills the grid in with spaces to try and prevent null values.
If anyone could suggest anything it would be much appreciated. Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void user_prompt();
void clear_board(char gameBoard[3][3]);
void display_board(char gameboard[3][3]);
void user_move(char gameBoard[3][3]);
void computer_move(char gameBoard[3][3]);
int detect_win(char gameBoard[3][3]);
int gameMode;
char symbol1;
char symbol2;
char nickname1[10];
char nickname2[10] = "TicTacBot";
char gameBoard[3][3];
char playerTurn[10];
int main(void){
int i, j;
char gameBoard [3][3];
clear_board(gameBoard);
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
gameBoard[i][j] = ' ';
}
}
i = 0;
j = 0;
user_prompt();
display_board(gameBoard);
if(gameMode == 2){
for(i = 0; i < 9; i++){
user_move(gameBoard);
display_board(gameBoard);
if(detect_win(gameBoard) == 1){
printf("The winner is %s!!!\n", nickname1);
}
if(detect_win(gameBoard) == 2){
printf("The winner is %s!!!\n", nickname2);
}
}
}
else{
user_move(gameBoard);
display_board(gameBoard);
for(i = 0; i < 4; i++){
printf("TicTacBot's move.\n");
computer_move(gameBoard);
display_board(gameBoard);
if(detect_win(gameBoard) == 1){
printf("The winner is %s!!!\n", nickname1);
}
user_move(gameBoard);
display_board(gameBoard);
if(detect_win(gameBoard) == 1){
printf("The winner is %s!!!\n", nickname2);
}
}
}
if(detect_win(gameBoard) == 0){
("The game ended in stalemate!\n");
}
return 0;
}
/*
Prompts the user to enter a nickname, what symbol they would like to use, and whether they'd rather play against the computer or another user.
*/
void user_prompt(void){
printf("Please choose whether you would rather play against the computer (enter '1'),or another user (enter '2'): \n");
scanf("%d", &gameMode);
getchar();
while(gameMode != 1 && gameMode != 2){
printf("Please enter a valid digit: \n");
scanf("%d", &gameMode);
getchar();
}
if(gameMode == 1){
printf("Please choose whether you would rather play as 'X' (enter 'x') or as 'O' (enter 'o'): \n");
scanf(" %c", &symbol1);
getchar();
if(symbol1 == 'x') {
symbol2 == 'o';
}
else{
symbol2 == 'x';
}
}
else{
printf("Player 1, would you like to play as 'X' (enter 'x') or as 'O' (enter 'o'): \n");
scanf(" %c", &symbol1);
getchar();
while(symbol1 != 'x' && symbol1 != 'o'){
printf("Please enter a valid symbol: \n");
scanf(" %c", &symbol1);
getchar();
}
if(symbol1 == 'x'){
symbol2 == 'o';
}
else{
symbol2 == 'x';
}
}
if(gameMode == 1){
printf("Please enter a nickname: \n");
fgets(nickname1, 10, stdin);
getchar();
}
else{
printf("Please enter a nickname for player 1: \n");
fgets(nickname1, 10, stdin);
getchar();
printf("Please enter a nickname for player 2: \n");
fgets(nickname2, 10, stdin);
getchar();
}
}
/*
Resets the game board.
*/
void clear_board(char gameBoard[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
gameBoard[i][j] = 0;
}
}
}
/*
Displays the game board and all symbols within it.
*/
void display_board(char gameBoard[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
printf(" %c ", gameBoard[i][j]);
if(j == 2){
printf("\n");
}
if(j != 2){
printf("|");
}
}
if(i != 2){
printf("---+---+---\n");
}
}
}
/*
Takes input of a position on the board from the user, then places the user's symbol into that space on the game board.
*/
void user_move(char gameBoard[3][3]){
int row;
int column;
if(playerTurn == nickname1){
printf("Would you like to enter your %c in row 1, 2 or 3? \n", symbol1);
scanf("%d", &row);
getchar();
printf("Would you like to enter your %c in column 1, 2 or 3? \n", symbol1);
scanf("%d", &column);
getchar();
}
else{
printf("Would you like to enter your %c in row 1, 2 or 3? \n", symbol2);
scanf("%d", &row);
getchar();
printf("Would you like to enter your %c in column 1, 2 or 3? \n", symbol2);
scanf("%d", &column);
getchar();
}
if(row < 1 || row > 3){
printf("Please enter a valid row number: \n");
scanf("%d", &row);
getchar();
}
if(column < 1 || column > 3){
printf("Please enter a valid column number: \n");
scanf("%d", &row);
getchar();
}
if(gameBoard[row-1][column-1] != ' '){
printf("The position you entered is already taken. Try again! \n");
display_board(gameBoard);
user_move(gameBoard);
}
else if(gameBoard[row-1][column-1] != ' '){
printf("The position you entered is already taken. Try again! \n");
display_board(gameBoard);
user_move(gameBoard);
}
else{
if(playerTurn == nickname1){
gameBoard[row-1][column-1] = symbol1;
}
else{
gameBoard[row-1][column-1] = symbol2;
}
}
printf("%c", symbol2);
if(gameMode == 2){
return;
}
if(strcmp(playerTurn, nickname1)==0){
strcpy(playerTurn, nickname2);
}
else if(strcmp(playerTurn, nickname2)==0){
strcpy(playerTurn, nickname1);
}
}
/*
Automates a strategic move from the computer, aiming to win the game, or at the least prevent the user from winning
*/
void computer_move(char gameBoard[3][3]){
int row;
int column;
int endTurn = 0;
row = rand() % 3 + 0;
column = rand() % 3 + 0;
if(gameBoard[row][column] != symbol1 && gameBoard[row][column] != symbol2){
gameBoard[row][column] = symbol2;
endTurn = 1;
}
}
/*
Detects a win on the game board. Checks if there are three identical symbols in a row, or if there are no more spaces on the game board.
*/
int detect_win(char gameBoard[3][3]){
for(int row = 0; row < 3; row++){
if(gameBoard[row][0] == gameBoard[row][1] && gameBoard[row][1] == gameBoard[row][2]){
if(gameBoard[row][0] == symbol1){
return 1;
}
if(gameBoard[row][0] == symbol2){
return 2;
}
}
}
for(int column = 0; column < 3; column++){
if(gameBoard[0][column] == gameBoard[1][column] && gameBoard[1][column] == gameBoard[2][column]){
if(gameBoard[0][column] == symbol1){
return 1;
}
if(gameBoard[0][column] == symbol2){
return 2;
}
}
}
if(gameBoard[0][0] == gameBoard[1][1] && gameBoard[1][1] == gameBoard[2][2]){
if(gameBoard[1][1] == symbol1){
return 1;
}
if(gameBoard[1][1] == symbol2){
return 2;
}
}
if(gameBoard[0][2] == gameBoard [1][1] && gameBoard[1][1] == gameBoard[2][0]){
if(gameBoard[1][1] == symbol1){
return 1;
}
if(gameBoard[1][1] == symbol2){
return 2;
}
}
return 0;
}
There's a small logical error:
In line 98, 101, 117, and 121, (and perhaps other places - please check) you have used == (operator for equality check) instead of the = used for assignment.
For example,
symbol2 == 'o';
should be replaced with
symbol2 = 'o';
Hence, it just checks for equality, throws away the result, and continues; with no changes made to symbol2.

Reading in and recording a number in C

This is a homework problem. I have a C program that takes user input for a number of people's first names, last names, and ages. Right now it works and prints out the names to the console correctly, but it is not printing out the right ages, and I can't figure out what I'm doing wrong. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int choice;
int i = 0;
int x,k,l;
fputs("How many people would you like to add? ", stdout);
scanf(" %d", &choice);
fflush(stdout);
int ch;
while((ch = getchar()) != EOF && ch != '\n');
if (ch == EOF)
{
}
char firstName[choice][20];
char lastName[choice][20];
int age[choice][3];
char first[20];
char last[20];
int a[3];
for (x = 0; x < choice; x++)
{
for (l = 0; l < 3; l++)
{
age[x][l] = 0;
a[l] = 0;
}
}
while(i < choice)
{
printf("Enter the first name of person ");
printf(" %d", i);
printf(": ");
fgets(first, 20, stdin);
for (k = 0; k < 20; k++)
{
firstName[i][k] = first[k];
}
i++;
}
i = 0;
while(i < choice)
{
printf("Enter the last name of person ");
printf(" %d", i);
printf(": ");
fgets(last, 20, stdin);
for (k = 0; k < 20; k++)
{
lastName[i][k] = last[k];
}
i++;
}
i = 0;
while(i < choice)
{
fputs("Enter the age of person ", stdout);
printf(" %d", i);
printf(": ");
scanf(" %d", &a);
fflush(stdout);
for (l = 0; l < 3; l++)
{
age[i][l] = a[l];
}
i++;
}
int sh;
while((sh = getchar()) != EOF && sh != '\n');
if (sh == EOF)
{
}
for (x = 0; x < choice; x++)
{
printf("First name ");
printf(": ");
printf("%s ", firstName[x]);
printf("\n");
printf("Last name ");
printf(": ");
printf("%s ", lastName[x]);
printf("\n");
printf("Age ");
printf(": ");
printf("%d ", &age[x]);
printf("\n");
}
return 0;
}
If you copy/paste this code it will run, but the age outputted will be incorrect. Can anyone tell me why this is? Thank you!
scanf(" %d", &a);
That should be:
scanf(" %d", &a[0]);
And the printf should be printf("%d", age[x][0]);
You want to read into the first element of the array, not the entire array. You want to print out the first element of the array, not the address of the array.
A better solution would probably be not to make age an array of 3 at all. Each person only has one age. The changes would be:
int age[choice];
int a;
scanf(" %d", &a);
age[choice] = a;
printf("%d ", age[x]);

Resources