gpt4 book ai didi

c - 输入字母字符时,Tic-Tac-Toe 用户输入无休止地循环

转载 作者:太空宇宙 更新时间:2023-11-04 02:22:51 24 4
gpt4 key购买 nike

所以我正在用 C 语言制作一个井字游戏,我遇到了一个问题,我要求用户按 2 撤消他们的移动。每次轮到他们时,他们可以撤消移动或继续通过选择另一个键选择下一回合。

它按应有的方式工作,但我有一个问题,如果用户输入字母字符,程序会在检查我的 GetHumanMove 函数时重复循环说这不是数字。有谁知道如何让它停止这样做并在不循环程序的情况下只说这不是一个数字?

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>

//Tic-Tac-Toe game in C
//20/03/2019
//5x5 Board with 4 in a row to win. Also has playable AI that randomly blocks human moves.
//Also has replay function using a doubly linked list

/*
int board[49] = {
;,;, ;, ;, ;, ;, ;,
;,1, 2, 3, 4, 5 ,;,
;,6, 7, 8, 9, 10,;,
;,11,12,13,14,15,;,
;,16,17,18,19,20,;,
;,21,22,23,24,25,;,
;,;, ;, ;, ;, ;, ;,
}
*/

struct node
{
int side;
int move;
int place;
struct node * prev;
struct node * next;
};

void append(struct node **, int, int, int);
void display(struct node *);
void delete(struct node **, int);

//Constants of pieces, border and empty places
enum { NOUGHTS, CROSSES, BORDER, EMPTY };
//Constants for human/computer win or draw
enum { HUMANWIN, COMPWIN, DRAW };

const int directions[4] = { 1, 7, 6, 8 };

int moveCount = 0;

//Values of original places to play
const int ConvertTo49[25] = {
8, 9, 10,11,12,
15,16,17,18,19,
22,23,24,25,26,
29,30,31,32,33,
36,37,38,39,40
};

void append(struct node ** list, int side, int move, int place)
{
struct node *temp , *current = *list;

if(*list == NULL)
{
*list = (struct node *) malloc(sizeof(struct node));
(*list) -> prev = NULL;
(*list) -> side = side;
(*list) -> move = move;
(*list) -> place = place;
(*list) -> next = NULL;
}
else
{
while(current -> next != NULL)
current = current -> next;

temp = (struct node *) malloc(sizeof(struct node));
temp -> side = side;
temp -> move = move;
temp -> place = place;
temp -> next = NULL;
temp -> prev = current;
current -> next = temp;
}
}

void delete(struct node ** list, int num)
{
struct node *temp = *list;

while(temp != NULL)
{
if(temp -> move == num)
{
if(temp == *list)
{
*list = (*list) -> next;
(*list) -> prev = NULL;
}
else
{
if(temp -> next == NULL)
temp -> prev -> next = NULL;
else
{
temp -> prev -> next = temp -> next;
temp -> next -> prev = temp -> prev;
}
free(temp);
}
return ;
}
temp = temp -> next;
}
printf("Element %d not found in the supplied list \n\n", num);
}

//Loop through a direction until a border square is hit
int GetNumForDir(int startSq, const int dir, const int *board, const int us)
{
int found = 0;

while(board[startSq] != BORDER)
{
if(board[startSq] != us)
{
break;
}
found++;
startSq += dir;
}
return found;
}

//Loop through directions and find four in a row
int FindFourInARow(const int *board, const int ourIndex, const int us)
{
int dirIndex = 0;
int dir = 0;
int countFour = 1;

for(dirIndex = 0; dirIndex < 4; ++dirIndex)
{
dir = directions[dirIndex];
countFour += GetNumForDir(ourIndex + dir, dir, board, us);
countFour += GetNumForDir(ourIndex + dir * -1, dir * -1, board, us);
if(countFour == 4)
{
break;
}
countFour = 1;
}
return countFour;
}

//Set up board structure
void InitialiseBoard(int *board)
{
//index variable
int index;

//set whole board to border squares initially
for(index = 0; index < 49; ++index)
{
board[index] = BORDER;
}

//Set up empty squares for placing pieces
for(index = 0; index < 25; ++index)
{
board[ConvertTo49[index]] = EMPTY;
}
}

