4/19学习总结

文章描述了一个计算积分的算法,用于人机对战的棋盘游戏中。该算法遍历每个空白位置,评估可能的连子情况,为下一步AI走棋提供评分。当找到最高评分的坐标时,AI应在该位置下棋。然而,作者遇到的问题是ai_think()函数未能正确执行自动下棋。
摘要由CSDN通过智能技术生成

今天还是项目

今天就搞了那个人机操作,但是很痛苦,弄了一天都没弄出来,不知道是哪个地方出了问题,对于人机操作的话最开始的算法就是计算积分

void ai_calculateScore( )
{
	// 统计玩家或者电脑连成的子
	int personNum = 0;  // 玩家连成子的个数
	int botNum = 0;     // AI连成子的个数
	int emptyNum = 0;   // 各方向空白位的个数

	// 清空评分数组
	for (int i = 0; i < 15; i++) {
		for (int j = 0; j < 15; j++) {
			scoreMap[i][j] = 0;
		}
	}

	int size = b_wide;
	for (int Row = 0; Row < size; Row++)
		for (int Col = 0; Col < size; Col++)
		{
			// 空白点就算
			if (board[Row][Col] == 0) {
				// 遍历周围八个方向
				for (int y = -1; y <= 1; y++) {
					for (int x = -1; x <= 1; x++)
					{
						// 重置
						personNum = 0;
						botNum = 0;
						emptyNum = 0;

						// 原坐标不算
						if (!(y == 0 && x == 0))
						{
							// 每个方向延伸4个子
							// 对黑棋评分(正反两个方向)
							for (int i = 1; i <= 4; i++)
							{
								int curRow = Row + i * y;
								int curCol = Col + i * x;
								if (curRow >= 0 && curRow < size &&
									curCol >= 0 && curCol < size &&
									board[curRow][curCol] == 1) // 真人玩家的子
								{
									personNum++;
								}
								else if (curRow >= 0 && curRow < size &&
									curCol >= 0 && curCol < size &&
									board[curRow][curCol] == 0) // 空白位
								{
									emptyNum++;
									break;
								}
								else            // 出边界
									break;
							}

							for (int i = 1; i <= 4; i++)
							{
								int curRow = Row - i * y;
								int curCol = Col - i * x;
								if (curRow >= 0 && curRow < size &&
									curCol >= 0 && curCol < size &&
									board[curRow][curCol] == 1) // 真人玩家的子
								{
									personNum++;
								}
								else if (curRow >= 0 && curRow < size &&
									curCol >= 0 && curCol < size &&
									board[curRow][curCol] == 0) // 空白位
								{
									emptyNum++;
									break;
								}
								else            // 出边界
									break;
							}

							if (personNum == 1)                      // 杀二
								scoreMap[Row][Col] += 10;
							else if (personNum == 2)                 // 杀三
							{
								if (emptyNum == 1)
									scoreMap[Row][Col] += 30;
								else if (emptyNum == 2)
									scoreMap[Row][Col] += 40;
							}
							else if (personNum == 3)                 // 杀四
							{
								// 量变空位不一样,优先级不一样
								if (emptyNum == 1)
									scoreMap[Row][Col] += 60;
								else if (emptyNum == 2)
									scoreMap[Row][Col] += 200;
							}
							else if (personNum == 4)                 // 杀五
								scoreMap[Row][Col] += 20000;

							// 进行一次清空
							emptyNum = 0;

							// 对白棋评分
							for (int i = 1; i <= 4; i++)
							{
								int curRow = Row + i * y;
								int curCol = Col + i * x;
								if (curRow > 0 && curRow < size &&
									curCol > 0 && curCol < size &&
									board[curRow][curCol] == -1) // 玩家的子
								{
									botNum++;
								}
								else if (curRow > 0 && curRow < size &&
									curCol > 0 && curCol < size &&
									board[curRow][curCol] == 0) // 空白位
								{
									emptyNum++;
									break;
								}
								else            // 出边界
									break;
							}

							for (int i = 1; i <= 4; i++)
							{
								int curRow = Row - i * y;
								int curCol = Col - i * x;
								if (curRow > 0 && curRow < size &&
									curCol > 0 && curCol < size &&
									board[curRow][curCol] == -1) // 玩家的子
								{
									botNum++;
								}
								else if (curRow > 0 && curRow < size &&
									curCol > 0 && curCol < size &&
									board[curRow][curCol]==0) // 空白位
								{
									emptyNum++;
									break;
								}
								else            // 出边
									break;
							}

							if (botNum == 0)                      // 普通下子
								scoreMap[Row][Col] += 5;
							else if (botNum == 1)                 // 活二
								scoreMap[Row][Col] += 10;
							else if (botNum == 2)
							{
								if (emptyNum == 1)                // 死三
									scoreMap[Row][Col] += 25;
								else if (emptyNum == 2)
									scoreMap[Row][Col] += 50;  // 活三
							}
							else if (botNum == 3)
							{
								if (emptyNum == 1)                // 死四
									scoreMap[Row][Col] += 55;
								else if (emptyNum == 2)
									scoreMap[Row][Col] += 10000; // 活四
							}
							else if (botNum >= 4)
								scoreMap[Row][Col] += 30000;   // 活五,应该具有最高优先级
						}
					}
				}
			}
		}
}

具体来说,该算法遍历棋盘上每个空白位置,然后在该位置的周围八个方向上分别向两个方向(正反方向)延伸四个子,统计出在该方向上人类玩家和AI电脑分别连成的子的数量和周围的空白位置数,最后根据这些信息为该空白位置评分,评分规则如下:

  • 如果人类玩家在该方向上连了1个子,AI电脑在该方向上可以杀掉一个子,给该空白位置加10分。
  • 如果人类玩家在该方向上连了2个子,AI电脑在该方向上可以杀掉两个子,给该空白位置加30分(如果周围有1个空白位置)或40分(如果周围有2个空白位置)。
  • 如果人类玩家在该方向上连了3个子,AI电脑在该方向上可以杀掉三个子,给该空白位置加60分(如果周围有1个空白位置)或200分(如果周围有2个空白位置)。
  • 如果人类玩家在该方向上连了4个子,AI电脑在该方向上可以杀掉四个子,给该空白位置加20000分。
  • 如果AI电脑在该方向上连了5个子,AI电脑已经胜利,给该空白位置加100000分

其次就是一个ai_think()函数,找到积分最大的坐标返回出来,然后在自动在该位置下棋,但是今今天一直按都没有用,他不能自动下棋,检查了n遍都还没发现问题,都要崩溃了,哎

void ai_think(int*k)
{
	// 计算评分
	ai_calculateScore();

	// 从评分中找出最大分数的位置
	int maxScore = 0;

	int size = b_wide;
	for (int i = 0; i < size; i++) {
		for (int j = 0;j < size; j++)
		{
			// 前提是这个坐标是空的
			if (board[i][j] == 0) {
				if (scoreMap[i][j] > maxScore)          // 找最大的数和坐标
				{
					maxScore = scoreMap[i][j];
					k[0] = i;k[1] = j;
				}
				else if (scoreMap[i][j] == maxScore) {   // 如果有多个最大的数,都存起来
					k[0] = i;k[1] = j;
				}
			}
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值