这里有完整代码:c语言: 测试仓库 (gitee.com)
1.判断是否要玩游戏
(1)打印一个游戏菜单,输入1是进入游戏,输入0是退出游戏
2.game()函数
(1)初始化棋盘,创建Board放置棋子
(2)创建Print函数打印棋盘
3.通过IsWin( )函数判断是否输赢
可以使用cheer变量控制输赢的条件
4.创建判断是否平局的函数Isfull( )
(1)棋子占满返回1,否则则返回0
(2)如果返回1则退出game()函数
1.判断是否要玩游戏
(1)首先使用menu()函数打印一个菜单,选择1进入游戏,选择0退出游戏
void menu()
{
printf("*****1.play*******\n");
printf("******************\n");
printf("*****0.exit*******\n");
}
(2)用switch判断是否进入游戏,如果input为1则进入游戏,如果input为0则退出游戏,输入其他则提示重新数输入。为了多次玩游戏,将整个switch语句放在while循环中,当input不为零循环继续。
int main()
{
srand((unsigned)time(NULL));
int input = 0;
do
{
menu();
printf("请输入>:");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏>\n");
break;
default:
printf("请重新输入!\n");
break;
}
} while (input);
return 0;
}
2.game()函数
(1)首先初始化一个二维字符数组,行为ROW,列为COL,我们用三行三列举例
char Board[ROW][COL];
(2)创建函数InintBoard()初始化棋盘,使用空格初始化数组。
一维数组列元素的下标是从0到COL-1,一维数组行元素的下标是从0到ROW-1,所以使用一个for行循环嵌套一个for列循环
void InintBoard(char Board[ROW][COL])
{
int i = 0;//行初始化
for (i = 0; i < ROW; i++)
{
int j = 0;//列初始化
for (j = 0; j < COL; j++)
{
Board[i][j] = ' ';
}
}
}
(3)创建函数PrintBoard()打印棋盘
这里想要打印二维数组中放置的棋子Board[i][j],需要再次使用一个for行循环嵌套一个for列循环:
void PrintBoard(char Board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
printf(" %c ", Board[i][j]);
}
printf("\n");
}
}
想要打印出这样的棋盘 :
我们可以把棋盘分为两部分:
第一部分可以分为:Board[0][0] | Board[0][1] | Board[0][2]
可以看成 ----------> 数组 | 数组 | 数组 ‘|’
也就是每个数组隔着一个 | ,但是最后一个带引号的 ‘|’ 不打印,所以要在循环中加限制条件,当循环变量j等于COL就不打印最后一个 |
int j = 0;
for (j = 0; j < COL; j++)
{
printf(" %c ", Board[i][j]);
//每打印一个数组元素就打印一个'|',但最后一个'|'不打印。
if (j < COL - 1)
{
printf("|");
}
}
第二个部分和第一个部分非常相似
第二个部分可以分成:--- | --- | ---
可以看成--------------> --- | --- | --- '|'
也就是每个 --- 隔着一个 | ,但是最后一个带引号的 ‘|’ 不打印,所以要在循环中加限制条件,n等于COL就不打印最后一个 |
int n = 0;
for (n = 0; n < COL; n++)
{
printf("---");
//最后一行不打印’----|----‘,和上面同理
if (n < COL - 1)
{
printf("|");
}
}
知道了上面的逻辑,现在只要把三个部分的代码拼在一起即可:
//每打印一个元素,后面用’|‘分割
void PrintBoard(char Board[ROW][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 n = 0;
for (n = 0; n < COL; n++)
{
printf("---");
//最后一行不打印’----|----‘,和上面同理
if (n < COL - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
(4)在while循环中实现玩家下棋过程,创建PlayerBoard()函数
创建两个变量x,y放置玩家输入的坐标:
玩家输入坐标后,要判断输入坐标是否在棋盘中:(x >= 1 && x <= ROW && y >= 1 && y <= COL))
判断坐标位置是否为空:
如果位置为空则使用 ‘*‘ 落子(由于数组的下标是0到COL-1或者0到ROW-1,所以需要将x-1和y-1)
如果位置已经有棋子,则提示重新输入坐标,直到成功输入
这个部分的完整代码:
void PlayerBoard(char Board[ROW][COL])
{
while(1)
{
printf("请输入坐标,中间使用空格>:");
int x, y = 0;
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");
}
}
}
(5)在while循环中实现电脑下棋的过程,创建ComputerBoard()函数
调用rand()函数生成坐标:
注意:调用rand()函数时需要在主函数中调用srand()函数还有time()函数,和引用头文件<stdlib.h>和<time.h>
srand((unsigned)time(NULL));
rand() % ROW结果的范围就是0到ROW-1,同理 rand() % COL结果的范围就是0到COL-1
同理:此处需要判断坐标位置是否为空:
由于代码比较短,直接给出这个部分完整代码:
void ComputerBoard(char Board[ROW][COL])
{
while(1)
{
//调用rand函数,生成0到ROW-1的数和0到COL-1的数
int x = rand() % ROW;
int y = rand() % COL;
//如果坐标为空,则落子,循环退出
if(Board[x][y] == ' ')
{
Board[x][y] = '#';
break;
}
}
}
这里再附上game()的主体代码:
void game()
{
char Board[ROW][COL];
InintBoard(Board);
PrintBoard(Board);
while (1)
{
char flag = 0;
while(1)
{
printf("玩家走\n");
PlayerBoard(Board);
PrintBoard(Board);
flag = IsWin(Board);
if (flag != 'C')
break;
printf("电脑走\n");
ComputerBoard(Board);
PrintBoard(Board);
flag = IsWin(Board);
if (flag != 'C')
break;
}
if (flag == '*')
{
printf("恭喜你赢了!\n");
return 0;
}
else if (flag == '#')
{
printf("电脑赢了\n");
return 0;
}
else if (flag == 'Q')
{
printf("平局\n");
return 0;
}
}
}
3.通过IsWin函数判断是否输赢
(1)创建一个函数IsWin,在人或电脑走完使用flag=IsWin(),对flag的值进行判断:
需要分为三个部分判断,分别是行,列,两个对角线
通过遍历数组,计算挨在一起的棋子的个数,因为首尾棋子无法被计入,所以只要个数count等于cheer-1,就可以判断出输赢
(2)需要在函数末尾用Isfunll()函数判断是否平局-------->4.判断平局的函数Isfunll()
附上完整代码:
char IsWin(char Board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
//创建count判断连在一起的棋子个数,首尾棋子无法判断,所以count==cheer-1即可
//cheer为所需连在一起的棋子个数
int count = 0;
int j = 0;
for (j = 0; j < COL-1; j++)
{
if (Board[i][j] == Board[i][j + 1] && Board[i][j] != ' ')
{
count++;
}
}
if (count == cheer-1)
{
return Board[i][j];
}
}
for (i = 0; i < COL; i++)
{
int count = 0;
int j = 0;
for (j = 0; j < ROW-1; j++)
{
if (Board[j][i] == Board[j+1][i] && Board[j][i] != ' ')
{
count++;
}
}
if (count == cheer-1)
{
return Board[j][i];
}
}
//对角线判断
int count = 0;
int x = 0;
int y = 0;
for (x = 0, y = 0; x < ROW - 1 && y < COL - 1; x++, y++)
{
if (Board[x][y] == Board[x + 1][y + 1] && Board[x][y] != ' ')
{
count++;
}
if (count == cheer - 1)
{
return Board[x][y];
}
}
count = 0;
for (x = ROW, y = 0; x >0 && y < COL - 1; x--, y++)
{
int count = 0;
if (Board[x][y] == Board[x - 1][y + 1] && Board[x][y] != ' ')
{
count++;
}
if (count == cheer-1)
{
return Board[x][y];
}
}
int flag = 0;
//判断是否平局
flag = Isfull(Board);
if (flag == 1)
{
return 'Q';
}
return 'C';
}
4.判断平局的函数Isfunll()
遍历数组,如果数组元素有一个为空,函数返回0,反之如果数组遍历完毕,都没有一个数组元素为空,函数则返回1
附上完整代码:
int Isfull(char Board[ROW][COL])
{
//棋子占满返回1,不满返回0
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
if (Board[i][j] == ' ')
return 0;
}
}
return 1;
}
上面用到的常数和函数定义,也包括头文件的引用:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
#define cheer 3
void game();
void InintBoard(int Board[ROW][COL]);
void PrintBoard(char Board[ROW][COL]);
void PlayerBoard(char Board[ROW][COL]);
void ComputerBoard(char Board[ROW][COL]);
char IsWin(char Board[ROW][COL]);
int Isfull(char Board[ROW][COL]);