三子棋的c语言设计
设计思路
三子棋的玩法主要为,在一个3*3的棋盘上,两线先后执子下棋,然后如果有一方的三个棋子落在同一行或者同一列,或者一斜行,都算是这一方获胜。所以在设计三子棋人机对战小程序的时候,首先要考虑在这个程序中需要我们实现什么功能。我认为想要作为一个游戏,首先应该设计进入页面,让玩家自己选择是退出游戏还是进入游戏。选择进入游戏之后,需要有游戏棋盘的加载,然后是玩家下棋,每次下完棋之后都应该判断输赢,如果判断结果没有人赢的话,则电脑下棋。需要注意的是在每次下棋之前都要先判断棋盘上是否还有空位可以放棋。如果没有空位并且没有玩家获胜,那么判断本局游戏为平局。每位玩家下完棋之后都应该放出下完棋之后的预览,可以清楚观察对方的落棋点。最后只要有一方获得胜利或是平局,那么本场比赛结束,重新载入菜单页面,让玩家自己选择是否再来一次。
那么根据我们的最初设计思路,首先应该写出棋盘的main函数。
main函数
int main()
{
int i = 0;
while (1)
{
menu();
scanf("%d",&i);
if (0 == i)
break;
else if (1 == i)
game();
else
printf("输入错误,请重新输入:>");
}
return 0;
}
上述main函数主要实现了玩家选择是否进入游戏的功能,通过menu函数来提示玩家进行下一步的操作,当玩家选择进入游戏之后,开始加载game函数。下面将列出menu和game的代码:
void menu()
{
printf("\n+-----------------+\n");
printf("| 1 play |\n");
printf("| 0 exit |\n");
printf("+-----------------+\n");
printf("请输入数字选择:>");
}
void game()
{
char arr[row][col];
init_board(arr);//棋盘初始化
char ret;
do{
display_board(arr);//显示棋盘
player_move(arr);//玩家下棋
ret = is_win(arr);//判断输赢
if (' ' == ret)
display_board(arr);
computer_move(arr);//电脑下棋
ret = is_win(arr);
} while (ret == ' ');
if ('X' == ret)
display_board(arr);
printf("恭喜你赢啦\n");
if ('O' == ret)
display_board(arr);
printf("失败了\n");
if('q'==ret)
display_board(arr);
printf("平局\n");
}
思路总结
通过上面的game函数所需求的功能,我们大体已经总结出了我们接下来需要实现的函数功能,大致有:棋盘初始化、棋盘显示、玩家下棋、电脑下棋、判断棋盘是否下满、判断输赢。
这几部分的函数因为种类比较多,并且加上定义后占篇幅比较大,所以我们建立一个.h文件来引入头文件,并且再写一个.c文件来集中定义这些函数,这样可以让我们的主函数看起来更加的简洁明了。
首先来看看我设置的sanziqi.h文件,主要列入了函数的声明。
#ifndef __TEST_H__
#define __TEST_H__ //防止头文件被多次引入,
#define row 3
#define col 3
void init_board(char arr[row][col]); //棋盘初始化
void display_board(char arr[row][col]); // 棋盘显示
void player_move(char arr[row][col]); //玩家下棋
int is_full(char arr[row][col]); //判断棋盘是否还有空位
void computer_move(char arr[row][col]); //电脑下棋
char is_win(char arr[row][col]); \\判断输赢
#endif //__TEST_H__
头文件声明完成以后,接下来就是补充定义实现函数功能了。
为了思路清楚我把每项功能的函数都分别列出。
棋盘初始化
void init_board(char arr[row][col])
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = ' ';
}
}
}
其中的row和col因为要在整段函数中多次引用,所以在函数开始通过#define来定义等于3。初始化的主要目的是把所有的位置都设置为空格,这样就可以在每个位置上下棋了。
棋盘显示
void display_board(char arr[row][col])
{
int i = 0;
int j = 0;
printf("_____________\n");
for (i = 0; i < row; i++)
{
printf("| %c | %c | %c |\n", arr[i][0],arr[i][1],arr[i][2]);
if (i != 2)
printf("|---|---|---|\n");
}
printf("~~~~~~~~~~~~~\n");
}
棋盘显示的功能主要是在每次下棋之前告诉玩家还有哪些位置还可以下棋并且判断怎么落子更加有利于获胜。
玩家下棋
void player_move(char arr[row][col]){
int x = 0; int y = 0;
printf("请输入你的坐标\n");
scanf("%d%d", &x, &y);
while (1)
{
x = x - 1;
y = y - 1;
if ((x<0||x>3)||(y<0||y>3))
printf("该位置不存在\n");
if ((0 <= x && x < row) && (0 <= y &&y < col));
{
if (' ' == arr[x][y])
{
arr[x][y] = 'X';
break;
}
else
{
printf("该位置已经有棋了\n");
}
}
}
}
玩家下棋的功能主要是接收玩家输入的坐标,并且判断输入坐标是否在棋盘内部,如果在棋盘内部并且该位置为空,那么该位置替换为X代表玩家已经下棋。
判断是否有空位
int is_full(char arr[row][col])
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
{
if (' ' == arr[i][j])
return 0;
}
return 1;
}
通过循环来判断每个位置是否还有空位,有空位返回0,没有空位返回1.
电脑下棋
void computer_move(char arr[row][col])
{
printf("电脑下棋\n");
int x = 0; int y = 0;
srand((unsigned)time(NULL));
do
{
x = rand() % row;
y = rand() % col;
if (' '==arr[x][y])
{
arr[x][y] = 'O';
break;
}
} while (1);
}
电脑下棋的话为了程序简单,采用rand生成随机值来落子,这里需要补充的是srand需要引入time.h的头文件。在每次产生随机位置后判断该位置是否为空,只有当该位置为空时电脑下棋用O来表示。
判断是否获胜
char is_win(char arr[row][col])
{
int i = 0;
for (i = 0; i < row; i++)
{
if ((arr[i][0] == arr[i][1]) && (arr[i][1] == arr[i][2]) && arr[i][2] != ' ')
return arr[i][2];
}
for (i = 0; i < col; i++)
{
if ((arr[0][i] == arr[1][i]) && (arr[1][i] == arr[2][i]) && arr[2][i] != ' ')
return arr[0][i];
}
if ((arr[0][0] == arr[1][1]) && (arr[1][1] == arr[2][2]) && arr[2][2] != ' ')
return arr[0][0];
if ((arr[0][2] == arr[1][1]) && (arr[1][1] == arr[2][0]) && arr[2][0] != ' ')
return arr[0][2];
if (1 == is_full)
return 'q';
return ' ';
}
这里列出了可能获胜的所有可能,分别用三种颜色标出,当玩家获胜时,即满足这张图中某一条线上均为X,电脑获胜时,即满足这张图上的某一条线上的三个值均为O。如果都下满了还没有人获胜,那么就是平局。
程序运行结果与总结
到这里三子棋的程序就算是彻底做完了,这次的三子棋制作中,我认识到每次接触到一个类似于三子棋这样的需要完成复杂任务的程序时,应该从使用角度出发,仔细考虑这之中完成的功能,先搭建出大致框架之后再逐步实现功能会更加高效一些。并且在敲代码的过程中不时得测一测有什么错误,以便及时得更改。在实现功能的同时还要考虑到避免bug,考虑更多的应用场景。