//Print the board
void PrintBoard(const int *board)
{
//index variable
int index;

//Set pieces and places
char pceChars[] = "OX| ";

printf("\n\n\n");

//Loop through and only draw the actual playable squares, leaving out the border squares
for(index = 0; index < 25; ++index)
{
//Put lines inbetween places
if(index==1 || index==2 || index==3 || index==4 ||
index==6 || index==7 || index==8 || index==9 ||
index==11 || index==12 || index==13 || index==14 ||
index==16 || index==17 || index==18 || index==19 ||
index==21 || index==22 || index==23 || index==24)
{
printf(" |");
}

//Put space at start to space out board from edge of screen
if(index==0)
{
printf(" ");
}

//Print new line every 5 places
if(index!= 0 && index==5 || index==10 || index==15 || index==20)
{
printf("\n");
printf(" -------------------");
printf("\n");
printf(" ");
}

//Print each playable piece
printf(" %c", pceChars[board[ConvertTo49[index]]]);
}
printf("\n\n");
}

//Check if board has empty spaces
int HasEmpty(const int *board)
{
int index;

for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY) return 1;
}

return 0;
}

//Function for making move of current player
void MakeMove(int *board, const int sq, const side)
{
//set board place that either player decides
board[sq] = side;
}

void UndoMove(int *board, int sq, int side)
{
//set board place that either player decides
board[sq] = side;
}


//Help the computer find a winning move
int GetWinningMove(int *board, const int side)
{
int ourMove = -1;
int winFound = 0;
int index = 0;

for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY)
{
ourMove = ConvertTo49[index];
board[ourMove] = side;

if(FindFourInARow(board, ourMove, side) == 4)
{
winFound = 1;
}
board[ourMove] = EMPTY;
if(winFound == 1)
{
return ourMove;
}
ourMove = -1;
};
}
return ourMove;
}

//Get computer player move
int GetComputerMove(int *board, const int side)
{
int index;
int numFree = 0;
int availableMoves[25];
int randMove = 0;

//Set random number to randomly run a function
int randFunction = 0;
randFunction = (rand() % 2);

//Go for the winning move
randMove = GetWinningMove(board, side);
if(randMove != -1)
{
return randMove;
}

//If random function is 1, stop any winning move from the human
if(randFunction == 1)
{
randMove = GetWinningMove(board, side ^ 1);
if(randMove != -1)
{
return randMove;
}
}

randMove = 0;
//Loop through all squares and put piece in random place
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY)
{
availableMoves[numFree++] = ConvertTo49[index];
};
}

randMove = (rand() % numFree);
return availableMoves[randMove];
}


//Get human player move
int GetHumanMove(const int *board)
{
//Array for user input
int userInput;
char term;
//Start moveOK at 0
int moveOK = 0;
int move = -1;

//Loop through until move being made is valid
while(moveOK == 0)
{

printf("\n");

//Ask user for input of 1-9
printf("Please enter a place on the board to make your move, from 1 to 25: ");
//Make sure that user doesnt enter long string with number on the end that eventaully passes tests in the while loop
scanf("%d%c", &userInput, &term);

if(term != '\n')
{
move = -1;
printf("This is not a number\n");
continue;
}

//Check if input is in proper range
if(userInput < 1 || userInput > 25)
{
move = -1;
printf("Invalid Range\n");
continue;
}

//decrement move to get the array location of the playable places
userInput--;

//Check if place selected is already taken
if(board[ConvertTo49[userInput]] != EMPTY)
{
move = -1;
printf("Square not available\n");
continue;
}

//Set move ok to 1 after passing all the tests
moveOK = 1;
}

//Print move being made and return it
printf("\nHuman making Move at square: %d\n",(userInput+1));
return ConvertTo49[userInput];
}

