arrays - 如何存储数组槽以在函数之间使用?
问题描述
我正在尝试制作一个井字游戏,让您可以与人类敌人或计算机对战。我正在尝试编写一些基本的 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()'
解决方案
正如我通过对您的问题的评论所说:
[错误] 函数 'char isThereaWinningMove()' 的赋值 [错误] 在赋值中无法将 'int' 转换为 'char()'
isThereaWinningMove是一个函数,这样做isThereaWinningMove = 'tempcT' you try to assign a function with an (invalid) char
毫无意义。
其他一些评论:
除此之外,您有几次调用isThereaWinningMove都是徒劳的,因为您失去了结果。
scanf("%d", x)
你想要的无效scanf("%d", &x)
您多次调用srand时使用的值很可能相同(程序在同一秒内运行),因此您很可能为所有rndX和rndY获得相同的值,您必须在 main 开始时调用srand一次。
实际上,您想修改其值由isThereaWinningMove返回的单元格,在 C(然后是 C++)中,您可以返回单元格的地址而不是单元格值:
char * isThereaWinningMove(); //checks if there is a winning move available
...
char * isThereaWinningMove(){
int i;
//checks rows
for(i=0; i<=2; i++){
if(board[i][0]==board[i][1] && board[i][0]!= ' '){
return &board[i][2];
}
}
for(i=0; i<=2; i++){
if(board[i][0]==board[i][2] && board[i][0]!= ' '){
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[0][i]!= ' '){
return &board[1][i];
}
}
for(i=0; i<=2; i++){
if(board[0][i]==board[1][i] && board[0][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[0][0]!= ' '){
return &board[1][1];
}
if(board[0][0]==board[1][1] && board[0][0]!= ' '){
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 [2][0]!= ' '){
return &board[0][2];
}
if(board[2][0]==board[0][2] && board [2][0]!= ' '){
return &board[1][1];
}
return 0;
}
...
void pickTile(){
int rndX, rndY, i;
//did the computer detect a winning move?
char * p = isThereaWinningMove();
if(p != 0){
*p = tempcT;
}
//if not, pick a random available tile
else{
...
另一种方法是在isThereaWinningMove中进行分配,并在您执行时返回 0 的其他内容
int isThereaWinningMove(); //checks if there is a winning move available
...
int isThereaWinningMove(){
int i;
//checks rows
for(i=0; i<=2; i++){
if(board[i][0]==board[i][1] && board[i][0]!= ' '){
board[i][2] = tempcT;
return 1;
}
}
for(i=0; i<=2; i++){
if(board[i][0]==board[i][2] && board[i][0]!= ' '){
board[i][1] = tempcT;
return 1;
}
}
for(i=0; i<=2; i++){
if(board[i][1]==board[i][2] && board[i][0]!= ' '){
board[i][0] = tempcT;
return 1;
}
}
//checks columns
for(i=0; i<=2; i++){
if(board[0][i]==board[2][i] && board[0][i]!= ' '){
board[1][i] = tempcT;
return 1;
}
}
for(i=0; i<=2; i++){
if(board[0][i]==board[1][i] && board[0][i]!= ' '){
board[2][i] = tempcT;
return 1;
}
}
for(i=0; i<=2; i++){
if(board[1][i]==board[2][i] && board[0][i]!= ' '){
board[0][i] = tempcT;
return 1;
}
}
//checks diagonals from top left to bottom right
if(board[1][1]==board[2][2] && board[0][0]!= ' '){
board[0][0] = tempcT;
return 1;
}
if(board[0][0]==board[2][2] && board[0][0]!= ' '){
board[1][1] = tempcT;
return 1;
}
if(board[0][0]==board[1][1] && board[0][0]!= ' '){
board[2][2] = tempcT;
return 1;
}
//checks diagonals from bottom left to top right
if(board[1][1]==board[0][2] && board [2][0]!= ' '){
board[2][0] = tempcT;
return 1;
}
if(board[2][0]==board[1][1] && board [2][0]!= ' '){
board[0][2] = tempcT;
return 1;
}
if(board[2][0]==board[0][2] && board [2][0]!= ' '){
board[1][1] = tempcT;
return 1;
}
return 0;
}
...
//picks a tile based on available information
void pickTile(){
int rndX, rndY, i;
//did the computer detect a winning move?
if (isThereaWinningMove() == 0){
//if not, pick a random available tile
while(1){
...
无论采用哪种方式,还要删除 pickTile 中无用的变量i 并删除 main中isThereaWinningMove的调用,执行时会出现一些其他问题,例如我可以:
pi@raspberrypi:/tmp $ gcc -Wall t.cpp
pi@raspberrypi:/tmp $ ./a.out
TIC TAC TOE
The World's Number 1 Multiplayer Game!
Press 1 to PLAY AGAINST A HUMAN or 0 to PLAY AGAINST AI: 0
Press 1 if you'd like to GO FIRST and 0 if you'd like to GO SECOND: 1
OK, the player is going first. | |
---|---|---
| |
---|---|---
| |
Player 1, please pick a row (1-3): 2
Now pick a column (1-3): 2
| |
---|---|---
| X |
---|---|---
| |
| |
---|---|---
| X |
---|---|---
O | |
Player 1, please pick a row (1-3): 1
Now pick a column (1-3): 1
X | |
---|---|---
| X |
---|---|---
O | |
O | |
---|---|---
| X |
---|---|---
O | |
Player 1, please pick a row (1-3): ^C
pi@raspberrypi:/tmp $
正如你所看到的,程序得到了我之前得到的单元格 1-1。
原因很简单,isThereaWinningMove ` 可以在不检查它是否空闲的情况下获取一个单元格,例如
if(board[i][0]==board[i][1] && board[i][0]!= ' '){
board[i][2] = tempcT;
return 1;
}
一定是
if((board[i][0]==board[i][1] && board[i][0]!= ' ') && (board[i][2] == ' ')) {
board[i][2] = tempcT;
return 1;
}
ETC
注意还有两个错误的索引,例如使用第二种方式
for(i=0; i<=2; i++){
if(board[i][1]==board[i][2] && board[i][0]!= ' '){
board[i][0] = tempcT;
return 1;
}
}
你想要(在缺少的测试中检查单元格是否为空)
for(i=0; i<=2; i++){
if(board[i][1]==board[i][2] && board[i][1]!= ' '){
board[i][0] = tempcT;
return 1;
}
}
并且对于
for(i=0; i<=2; i++){
if(board[1][i]==board[2][i] && board[0][i]!= ' '){
board[0][i] = tempcT;
return 1;
}
}
你想要(在缺少的测试中检查单元格是否为空):
for(i=0; i<=2; i++){
if(board[1][i]==board[2][i] && board[1][i]!= ' '){
board[0][i] = tempcT;
return 1;
}
}
请注意checkWin中的循环在:
//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;
}
}
做就够了
if(board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[0][0]!= ' '){
return 1;
}
if(board[2][0]==board[1][1] && board[1][1]==board[0][2] && board [2][0]!= ' '){
return 1;
}
推荐阅读
- select - Vaadin-Grid:全选复选框在 UI 中不起作用
- python - 在PowerShell中激活python的虚拟环境括号没有显示当shell确认env打开时是否重要?
- ios - 我的 UITapGestureRecognizer 影响 TableViewCell 中的所有元素
- .net - IIS 托管在 .Net Framework 上运行的 ASP Core?
- c - 编译英特尔内在和反向汇编但不工作
- c# - 使用 dto 将布尔值从一个类传递到另一个类
- oracle - 如何将年份和月份转换为数字oracle
- javascript - React:更新状态时打印所有过去的状态
- amazon-web-services - elasticbeanstalk ec2实例设置脚本文件和配置文件是看不到的吗?
- typescript - 通过 VUE3 中的 store 创建组件时更新数据