一、项目概述
井字棋是一款经典的双人游戏,玩家轮流在 3x3 的棋盘上放置棋子,先在水平、垂直或对角线方向形成三个相同棋子的一方获胜。若棋盘被填满且无人获胜,则游戏平局。我们的目标是实现一个控制台版本的井字棋游戏,支持玩家与电脑对战,电脑将采用简单的随机策略选择落子位置。
二、代码实现
1.初始界面
首先利用do ....while函数最少执行依次的特点,在屏幕上打印一个游戏的开始界面,代码和结果如下:
#include <stdio.h>
void menu()
{
printf("*****************************\n");
printf("******1.开始游戏 0.exit******\n");
printf("*****************************\n");
}
int main()
{
int input = 0;
do
{
menu();
} while(input);
return 0;
}
2.用户选择
界面打印之后,用户可以通过键盘来输入数据,以选择是否开始游戏,利用switch语句来判断输入是否合理,结果如下:
printf("请选择:>\n");
scanf("%d",&input);
switch (input)
{
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
3.初始化棋盘并打印
在进入游戏之后,首先需要初始化棋盘并打印,因此需要声明函数来实现棋盘的初始化和打印
初始化棋盘
通过for循环遍历二维数组的每一个元素,让其初始化为空格
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
棋盘打印
棋盘的打印主要利用循环来实现,棋盘中的每一行的元素:首先另二维数组中的第1行第一列元素为“ 字符 ”,若列数小于列数减一,则打印“|”,完成后换行。然后判断数据是否小于行数减一,若符合,则打印“---”,若列数据小于所设定的列,则打印“|”,结果如下:
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ",board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
4.开始游戏
棋手下棋
棋手下棋主要通过初始化棋子的坐标,然后由棋手手动输入坐标来实现,若坐标对应位置为空格,则另该坐标位*,若已经被占用,则输出“坐标被占用,请重新输入”,若坐标不满足二维数组的条件,则输出“坐标非法请重新输入”。
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家请输入坐标:>");
scanf("%d %d",&x,&y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("坐标被占用,请重新输入\n");
}
else
{
printf("坐标非法,,请重新输入\n");
}
}
}
电脑下棋
电脑下棋的坐标通过rand函数来生成随机数,然后将随机数取模行和列之后分别赋值给局部变量,另数组对应位置位“#”即可实现。
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
5.判断输赢
当玩家或着电脑输入坐标之后,需要判断是否赢得游戏,若没有,则继续游戏,若已经有横列、纵列以及对角线中的中的其中一个实现三子相连,则获得胜利。因此需要写一个函数来实现判断输赢,该函数主要通过判断行,或者列或者对角线三个元素是否相等且不等于空格来实现,代码如下:
判断行:
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
判断列
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][1] && board[1][1] != ' ')
{
return board[1][1];
}
若都不满足,则需要判断是否平局,因此需要一个函数来判断棋盘中是否有空,若有返回0,若无返回1,然后利用返回值,通过条件语句来给主函数返回Q,代表平局。
//判断是否有空,有空返回0,没有返回1
int Isfull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
if (Isfull(board, row, col))
{
return 'Q';
}
若以上条件都不满足,则返回C表示继续游戏,整体结果如下。
6.效果展示
选择1后开始游戏,打印初始化棋盘,并提醒玩家输入坐标
当玩家输入坐标后,先判断输赢还是继续游戏,若继续游戏,则电脑开始下棋,若已经有结果,则输出结果。
三、总结
开发这个井字棋游戏,综合运用了 C 语言的数组、循环、条件判断、函数定义等基础知识。在实现过程中,需要注意代码的逻辑顺序和边界条件的处理,例如输入合法性检查、棋盘状态的判断等。虽然这个版本的电脑 AI 只是简单的随机落子,不够智能,但作为初学者的入门项目,已经能够帮助我们加深对 C 语言的理解和应用。希望大家可以在此基础上进行改进和扩展,比如实现更智能的 AI 算法、支持双人对战等,进一步提升自己的编程能力。