- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用 alpha-beta pruning 编写算法跳棋游戏(AI vs AI)。可以看到代码&注释低于或在此 PasteBin .
游戏本身运行良好,但 AI(alpha-beta 剪枝算法)似乎存在错误,因为机器人基本上将跳棋喂给彼此(根本没有显示计算结果)。该代码包含 2 个不同版本的 alpha-beta 算法函数(更详细和不太详细)。
我已经尝试在 alphabeta()
中跟踪 tmp
的值,它似乎具有正常值(在深度 = 5 的情况下范围从 -3 到 3) .
我也试过实现 this代码进入我的,但得到了相同的结果。
我最好的猜测是问题出在 bool whiteTurn
中,它声明现在轮到谁了,但我找不到任何问题 - 轮次切换正确。
第二个最佳猜测 - Move bestMove
。我不确定将其从递归函数中剥离是否正确。
错误是什么?
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Move
{
public:
pair<int, int> start;
pair<int, int> end;
bool lethal;
Move(int x, int y, int x1, int y1, bool kill)
{
start.first = x; start.second = y;
end.first = x1; end.second = y1;
lethal = kill;
}
};
char **initBoard(int size)
{
char **board = new char*[size];
for (int count = 0; count < size; count++)
board[count] = new char[size];
return board;
}
void newGame(char **board, int size)
{
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
board[i][j] = '-';
if ((i == 0 || i == 2) && j % 2 == 1) board[i][j] = 'O';
if (i == 1 && j % 2 == 0) board[i][j] = 'O';
if ((i == size - 3 || i == size - 1) && j % 2 == 0) board[i][j] = 'X';
if (i == size - 2 && j % 2 == 1) board[i][j] = 'X';
}
}
void printBoard(char **board, int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cout << board[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void do_move(char **board, Move play)
{
char temp = board[play.start.first][play.start.second];
board[play.start.first][play.start.second] = board[play.end.first][play.end.second];
board[play.end.first][play.end.second] = temp;
if (play.lethal)
board[(play.end.first + play.start.first) / 2][(play.end.second + play.start.second) / 2] = '-';
}
void undo_move(char **board, Move play)
{
board[play.start.first][play.start.second] = board[play.end.first][play.end.second];
board[play.end.first][play.end.second] = '-';
if (play.lethal)
{
if (board[play.start.first][play.start.second] == 'X')
board[(play.end.first + play.start.first) / 2][(play.end.second + play.start.second) / 2] = 'O';
if (board[play.start.first][play.start.second] == 'O')
board[(play.end.first + play.start.first) / 2][(play.end.second + play.start.second) / 2] = 'X';
}
}
vector<Move> findMoves(char **board, int size, bool whiteTurn)
{
vector<Move> moves;
//first jump (if possible)
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
if (whiteTurn && board[x][y] == 'X')
{
if (x > 1 && y > 1 && board[x - 1][y - 1] == 'O' && board[x - 2][y - 2] == '-')
moves.push_back(Move(x, y, x - 2, y - 2, true));
if (x > 1 && y < size - 2 && board[x - 1][y + 1] == 'O' && board[x - 2][y + 2] == '-')
moves.push_back(Move(x, y, x - 2, y + 2, true));
if (x < size - 2 && y > 1 && board[x + 1][y - 1] == 'O' && board[x + 2][y - 2] == '-')
moves.push_back(Move(x, y, x + 2, y - 2, true));
if (x < size - 2 && y < size - 2 && board[x + 1][y + 1] == 'O' && board[x + 2][y + 2] == '-')
moves.push_back(Move(x, y, x + 2, y + 2, true));
}
if (!whiteTurn && board[x][y] == 'O')
{
if (x > 1 && y > 1 && board[x - 1][y - 1] == 'X' && board[x - 2][y - 2] == '-')
moves.push_back(Move(x, y, x - 2, y - 2, true));
if (x > 1 && y < size - 2 && board[x - 1][y + 1] == 'X' && board[x - 2][y + 2] == '-')
moves.push_back(Move(x, y, x - 2, y + 2, true));
if (x < size - 2 && y > 1 && board[x + 1][y - 1] == 'X' && board[x + 2][y - 2] == '-')
moves.push_back(Move(x, y, x + 2, y - 2, true));
if (x < size - 2 && y < size - 2 && board[x + 1][y + 1] == 'X' && board[x + 2][y + 2] == '-')
moves.push_back(Move(x, y, x + 2, y + 2, true));
}
}
}
//then move
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
if (whiteTurn && board[x][y] == 'X')
{
if (x > 0 && y > 0 && board[x - 1][y - 1] == '-')
moves.push_back(Move(x, y, x - 1, y - 1, false));
if (x > 0 && y < size - 1 && board[x - 1][y + 1] == '-')
moves.push_back(Move(x, y, x - 1, y + 1, false));
}
if (!whiteTurn && board[x][y] == 'O')
{
if (x < size - 1 && y > 0 && board[x + 1][y - 1] == '-')
moves.push_back(Move(x, y, x + 1, y - 1, false));
if (x < size - 1 && y < size - 1 && board[x + 1][y + 1] == '-')
moves.push_back(Move(x, y, x + 1, y + 1, false));
}
}
}
return moves;
}
//plain score calculation function
int getScore(char **board, int size, bool whiteTurn)
{
int whiteNum = 0, blackNum = 0;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (board[i][j] == 'X') whiteNum++;
if (board[i][j] == 'O') blackNum++;
}
}
if (whiteTurn)
return whiteNum - blackNum;
else
return blackNum - whiteNum;
}
//old function, doesnt work as intended too
/*Move getBestMove(char **board, int size, bool whiteTurn)
{
int score, tmp;
Move bestMove(0, 0, 0, 0, false);
vector<Move> movelist = findMoves(board, size, whiteTurn);
score = getScore(board, size, whiteTurn);
for (unsigned int i = 0; i < movelist.size(); i++)
{
do_move(board, movelist.at(i));
tmp = getScore(board, size, whiteTurn);
undo_move(board, movelist.at(i));
if (tmp >= score)
{
score = tmp;
bestMove = movelist.at(i);
}
}
return bestMove;
}*/
//made this global - no idea how to avoid it being global with recursion in alphabeta
Move bestMove(0, 0, 0, 0, false);
//alphabeta function with more detailed calculations
/*int AlphaBeta(char **board, int size, bool whiteTurn, int depth, int alpha, int beta)
{
if (depth == 0) return getScore(board, size, whiteTurn);
int score = -100;
vector<Move> movelist = findMoves(board, size, whiteTurn);
for (unsigned int i = 0; i < movelist.size(); i++)
{
do_move(board, movelist.at(i));
int tmp = -AlphaBeta(board, size, !whiteTurn, depth - 1, alpha, beta);
undo_move(board, movelist.at(i));
if (tmp > score)
{
if (whiteTurn)
{
if (score > alpha)
{
alpha = score;
}
if (-alpha <= beta)
{
return alpha;
}
}
else
{
if (score > beta)
{
beta = score;
}
if (-beta <= alpha)
{
return beta;
}
}
}
}
return score;
}*/
//generic alphabeta function
int alphabeta(char **board, int size, bool whiteTurn, int depth, int alpha, int beta)
{
if (depth == 0) return getScore(board, size, whiteTurn);
vector<Move> movelist = findMoves(board, size, whiteTurn);
for (const Move &move : movelist)
{
do_move(board, move);
int tmp = -alphabeta(board, size, !whiteTurn, depth - 1, -beta, -alpha);
undo_move(board, move);
if (tmp > alpha)
{
if (depth == 5)
bestMove = move;
alpha = tmp;
}
}
return alpha;
}
//main game loop
void game(char **board, int size, bool &whiteTurn)
{
newGame(board, size);
printBoard(board, size);
system("PAUSE");
int a = -std::numeric_limits<int>::max();
int b = std::numeric_limits<int>::max();
do
{
alphabeta(board, size, whiteTurn, 5, a, b);
do_move(board, bestMove);
whiteTurn = !whiteTurn;
system("cls");
printBoard(board, size);
system("PAUSE");
} while (!findMoves(board, size, whiteTurn).empty());
}
int main()
{
int n = 8;
bool whTurn = true;
char **board=initBoard(n);
game(board, n, whTurn);
return 0;
}
最佳答案
文献中通常描述的 alpha-beta 截断方式是不必要的复杂。你不需要两个限制,这也不是一个好主意从同一个玩家的角度来评估移动。这是一个更清晰的描述:
for all moves: evaluate the move give it a temporary score from the point of view of the player at move for all counter moves: evaluate the move give is a temporary score from the point of view of the player at move for all counter-counter moves: evaluate the move give it a score from the point of view of the player at move undo the counter-counter move update best counter-counter move if better if the counter-counter move is so good, that current counter move cant be best, (other is better) then break subtract best counter-counter-move score from temporary counter score undo the counter move update best counter move if better if the counter move is so good, that current move cant be best, (other is better) then break subtract best counter-move score from temporary score undo the move update best move if better
逻辑是这样的:
假设您已经评估了几个 Action ,到目前为止最好的 Action 值 3
当前走法暂时得分为5。
您当前评估的反击行动值(value) 4。
这意味着当前的移动最多值 1。(5-4)
既然当前的走法不可能是最好的,就不必再寻找更好的反走法了
关于使用 alpha-beta 剪枝的 C++ 检查器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33551928/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我不知道我问的是否可行。 我有一个带有 Color.BLACK 的 Paint 和 0.2f 的 alpha 和两个对象: 它们都使用相同的Paint。我还测试了 2 个不同的 Paint 对象,仅更
Alpha Vantage API 不提供纳斯达克指数的报价(不再?)。我感兴趣的所有其他 indizes 似乎都很有魅力。 例如,调用以下 URL(隐藏 API key )将提供 S&P 的报价(符
问:有没有办法使用默认管道正确混合 Alpha 分量? 问题:我正在将半透明表面绘制到纹理中,然后我想将该纹理传输到主框架后台缓冲区中。通常,当您使用直接的 Alpha 混合来实现透明度或抗锯齿时,会
如果我有一个底层颜色和一个 alpha 值 (C&A),并且想在屏幕上创建一个自定义 C&A,那么确定必须将什么 C&A 作为底层添加到底层之上的层的函数是什么? 编辑: 我想复制 photoshop
我想知道它们之间的区别: 给我的 UIView 分配一个颜色 <1 alpha vs 为它指定一个不透明的颜色,但给 UIView 一个 <1 的 alpha 值。 在屏幕截图上,我制作了两个 UIV
我在 OSX 10.9.4 上试图转换这个 python 正则表达式 p = "(2024 (?:(?:(?:[a-z|.]+ ?)+)) 93)"到 Unix 正则表达式以提高 grep 的速度。
我为 4 张图像制作了这个脚本,第一张图像是 alpha,但从第二张开始什么都没有显示 这是ffmpeg的代码确实有错误,但我没有。不明白:[swscaler @ 0x7fef79845e00] 使用
我正在尝试将文本绘制到具有特定 Alpha 级别的 Canvas 上,并剪辑文本并使用其自己的 Alpha 级别绘制背景颜色: ctx.globalCompositeOperation = '...'
我需要实现Lasso和Ridge回归,并通过交叉验证的方式计算超参数。我找到了执行此操作的代码,但我不太理解它。 lassocv = LassoCV(alphas=None, cv=15, max_i
我得到我的位图,将它用作着色器平铺模式。 除了要绘制的形状轮廓外,PNG 大部分是 alpha。 除了它画出轮廓,但被黑色包围,不是透明的(alpha)。 pnt.reset(); i
我正在开发一个带有 tableViewController 的应用程序。我想在我的表格 View 单元格下方添加背景图片。我想让表格 View 单元格透明,以便我的整个表格 View 可以具有自定义背
如图所示,我有 2 个具有 0.5 alpha 和 1 alpha 的按钮。我想将第一张图片中标题的 alpha 更改为 1,这可能吗? 到目前为止,我尝试了这些都不起作用: button.title
我正在尝试生成一个 python 正则表达式来表示词法分析器的标识符。我的做法是: ([a-zA-Z]([a-zA-Z]|\d)*) 当我使用它时: regex = re.compile("\s*([
我正在尝试删除所有非数字字符的字符串,并且我已阅读 Why isn't isnumeric working? ,或者我必须有一个 unicode 字符串。然而,自从 is.alnum()和is.alp
来自 hadoop 网站上的发布页面: “This release, like previous releases in hadoop-2.x series is still considered a
真的没有与 setAlpha(int) 对应的 XML 属性吗? 如果没有,有什么替代方案? 最佳答案 它比其他响应更容易。有一个 xml 值 alpha 采用 double 值。 android:a
我正在three.js 中构建一个“ Papercut ”世界。我所有的模型都是简单的“平面”,我使用带有 Alpha channel 的 PNG 对它们进行纹理处理,以将平面修剪成更令人愉悦的形状。
我想知道 Graphics2D.setComposite(..., alpha) 之间是否真的有区别和 Graphics2D.setColor(new Color(..., alpha))在 Java
我需要在两个图像之间进行转换 - 两个图像都是隐藏下面的 Sprite 的蒙版。每个面具的一部分是白色的,一部分是透明的。我需要两个图像的总 alpha 每次都为 1,这样蒙版看起来会平滑地改变其形状
我是一名优秀的程序员,十分优秀!