我正在为类似国际象棋的游戏编写AI。 该板为10x10,每侧15个 所有国际象棋都有类似的举动。
游戏中的所有内容都以对象组织。 瓷砖[] []瓷砖; 10x10,每个Tile都有一个指向一个片段的指针或null。
到目前为止,我已经实现了MinMax算法,但没有修剪。 每轮可能的动作平均是国际象棋比赛的两倍。
算法有效,但速度很慢。平均而言,它可以检查 40000次/秒。所以深度为4,我的游戏使用大约4-5秒 计算所有可能的动作。我将在稍后实施修剪,但可能需要 首先对我的实施提出一些反馈。
问题: 我是否必须转换为char-arrays / bit-board或类似的以加速 计算还是我做错了什么?
实施:(sudo) 为了避免大量双重for循环,我会跟踪myPieces和opponentPieces 在瓷砖列表中。董事会评估也进行一次,然后只进行更新 并且只能通过添加和减去移动的值来更新。 在我的minMax算法的实现中,我使用了一个GameState类 持有当前的gameState。
GameState {
Tile[][] board
List<Tile> myPieces;
List<Tile> otherPieces;
int[][] evaluatedBoard
int evaluatedValue
Piece moveFrom, moveTo //used to save pointer when applying move
int moveFromValue, moveToValue //used to save evaluationValue when applying move
void applyMove(Tile from, Tile to)
void undoMove(Tile from, Tile to)
GameState createCopy()
}
ApplyMove仅更新evaluateValue而不会通过 整个array.myPieces和otherPieces也会通过apply / undo更新。
MINMAX:
maxMove(GameState state, int depth) {
for(Tile from : state.getMyPieces().clone()) { //list will be changed
for(Tile to : from.getPiece().getPossibleMoves()) {
if(depth == 0)
//find best move and so forth
else {
state.applyMove(from, to);
minMove(state.createCopy(), depth - 1) //similar to maxMove except it uses otherPieces
state.undoMove(from, to)
}
}
}
//return best move
}
编辑: 添加了有关applyMove和Profiler
的信息Profiler: instructions
applyMove() 3200ms 11 430 000
undoMove() 1800ms 11 430 000
evaluateTile() 1400ms 22 400 000
minMove() 1700ms 315 493
applyMove和undoMove只存储/反向旧指针 重视和取而代之的是新的 此举。然后调用evaluateTile,它返回1-10的数字 取决于枚举类型。
答案 0 :(得分:1)
您选择的代表性会花费很多 - 您考虑的每一个举动都需要您复制很多州。我看待它的方式,你有两个选择:
(1)使你的状态表示非常小(在国际象棋中,你可以用64 x 4位,或.NET中的4个Int64),所以复制它非常便宜;或
(2)使用deltas使你的状态表示不可变,因此创建一个更新状态很便宜。
我先尝试选项(1),看看你是怎么做的。
这里有一些您可能会觉得有用的链接: http://en.wikipedia.org/wiki/Board_representation_(chess) http://www.cis.uab.edu/hyatt/boardrep.html