//Run Game function
void RunGame()
{
struct node *list;
list = NULL;

//Display
printf("\n\n Noughts And Crosses Game:");
printf("\n =========================");

//game over variable
int gameOver = 0;
//Start on noughts side
int side = NOUGHTS;
//Record last move
int lastMoveMade = 0;
//Create new board
int board[49];
//Count of first move
int initialMove = 0;

//Initialise the Board
InitialiseBoard(&board[0]);

//Print the board to screen
PrintBoard(&board[0]);

//While game isn't over
while(!gameOver)
{
initialMove++;
//Human
if(side==NOUGHTS)
{
//Ask to undo move after first move played
if(initialMove > 1)
{
while(list -> prev != NULL)
list = list -> prev;
int undo;
printf("\n\nWould you like to undo your move? \nEnter 2 to undo or any other key/s to continue: ");
scanf("%d", &undo);
if( undo == 2)
{
while(list -> next != NULL)
list = list -> next;

char pceChars[] = "OX| ";
//printf(" %c", pceChars[board[ConvertTo49[index]]]);

int count = 2;
while(count != 0)
{
UndoMove(&board[0], list -> place, EMPTY);
list = list -> prev;
delete(&list, list -> next -> move);
moveCount--;
count--;
}
PrintBoard(&board[0]);
}
}
//Make new move for human
lastMoveMade = GetHumanMove(&board[0]);
MakeMove(&board[0], lastMoveMade, side);
moveCount++;
int humanMove;
//Find the position the computer is making on the 5x5 board
for(humanMove = 0; humanMove < 25; ++humanMove)
{
if(ConvertTo49[humanMove] == lastMoveMade)
{
break;
}
}
append(&list, 0, moveCount, lastMoveMade);
side = CROSSES;

}
//Computer
else
{
//Make move for computer
lastMoveMade = GetComputerMove(&board[0], side);
MakeMove(&board[0], lastMoveMade, side);
int compMove;
//Find the position the computer is making on the 5x5 board
for(compMove = 0; compMove < 25; ++compMove)
{
if(ConvertTo49[compMove] == lastMoveMade)
{
break;
}
}
printf("\nComputer making move at square: %d", compMove+1);
moveCount++;
append(&list, 1, moveCount, lastMoveMade);
side = NOUGHTS;
PrintBoard(&board[0]);
}

//If three in a row exists, game over
if(FindFourInARow(board, lastMoveMade, side ^ 1) == 4)
{
gameOver = 1;
if(side == NOUGHTS)
{
printf("\nGame Over!\n");
printf("Computer Wins! :(\n");
}
else
{
PrintBoard(&board[0]);
printf("\nGame Over!\n");
printf("Human Wins! :D\n");
}
}

//If no more moves, game is a draw
if(!HasEmpty(board))
{
PrintBoard(&board[0]);
printf("\n\nGame Over!\n");
gameOver = 1;
printf("It's a draw! :/\n");
}
}

/*
*
* Match Replay
*
*/
int answer;
printf("\n\nWould you like to replay the match? \nEnter 1 to replay or any other key/s to quit: ");
scanf("%d", &answer);

if(answer == 1)
{
InitialiseBoard(&board[0]);
while ( list != NULL )
{

MakeMove(&board[0], list -> place, list -> side);
PrintBoard(&board[0]);
char who[7];
if(list -> side == 0)
{
strcpy(who, "NOUGHTS");
//who = "NOUGHTS";
}
else
{
strcpy(who, "CROSSES");
//who = "CROSSES";
}
int moveMade;
//Find the position the computer is making on the 5x5 board
for(moveMade = 0; moveMade < 25; ++moveMade)
{
if(ConvertTo49[moveMade] == list -> place)
{
break;
}
}
printf ("\nMove:%2d Side:%8s Place: %d\n", list -> move, who, moveMade+1);
Sleep(2000);
list = list -> next ;
}
}
else
{
printf("\nGood Game! See ya!\n");
getch();
}
}



int main()
{
//Create random number
srand(time(NULL));

//Call Run Game to play
RunGame();

return 0;
}

最佳答案

与您的格式不匹配的输入不会被 scanf 消耗。它保留在输入流中。因此,当您键入一个字母时,它无法匹配您想要的数字 %d 并保留在输入流中。

scanf("%d%c", &userInput, &term);

代替scanf,使用getline 来处理整行输入会更简单。然后使用 sscanf(函数的基于字符串的版本)或其他方法解析结果。

char *line = NULL;
size_t len = 0;

while ((read = getline(&line, &len, stdin)) != -1) {
// Do something with line

int scanned = sscanf(line, "%d%c", &userInput);

if (scanned == EOF || scanned != 2) {
printf("Line failed to match\n");
}
}

关于c - 输入字母字符时,Tic-Tac-Toe 用户输入无休止地循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55367328/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com