三子棋的设计要完成以下步骤:

创建菜单页面——>创建棋盘——>初始化棋盘——>设计下棋规则——>制定游戏规则——>判断输赢

三子棋程序考验的是我们对二维数组的使用和理解。

首先我们先从三子棋运行时所进行时的流程来编写test()函数,一个好的开始是成功的一半,先从结构开始思考是一个好习惯,不会让我们在往后编写复杂程序时手忙脚乱。

步骤:

test()采用分支结构——switch,当选择1时进入game()函数开始游戏,choise = 0时退出游戏,这是退出这个程序的唯一入口。

​编写菜单函数来说明应该做出什么选择,清晰明了

编写功能函数,首先是初始化board[ROW][COL]二维数组,将这个二维数组初始化为空格,这样棋盘在整体上是空的状态,视觉上美观一点

我们把三个空格所以一个主体,所以书写代码 printf(" %c ", board[i][j]),空格之后加一个‘|’,但是首个和末尾不需要加‘|’,所以加入限制条件j < col - 1;

再在底下加入‘—’组成棋盘形状,同理第一行和最后一行不需要‘—’,所以加入限制条件 i < row - 1

​在编写玩家下棋的代码的时候要注意,一般人在进行游戏时是不会想到‘0,0’这个坐标的, 为了不让已经下过的坐标被覆盖,所以我们要加入条件board[x - 1][y - 1] == ’ ',只有满足这个条件才能落子

电脑落子我们是用随机数的方法——rand()来确定电脑落子坐标,当一个随机数 % row时只能够得到低于row的坐标

举个例子:假设row = 3,那么余数就只有0,1,2

小编在编写代码的时候把随机数放在了循环外面,这样虽然也能运行程序,但是当电脑第二次以后落棋有可能显示不出来结果了,因为在循环每次只能获得一个随机数,当board[x][y] == ’ '条件不成立时就陷入死循环了

玩家和电脑下棋总要分一个结果,结果有三种:玩家胜利,电脑胜利,平局

返回‘*’——玩家胜利

返回‘#’——电脑胜利

返回‘Q’——平局

返回‘C’——棋盘未满,玩家和电脑继续落子

为了判断棋盘是否满了,我们通过书写is_full()来判断;


头文件:game.h——用来声明函数

#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define COL 3
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayMove(char board[ROW][COL],int row,int col);
void ComputerMove(char board[ROW][COL],int row,int col);
char IsWin(char board[ROW][COL], int row, int col);

源文件:game.c——函数执行模块

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
//执行初始化函数
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}

}
}
void DisplayBoard(char board[ROW][COL], int row, int 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)
{

for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");

}
}
}
void PlayMove(char board[ROW][COL], int row, int col)
//玩家下子函数
{
int x = 0;
int y = 0;
printf("玩家走:>\n");
while (1)
{
printf("请输入坐标;>");
scanf_s("%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");

}
}

}
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;
}
}

}
int IsFull(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col)
//判断输赢
//列出所有情况
{
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
for (i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
return board[1][1];
if (1 == IsFull(board, ROW, COL))
{
return 'Q';
}
return 'C';
}

源文件:test.c——主函数——代码开始模块

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"
void menu()
{
printf("********************************\n");
printf("******* 1.play 0.exit *********\n");
printf("********************************\n");

}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };//创建数组
InitBoard(board, ROW, COL);//初始化数组,进入这个初始化函数
DisplayBoard(board, ROW, COL);打印棋盘,进入这个打印棋盘函数
while (1)
{
PlayMove(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("电脑赢");
}
else
{
printf("平局");
}




}

void test()
{
int input = 0;
srand((unsigned int)time(NULL));
//时间戳函数——库函数——需要引头文件#inculde<time.h>
do
{
menu();
printf("请输入:>");
scanf_s("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新选择\n");
break;
}
}
while (input);
}
int main()//从这里开始
{
test();
return 0;
}