目录
一.前期准备
这篇博客并不包含三子棋大体的内容设计,只有怎样让计算机下的棋更智能一些的讲解如果想看怎样实现三子棋大体程序设计内容还请跳转:
C语言自制小游戏:三子棋(井字棋)游戏(超详细)
在进行下面的内容开始前,需要你首先完善好大体的三子棋程序内容设计再向下进行
本篇文章写的很啰嗦,就是为了重复反复去推敲种种方式和可能性,可能这种啰嗦的表达方式,能让你理解的更加简单
二.逻辑与程序实现
这次我们要实现的是让计算机能更加智能的判断应该在哪个坐标下下入棋子,从而实现对玩家的“围追堵截”
在思考这个问题前,我们不妨将计算机替换成自己,想象一下,如果是你下棋,你是怎样判断此时应该在哪个坐标下下入棋子呢?
我们要从下面分成几种可能性逐个去分析
注意:要保持换位思考的概念,这里你把自己看成电脑去处理下面的“残局”案例,要记住你现在是后手下棋并且棋子是‘#’
这里我们创建一个函数去存放下面可能性中所生成的代码
——game.h
int AI_Computer(char arr[ROW][COL], int row, int col);
在这里你肯定会不理解为什么创建该函数,后面我会娓娓道来
1.连珠
①横向连珠
当出现下列“残局”你不想输掉游戏时,想必你肯定会在含有两颗‘#’井号的棋子行中找到空白处放入‘#’井号棋子,下面是“残局”的例局
那我们如何在代码中让计算机在下棋时遇到该残局做出连珠这部操作呢,首先在之前的代码中电脑每一步都是随机下棋的,其实我们可以在之前的ComputerMove这个函数中调用新创建的AI_Computer函数去实现判断并下棋这两部操作
大体思路:首先让计算机遍历二维数组中的行,寻找有没有符合条件的行,此行中有且仅有两个元素是‘#’并且另一个元素是‘ ’空格字符,就可确认本行,然后记录‘ ’空格字符的坐标,最后将其坐标赋值为‘#’ 至此完成
我们创建两个变量,count变量去进行计数工作,index变量去记录下标
——game.c
int count = 0; //count负责记录该行'#'的个数
int index = -1; //index记录坐标
要注意下面3个点:
- 这里我们要记录‘#’的数量,所以count负责记录该行‘#’的个数
- 因为已经遍历行了,我们很容易可以得到当前的行号,所以index记录列坐标就可以
- 之所以index的初值是-1而不是0是因为0也可以作为坐标出现在数组中,操作不方便,计算机无法知道这个0是因为坐标就是0所以为0,还是因为你没有操作index,所以赋值为-1在后期只要检验index是否>=0就可以轻易的知道index所传达的信息
- 因为函数要返回int型,所以一旦AI_Computer函数完成了自己的使命,我们就立即return 0,返回的0可以作为一种标注,后面会用到
——game.c的AI_computer函数中写入
int AI_Computer(char arr[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)//遍历行
{
count = 0;
index = -1;
for (int j = 0; j < col; j++)//记录每一行的元素
{
//如果是'#'那记数器count的数量就加以加一
if (arr[i][j] == '#')
{
count++;
}
if (arr[i][j] == ' ')
{
index = j;
}
}
//row是3不要忘记,写成row方便以后要改成4子棋等等使用
//当此行的'#'等于2时并且index的坐标>=0就可以进行赋值操作了
if (count == (row - 1) && index >= 0)
{
arr[i][index] = '#';
return 0;
}
}
}
②纵向连珠
经过了上面的横向连珠,我想纵向连珠也不难推敲,只需要在含有两个‘#’的列中找到空白处再次放入‘#’井号棋子,下面是“残局”的例局
写纵向连珠前我们要注意以下几个点:
- 这次我们用count来记录列中有几个‘#’
- 我们这次遍历列,所以index用来记录行号
- 因为纵向连珠的代码也是要写在AI_Computer函数中的,所以之前我们在横向连珠中调用过count和index,所以这次用之前我们把count再重置为0,index为-1
- 如果成功下棋记得return 0
——game.c的AI_computer函数中写入
count = 0; //重置count
index = -1; //重置index
for (int j = 0; j < col; j++)
{
count = 0;
index = -1;
int count = 0; //记录玩家棋子的个数
int index = -1; //记录要下入的下标
for (int i = 0; i < row; i++)
{
if (arr[i][j] == '#')
{
count++;
}
if (arr[i][j] == ' ')
{
index = i;
}
}
if (count == (col - 1) && index >= 0)
{
arr[index][j] = '#';
return 0;
}
}
③斜向连珠
连珠的最后一步就是斜向连珠了,这个也不难,只需要在含有两个‘#’的对角线方向中找到空白处再次放入‘#’井号棋子,下面是“残局”的例局
写斜向连珠前我们要注意以下几个点:
- count继续记录数量
- 在方向↘的斜线中你会发现都是[0,0] [1,1] [2,2]这样横纵一样的数字坐标,所以在方向↘的判断中只需要index记录行或列一个数字即可,这我们统一遍历每一行去判断。在方向↙的斜线中需要记录[0,2] [1,1] [2,0]这样的坐标,这样的情况下,我们还是遍历行,要记住cow的值一直为3,所以我们只需要利用cow的加减运算就可以写出想要的坐标,并赋值给index
- 两条斜线方向的代码分开写
- 如果成功下棋记得return 0
——game.c的AI_computer函数中写入
count = 0;
index = -1;
//判断方向↘的斜线是否要连珠
for (int i = 0; i < row; i++)
{
if (arr[i][i] == ch)
{
count++;
}
if (arr[i][i] == &#