【发布时间】:2021-02-14 12:38:01
【问题描述】:
我正在尝试制作一个井字游戏,让您可以与人类敌人或计算机对战。我正在尝试编写一些基本的 AI 代码,通过扫描板来查看您是否有 2 个 X 或 O 彼此相邻或在列/行/对角线的对角中,这将阻止您获胜,我需要一种方法来告诉计算机是否需要打印以及需要在哪个图块上打印以防止您获胜。我的代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void initializeBoard(); //initialize the board //
void drawBoard(); //draw it on the window //
void player_1_move(); //check if player 1 made a valid move and update the board
void player_2_move(); //check if player 2 made a valid move and update the board
//AI functions
void pickTile(); //picks a tile based on available information
void computerTurn(); //checks if the computer is going first or second
char* isThereaWinningMove(); //checks if the user is abou to win
char tempcT;
int checkWin(); //checks if either player has won at the end of every turn and if so ends the game and declares a winner //
char board[3][3]; //3x3 tic tac toe board
int main(){
int win = 0;
printf("==============");
printf("\n TIC TAC TOE \n");
printf("==============\n");
printf("The World's Number 1 Multiplayer Game! \n\n");
initializeBoard();
//let's the user pick the gamemode
int x;
printf("Press 1 to PLAY AGAINST A HUMAN or 0 to PLAY AGAINST AI: \n");
scanf("%d", &x);
while(x!=0 && x!=1){
printf("Invalid input. Press 1 to PLAY AGAINST A HUMAN or 0 to PLAY AGAINST AI: ");
scanf("%d", &x);
}
if(x==1){ //pvp
do{
drawBoard();
printf("\n\n");
player_1_move(); //player 1 (X) moves
drawBoard(); //update the board with each move
win=checkWin(); //did player 1 win?
if(win==1){
printf("\nPlayer 1 has won!");
break;
}
printf("\n\n");
player_2_move(); //player 2 (O) moves
drawBoard(); //update the board with each move
win=checkWin(); //did player 2 win?
if(win==1){
printf("\nPlayer 2 has won!");
break;
}
}while(1);
}
else{ //pvc
computerTurn();
if(tempcT == 'O'){ //if the player is going first
do{
srand( (unsigned int) time(NULL) ); //initialize random seed
drawBoard();
printf("\n\n");
player_1_move(); //user (X) moves first
drawBoard(); //update the board with each move
win=checkWin(); //did player 1 win?
if(win==1){
printf("\nPlayer has won!");
break;
}
//computer turn
printf("\n\n");
pickTile(); //picks available tile
win=checkWin();
if(win == 1){
printf("\nI win!");
break;
}
}while(1);
}
else{ //if the computer goes first
do{
//computer turn
srand( (unsigned int) time(NULL) ); //initialize random seed
printf("\n\n");
pickTile(); //picks available tile
win=checkWin();
if(win == 1){
printf("\nI win!");
break;
}
//player turn
drawBoard();
printf("\n\n");
player_1_move(); //user (X) moves first
drawBoard(); //update the board with each move
win=checkWin(); //did player 1 win?
if(win==1){
printf("\nPlayer has won!");
break;
}
}while(1);
}
}
return 0;
}
//initialize the board
void initializeBoard(){
int i, j;
for(i=0; i<=2; i++){
for(j=0; j<=2; j++){
board[i][j]= ' ';
}
}
}
//draws the board on the window
void drawBoard(){
int t;
for(t=0; t<=2; t++){
printf(" %c | %c | %c ", board[t][0], board[t][1], board[t][2]);
if(t!=2){
printf("\n---|---|---\n");
}
}
printf("\n");
}
//checks if there is a winner at the end of every turn
int checkWin(){
int i;
//checks rows
for(i=0; i<=2; i++){
if(board[i][0]==board[i][1] && board[i][0]==board[i][2] && board[i][0]!= ' '){
return 1;
}
}
//checks columns
for(i=0; i<=2; i++){
if(board[0][i]==board[1][i] && board[0][i]==board[2][i] && board[0][i]!= ' '){
return 1;
}
}
//checks diagonals from top left to bottom right
for(i=0; i<=2; i++){
if(board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[0][0]!= ' '){
return 1;
}
}
//checks diagonals from bottom left to top right
for(i=0; i<=2; i++){
if(board[2][0]==board[1][1] && board[1][1]==board[0][2] && board [2][0]!= ' '){
return 1;
}
}
return 0;
}
//player 1 (X) move
void player_1_move(){
int x, y;
//player 1 picks coordinates on the board
printf("Player 1, please pick a row (1-3): ");
scanf("%d", &x);
printf("Now pick a column (1-3): ");
scanf("%d", &y);
x--, y--;
//check if it's a valid tile
while(1){
if(x<0 || x>2){
if(y<0 || y>2){
printf("Invalid tile, please enter a valid tile (same order as before, 1-3): ");
scanf("%d%d", &x, &y);
x--, y--;
}
else{
printf("Invalid row, please try again (1-3): ");
scanf("%d", &x);
x--;
}
}
else if(y<0 || y>2){
printf("Invalid column, please try again (1-3): ");
scanf("%d", &y);
y--;
}
else{
break;
}
}
//check if the tile is free
while(board[x][y]=='O' || board[x][y]=='X'){
printf("Invalid move, please enter valid coordinates (same order as before, 1-3): ");
scanf("%d%d", &x, &y);
x--, y--;
}
board[x][y]='X';
}
//player 2 (O) move
void player_2_move(){
int x, y;
//player 2 picks a tile
printf("Player 2, please pick a row (1-3): ");
scanf("%d", &x);
printf("Now pick a column (1-3): ");
scanf("%d", &y);
x--, y--;
//check if it's a valid tile
while(1){
if(x<0 || x>2){
if(y<0 || y>2){
printf("Invalid tile, please enter a valid tile (same order as before, 1-3): ");
scanf("%d%d", &x, &y);
x--, y--;
}
else{
printf("Invalid row, please try again (1-3): ");
scanf("%d", &x);
x--;
}
}
else if(y<0 || y>2){
printf("Invalid column, please try again (1-3): ");
scanf("%d", &y);
y--;
}
else{
break;
}
}
//check if the tile is free
while(board[x][y]=='O' || board[x][y]=='X'){
printf("Invalid move, please enter valid coordinates (same order as before, 1-3): ");
scanf("%d%d", &x, &y);
x--, y--;
}
board[x][y]='O';
}
//AI functions
//checks if the computer is going first or second
void computerTurn(){
int x;
printf("Press 1 if you'd like to GO FIRST and 0 if you'd like to GO SECOND: ");
scanf("%d", &x);
while(x!=0 && x!=1){
printf("Invalid input. Press 1 if you'd like to GO FIRST and 0 if you'd like to GO SECOND: ");
scanf("%d", &x);
}
if(x==1){
printf("OK, the player is going first.\n\n");
tempcT = 'O';
}
else{
printf("OK, I'm going first.\n\n");
tempcT = 'X';
}
}
//if there is a winning move available on the AI's turn
char* isThereaWinningMove(){
int i;
//checks rows
for(i=0; i<=2; i++){
if(board[i][0]==board[i][1] && board[i][1] == ' '){
return &board[i][2];
}
}
for(i=0; i<=2; i++){
if(board[i][0]==board[i][2] && board[i][1] == ' '){
return &board[i][1];
}
}
for(i=0; i<=2; i++){
if(board[i][1]==board[i][2] && board[i][0] == ' '){
return &board[i][0];
}
}
//checks columns
for(i=0; i<=2; i++){
if(board[0][i]==board[2][i] && board[1][i] == ' '){
return &board[1][i];
}
}
for(i=0; i<=2; i++){
if(board[0][i]==board[1][i] && board[2][i] == ' '){
return &board[2][i];
}
}
for(i=0; i<=2; i++){
if(board[1][i]==board[2][i] && board[0][i] == ' '){
return &board[0][i];
}
}
//checks diagonals from top left to bottom right
if(board[1][1]==board[2][2] && board[0][0] == ' '){
return &board[0][0];
}
if(board[0][0]==board[2][2] && board[1][1] == ' '){
return &board[1][1];
}
if(board[0][0]==board[1][1] && board[2][2] == ' '){
return &board[2][2];
}
//checks diagonals from bottom left to top right
if(board[1][1]==board[0][2] && board [2][0] == ' '){
return &board[2][0];
}
if(board[2][0]==board[1][1] && board [0][2] ==' '){
return &board[0][2];
}
if(board[2][0]==board[0][2] && board [1][1] == ' '){
return &board[1][1];
}
return 0;
}
//picks a tile based on available information
void pickTile(){
int rndX, rndY;
char *p = isThereaWinningMove();
//did the computer detect a winning move?
if(p != 0){
*p = tempcT;
}
//if not, pick a random available tile
else{
while(1){
rndX = rand()%3;
rndY = rand()%3;
if(board[rndX][rndY] == ' '){
board[rndX][rndY] = tempcT;
break;
}
}
}
}
与人类对战似乎效果很好。我只有将 tempcT 的值分配给 isThereaWinningMove 函数将返回的任何数组槽的问题。由于 2 个编译器错误,我现在编写的代码实际上并没有运行:
[错误] 函数 'char isThereaWinningMove()' 的赋值 [错误] 在赋值中无法将'int'转换为'char()'
【问题讨论】:
-
isThereaWinningMove 是一个函数,做
isThereaWinningMove = 'tempcT'你尝试用一个(无效的)char 分配一个函数,你的目标是什么? -
除此之外,您有几次调用 isThereaWinningMove 都是徒劳的,因为您失去了结果,目标又是什么?
-
还有
scanf("%d", x)你想要的无效scanf("%d", &x) -
您多次调用 srand 时的值很可能相同(程序在同一秒内运行),因此您很可能为所有 rndX 获得相同的值 和 rndY,不要那样做,在 main 的开头调用它一次
-
isThereaWinningMove 应该在计算机从 computerTurn 函数中轮到它时调用,如果任何 if 语句为真,我需要告诉计算机在相应的图块上移动。