一、开始菜单
二、棋盘设计
三、开始游戏
四、玩家下棋
五、电脑下棋
六、胜负判断
一、开始菜单
当程序开始运行,首先需要输出一个开始菜单让玩家选择是否进行游戏。
我们在start()方法里面完成程序的主逻辑,输出菜单让玩家选择,根据选择进行操作。
//开始菜单
void menu()
{
printf("-------------三子棋-------------\n");
printf("| 1.开始游戏 |\n");
printf("| 0.退出 |\n");
printf("-----------------------------—-\n");
}
//主逻辑
void start()
{
int input = 0;
//循环让玩家游戏结束后重新开始或退出
do {
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("play.\n");
playGame();
break;
case 0:
printf("exit.\n");
break;
default :
printf("输入有误,请重新输入。\n");
break;
}
} while (input);
}
二、棋盘设计
我们用 3*3的棋盘作为例子,如下图:
棋盘的每一行细分为两部分:
第一行:一枚棋子的输出由左右各一个空格和棋子本身再加上后面一个 " | " 竖杠组成。
第二行:由三个横杠" — " 加一个竖杠 " | ",对应上一行的棋子。
实际上棋子信息存放在一个3*3的二维数组当中,每打印一行就会打印棋子和组成棋盘的部分
三、开始游戏
使用二维数组存放棋子信息并先初始化为空格。打印出棋盘,让玩家选择是否先手。任一方下完棋子后都会重新打印棋盘。
void subMenu()
{
printf("选择下棋顺序:\n");
printf("1.我想先手.\n");
printf("2.让电脑先手.\n");
}
void playGame()
{
//存放玩家和电脑落子信息
char board[ROW][COL] = { 0 };
//初始化棋盘 -- 初始化为空格
initBoard(board, ROW, COL);
//显示棋盘 -- 打印棋盘和下子信息
displayBoard(board,ROW,COL);
while (1)
{
int isFirst;
subMenu();
printf("请选择:");
scanf("%d", &isFirst);
if (isFirst == 1)
{
playerFirst(board, ROW, COL);
break;
}
else if (isFirst == 2)
{
computerFirst(board, ROW, COL);
break;
}
else
{
printf("输入有误,请重新输入!\n");
}
}
}
//玩家先手
void playerFirst(char board[ROW][COL], int row, int col)
{
int ret;//接受游戏状态
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
printf("平局!\n");
displayBoard(board, ROW, COL);
}
//电脑先手
void computerFirst(char board[ROW][COL], int row, int col)
{
int ret;//接受游戏状态
while (1)
{
//电脑下子
computerMove(board, ROW, COL);
displayBoard(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C') {
break;
}
//玩家下子
playerMove(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
printf("平局!\n");
displayBoard(board, ROW, COL);
}
四、玩家下棋
玩家棋子为 ’ * ’
输入坐标进行下子
- 检查玩家输入坐标的合法性,不合法就重新输入。
- 如果该坐标没有被占用,即坐标上为 ’ ’ 则可以落子。
void playerMove(char board[ROW][COL], int row, int col)
{
int x, y;
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("该坐标上已有棋子,请重新输入。\n");
}
}
else
{
printf("输入坐标非法,请重新输入!\n");
}
}
}
四、电脑下棋
电脑棋子为 ’ # ’
1.电脑根据rand()随机函数产生的坐标下棋
void computerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:\n");
int x, y;
while (1)
{
x = rand() % ROW;
y = rand() % COL;
//判断是否占用
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
五、判断胜负
通过isWin()函数棋盘进行胜负判断
- 检测棋盘的横竖三行和两条对角线,如果有某一行或者某一条对角线的所有元素相等,即返回该元素
- 如果棋盘满了则返回‘Q’
- 以上条件都不满足则返回’C’
根据isWin()函数的返回值进行判定,为 ’ * ’ 则玩家赢, ’ # '则电脑赢, ’ Q '为平局, ’ C '则继续下棋.
char isWin(char board[ROW][COL], int row, int col)
{
int i;
//横三行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
{
return board[i][0];
}
}
//竖三行
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ')
{
return board[0][i];
}
}
//对角线两行
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
{
return board[0][2];
}
//是否平局
if (isFull(board, row, col) == 1)
{
return 'Q';
}
else
{
return 'C';
}
}