今天还是项目
今天就搞了那个人机操作,但是很痛苦,弄了一天都没弄出来,不知道是哪个地方出了问题,对于人机操作的话最开始的算法就是计算积分
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;
}
}
}
}
}