一.设计思路
设计一个二维数组,支持人机输入,判断输入合法性
二.具体分析
1.棋盘 要实现一个简单的三子棋小游戏首先要有的是支持的场地,也就是得有一个棋盘,在开始先建一个空白棋盘
void init(char board[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) { //行
for (int col=0; col < MAX_COL; col++) { //列
board[row][col] = ' ';
}
}
}
对于棋盘也可以直接把循环写进主函数,不过这种函数调用的形式看上去更简洁,对于其他可能出现的要求也更适配。这里在界面出来会是空白一片,看不到棋盘本身,所以可以尝试用用一些符号来划出边界。
2.输入 游戏默认玩家为先手方,也就是由玩家先进行输入,此处输入玩家不能超出棋盘规定位置,若超出则要重新输入,同时还用一个if语句判断当前输入位置是否已满。
void playerMove(char board[MAX_ROW][MAX_COL]) {
printf("请落子\n");
while (1) {
printf("请输入坐标");
int row = 0;
int col = 0;
scanf("%d %d", &row, &col);
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
printf("坐标有误,请重新输入\n");
continue;
}
if (board[row][col] != ' ') {
printf("当前位置已满,请重新输入");
continue;
}
board[row][col] = 'x';
break;
}
}
3.人机 此处用到的人机确实是人工智障,它的核心是随机种子,即用时间来造一个随机数,即使是时间随时在变也不能确定每一次的随机数都不同,因此这个函数里面还要加一个判断,判断当前人机输入位置是否合法,这里其实效率就有些不能确定了,他的坐标生成所用时间完全随机,因此不能保证人机能用多长时间得出随机数。
4.胜负判断 三子棋规则是先让三子连成线的一方胜,于是先判断行列是否出现三连珠现象
for (int row = 0; row < MAX_ROW; row++) {
if (board[ row][0] != ' '
&& board [row][0] == board [row][1]
&& board [row][0] == board [row][2]) {
return board [row][0];
}
}
for (int col = 0; col <= MAX_COL; col++) {
if (board[0][col] != ' '
&& board[0][col] == board[1][col]
&& board[0][col] == board[2][col]) {
return board[0][col];
}
三子棋对角线三连也为胜,只是这种特殊情况不能用上面两个循环一起表示出来,要一一列出进行if选择判断
if (board[0][0] != ' '
&& board[0][0] == board[1][1]
&& board[0][0] == board[2][2]) {
return board[0][0];
}
if (board[2][0] != ' '
&& board[2][0] == board[1][1]
&& board[2][0] == board[0][2]) {
return board[2][0];
}
有可能会过于高估玩家的智商,以至于忘记了和棋的情况,此处如果上方都未出现三连子且棋盘已满,则为和棋。
三.细节处理
棋盘的数组大小可以直接输入,不过那样在每个函数中又有可能进行重新输入操作,于是在开头可以搞一个宏定义。
#define MAX_ROW 3
#define MAX_COL 3
判断棋盘是否已满在多个函数中均有应用,为方便操作,我们把它单独写出来,进行函数调用操作。
int isFULL(char board[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
if (board[row][col] == ' ') {
return 0;
}
}
}
return 1;
}
在玩家每次输入后会发现上一次的输入还在,导致本次的操作结果被顺延到下方,看上去很不舒服,这里可以用一个清屏函数system(”cls“)(记忆方法‘苍老师’)