目录
一、程序文件管理
程序将一共分为三个文件
mainGame.c存放主函数,运行主函数,启动游戏选择菜单等UI;gameManager.c中存放游戏运行逻辑中需要使用的相关函数,gameManager.h中对gameManager.c中的函数进行声明。
二、主函数与界面初始化选择菜单
1.主函数
主函数运行逻辑为:首先展示初始化选择菜单,当玩家输入1,开始游戏,当玩家输入0,则退出游戏,当玩家输入非0或1则请玩家重新选择。同时,要反复运行该程序,并在刚运行时也要启动程2序,所以采用do while进行设计,主函数代码如下:
int main() {
//用于后面电脑下棋函数中使用rand函数进行初始化
srand((unsigned int)time(NULL));
int input = 0;
do {
//选择菜单函数
menu();
printf("请选择>");
scanf("%d", &input);
switch (input)
{
case 1:
//游戏函数
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入错误,请重新选择>");
scanf("%d", &input);
break;
}
} while (input);
return 0;
}
这里menu()为初始化选择菜单函数,game()为游戏操作函数。
2.初始化选择菜单函数
void menu() {
printf("**************************\n");
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
printf("**************************\n");
}
三、游戏操作函数game()
1.函数结构设计
函数首先对棋盘进行初始化,将每个棋盘格设置为空格,并将棋盘进行可视化操作。
在初始化后,循环进行玩家与电脑的下棋操作,并进行输赢的判断。
void game(){
//创建一个数组用于存放棋盘每一行的棋子
char board[ROW][COL] = {0};
//初始化棋盘,让每一个格子里面的在开始都为空格
InitBoard(board, ROW, COL);
//绘制棋盘的函数
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1) {
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C') {
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
// 判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C') {
break;
}
}
if (ret == '*') {
printf("玩家赢\n");
}
else if (ret == '#') {
printf("电脑赢\n");
}
else if (ret == 'Q') {
printf("平局\n");
}
}
2.棋盘初始化函数InitBoard()
采用两层循环将board循环设置为空格即可
void InitBoard(char board[ROW][COL], int row, int col) {
for (int i = 0; i < row ; i++) {
for (int j = 0; j < col; j++) {
board[i][j] = ' ';
}
}
}
3.棋盘绘制函数DisplayBoard()
这里要求每个棋盘每行每个格子元素的两边设置空格,并在每两个棋格之间使用“|”进行分隔。
void DisplayBoard(char board[ROW][COL], int row, int col) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if(i < row-1)
for (int j = 0; j < col; j++) {
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
4.玩家下棋PlayerMove()
这里由玩家输入1-3的坐标,并保存在棋盘数组中,其中如果输入坐标不在1-3或所选位置已经被占用,需要提醒
void PlayerMove(char board[ROW][COL], int row, int col) {
printf("玩家下棋>");
int x = 0;
int y = 0;
while (1) {
printf("请输入下棋的位置坐标,中间用空格间隔\n");
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("该位置被占用,请重新输入:");
}
}
else {
printf("坐标非法,请重新输入:");
}
}
}
5.电脑下棋ComputerMove()
这里进行简化,电脑下棋使用随机函数生成位置,需要注意,需要在主函数中使用srand((unsigned int)time(NULL));对rand函数进行初始化。
void ComputerMove(char board[ROW][COL], int row, int col){
int x = 0;
int y = 0;
printf("电脑下棋>\n");
while (1) {
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ') {
board[x][y] = '#';
break;
}
}
}
6.判断输赢函数IsWin()
判断输赢,返回值为,玩家赢:*,电脑赢:#,平局:Q,继续:C
char IsWin(char board[ROW][COL], int row, int col) {
//判断每行是否用三个相同
for (int i = 0; i < row; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') {
return board[i][0];
}
}
//判断列是否有相同
for (int i = 0; i < col; i++) {
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ') {
return board[0][i];
}
}
//判断斜行是否有相同
if (board[0][0] == board[1][1] && board[2][2] == board[1][1] && board[1][1] != ' ') {
return board[1][1];
}
if (board[2][0] == board[1][1] && board[0][2] == board[1][1] && board[1][1] != ' ') {
return board[1][1];
}
//判断棋盘是否满,这里利用IsFull函数
if (IsFull(board,row,col)) {
return 'Q';
}
//以上均没有返回值,则返回C,游戏继续
return 'C';
}
//用于判段board数组是否全是空格,如果存在某元素为空格则返回0,否则返回1
int IsFull(char board[ROW][COL], int row, int col) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] == ' ') {
return 0;
}
}
}
return 1;
}
四、运行结果展示