【C语言】三子棋实现AI智能落子(简单语法)

文章介绍了棋盘游戏中电脑AI的策略,包括开局占中或占角、寻找并尝试三连、拦截玩家的三连机会以及在没有明显优势时靠近己方棋子落子以创造三连机会。代码示例展示了这些策略的具体实现,涉及同行、同列及对角线的判断。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


提示:以下是本篇文章正文内容,下面案例可供参考

一、实现逻辑

  • 落子优先级(叙述为电脑视角)
    • 一手占中,若中心被占则占角(默认为电脑后手)
    • 有三连机会,尝试三连
    • 玩家有三连机会,进行拦截
    • 靠近己方棋子落子
  • 实现方法均为基础的循环和判断语句,并且适用于不同规格的棋盘
  • 基本逻辑:判断同行、同列、正副对角线是否有两棋相同,且可能三连的位置为空


    • 以同列且两棋不相邻为例(为确保一般性,这里使用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步可应用在扫雷中的排查雷的步骤中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值