提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:以下是本篇文章正文内容,下面案例可供参考
一、实现逻辑
- 落子优先级(叙述为电脑视角)
- 一手占中,若中心被占则占角(默认为电脑后手)
- 有三连机会,尝试三连
- 玩家有三连机会,进行拦截
- 靠近己方棋子落子
- 实现方法均为基础的循环和判断语句,并且适用于不同规格的棋盘
-
基本逻辑:判断同行、同列、正副对角线是否有两棋相同,且可能三连的位置为空
-
以同列且两棋不相邻为例(为确保一般性,这里使用4x4棋盘)。 - 棋盘中实心红点为判断起始点(if语句的参考点)的所有可能位置,右侧为三连机会示例,中心为可能存在的制胜棋位置
其余情况均为此思考模式,注意讨论对角线时需区分正副对角线
-
二、实现代码
1.一手占中,若中心被占则占角
代码如下:
//电脑第一步
void FirstMove(char board[ROW][COL], int row, int col)
{
int ar1[2] = { 0, row - 1 };
int ar2[2] = { 0, col - 1 };
int x = ar1[rand() % (row - 1)], y = ar2[rand() % (col - 1)];
//判断中心点是否被占,玩家先中则不走边
if (board[row / 2][col / 2] == '*')
{
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//反则占中心
else
board[row / 2][col / 2] = '#';
}
2.有三连机会,尝试三连
代码如下:
//电脑三连机会,三连成功返回0,反之返回1
int ComputerWin(char board[ROW][COL], int row, int col)
{
//1.同一行
int i = 0, j = 0;
//1.1一行相同两枚棋子相邻,判断参考点起点[0][0],终点[row-1][col-2]
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] == '#')
{
if (j < col - 2 && board[i][j + 2] == ' ')
{
board[i][j + 2] = '#';
return 0;
}
else
if (board[i][j - 1] == ' ')
{
board[i][j - 1] = '#';
return 0;
}
}
}
}
//1.2一行相同两枚棋子不相邻,判断参考点起点[0][0],终点[row-1][col-3]
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i][j + 2] && board[i][j] == '#' )
{
if (board[i][j + 1] == ' ')
{
board[i][j + 1] = '#';
return 0;
}
}
}
}
//2.同一列
//2.1一列相同两枚棋子相邻,判断参考点起点[0][0],终点[col - 2][row - 1]
for (i = 0; i < row - 1; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == board[i + 1][j] && board[i][j] == '#')
{
if (i < col - 2 && board[i + 2][j] == ' ')
{
board[i + 2][j] = '#';
return 0;
}
else
if (board[i - 1][j] == ' ')
{
board[i - 1][j] = '#';
return 0;
}
}
}
}
//2.2一列相同两枚棋子不相邻,判断参考点起点[0][0],终点[col - 3][row - 1]
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == board[i + 2][j] && board[i][j] == '#' && board[i + 1][j] == ' ')
{
board[i + 1][j] = '#';
return 0;
}
}
}
//3.拦截对角线
//3.1正对角线
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '#')
{
if (board[i + 2][j + 2] == ' ')
{
board[i + 2][j + 2] = '#';
return 0;
}
}
if (board[i][j] == board[i + 2][j + 2] && board[i][j] == '#')
{
if (board[i + 1][j + 1] == ' ')
{
board[i + 1][j + 1] = '#';
return 0;
}
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '#')
{
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '#';
return 0;
}
}
}
}
//3.2副对角线
for (i = 2; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == '#')
{
if (board[i - 2][j + 2] == ' ')
{
board[i - 2][j + 2] = '#';
return 0;
}
}
if (board[i][j] == board[i - 2][j + 2] && board[i][j] == '#')
{
if (board[i - 1][j + 1] == ' ')
{
board[i - 1][j + 1] = '#';
return 0;
}
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == '#')
{
if (board[i + 1][j - 1] == ' ')
{
board[i + 1][j - 1] = '#';
return 0;
}
}
}
}
return 1;
}
3.玩家有三连机会,进行拦截
首先判断玩家是否存在三连机会,代码如下:
//判断是否需要拦截,需要即返回1,反之返回0
int IsDanger(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
//1.同一行三连
//1.1一行相同两枚棋子相邻,判断参考点起点[0][0],终点[row-1][col-2]
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] == '*')
{
if (j < col - 2 && board[i][j + 2] == ' ')
{
return 1;
}
else
if (board[i][j - 1] == ' ')
{
return 1;
}
}
}
}
//1.2一行相同两枚棋子不相邻,判断参考点起点[0][0],终点[row-1][col-3]
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i][j + 2] && board[i][j] == '*' && board[i][j + 1] == ' ')
{
return 1;
}
}
}
//2.同一列三连
//2.1一列相同两枚棋子相邻,判断参考点起点[0][0],终点[col - 2][row - 1]
for (i = 0; i < row - 1; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == board[i + 1][j] && board[i][j] == '*')
{
if (i < col - 2 && board[i + 2][j] == ' ')
{
return 1;
}
else
if (board[i - 1][j] == ' ')
{
return 1;
}
}
}
}
//2.2一列相同两枚棋子不相邻,判断参考点起点[0][0],终点[col - 3][row - 1]
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == board[i + 2][j] && board[i][j] == '*' && board[i + 1][j] == ' ')
{
return 1;
}
}
}
//3.对角线
//3.1正对角线
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '*')
{
if (board[i + 2][j + 2] == ' ')
{
return 1;
}
}
if (board[i][j] == board[i + 2][j + 2] && board[i][j] == '*')
{
if (board[i + 1][j + 1] == ' ')
{
return 1;
}
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '*')
{
if (board[i - 1][j - 1] == ' ')
{
return 1;
}
}
}
}
//3.2副对角线
for (i = 2; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == '*')
{
if (board[i - 2][j + 2] == ' ')
{
return 1;
}
}
if (board[i][j] == board[i - 2][j + 2] && board[i][j] == '*')
{
if (board[i - 1][j + 1] == ' ')
{
return 1;
}
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == '*')
{
if (board[i + 1][j - 1] == ' ')
{
return 1;
}
}
}
}
return 0;
}
然后进行拦截,代码如下:
//拦截玩家函数
int BlockPlayer(char board[ROW][COL], int row, int col)
{
//1.同一行
int i = 0, j = 0;
//1.1一行相同两枚棋子相邻,判断参考点起点[0][0],终点[row-1][col-2]
for (i = 0; i < row; i++)
{
for (j = 0; j < col-1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] == '*')
{
if (j < col - 2 && board[i][j + 2] == ' ')
{
board[i][j + 2] = '#';
return 0;
}
else
if (board[i][j - 1] == ' ')
{
board[i][j - 1] = '#';
return 0;
}
}
}
}
//1.2一行相同两枚棋子不相邻,判断参考点起点[0][0],终点[row-1][col-3]
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i][j + 2] && board[i][j] == '*' && board[i][j + 1] == ' ')
{
board[i][j + 1] = '#';
return 0;
}
}
}
//2.同一列
//2.1一列相同两枚棋子相邻,判断参考点起点[0][0],终点[col - 2][row - 1]
for (i = 0; i < row - 1; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == board[i + 1][j] && board[i][j] == '*')
{
if (i < col - 2 && board[i + 2][j] == ' ')
{
board[i + 2][j] = '#';
return 0;
}
else
if (board[i - 1][j] == ' ')
{
board[i - 1][j] = '#';
return 0;
}
}
}
}
//2.2一列相同两枚棋子不相邻,判断参考点起点[0][0],终点[col - 3][row - 1]
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == board[i + 2][j] && board[i][j] == '*' && board[i + 1][j] == ' ')
{
board[i + 1][j] = '#';
return 0;
}
}
}
//3.对角线
//3.1正对角线
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '*')
{
if (board[i + 2][j + 2] == ' ')
{
board[i + 2][j + 2] = '#';
return 0;
}
}
if (board[i][j] == board[i + 2][j + 2] && board[i][j] == '*')
{
if (board[i + 1][j + 1] == ' ')
{
board[i + 1][j + 1] = '#';
return 0;
}
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '*')
{
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '#';
return 0;
}
}
}
}
//3.2副对角线
for (i = 2; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == '*')
{
if (board[i - 2][j + 2] == ' ')
{
board[i - 2][j + 2] = '#';
return 0;
}
}
if (board[i][j] == board[i - 2][j + 2] && board[i][j] == '*')
{
if (board[i - 1][j + 1] == ' ')
{
board[i - 1][j + 1] = '#';
return 0;
}
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i][j] == '*')
{
if (board[i + 1][j - 1] == ' ')
{
board[i + 1][j - 1] = '#';
return 0;
}
}
}
}
return 1;
}
4.无三连机会,且无需拦截,则靠近己方棋子落子,创造三连机会
代码如下:
//无三连机会,无需拦截,自行制造机会
int CreatWin(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
int a = 0, b = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == '#')
{
for (a = 0; a < row; a++)
{
for (b = 0; b < col; b++)
{
if ((a - i == -1 && b - j == -1)
|| (a - i == -1 && b - j == 0)
|| (a - i == -1 && b - j == 1)
|| (a - i == 0 && b - j == -1)
|| (a - i == 0 && b - j == 1)
|| (a - i == 1 && b - j == -1)
|| (a - i == 1 && b - j == 0)
|| (a - i == 1 && b - j == 1))
{
if (board[a][b] == ' ')
{
board[a][b] = '#';
return 0;
}
}
}
}
}
}
}
}
总结
1-3步均使用一套判断模式,第4步可应用在扫雷中的排查雷的步骤中。