【发布时间】:2019-05-30 14:43:47
【问题描述】:
我需要用每个节点的多个分支来表示一棵树。我应该使用什么结构?它用于计算国际象棋游戏状态。它呈指数级增长,因此内存将成为一个问题。我正在使用 C++11,但对其他标准持开放态度。此外,修剪应该是 O(1)。
编辑1 为了扩展,我将举办一场国际象棋人工智能比赛。主要的 PvP 游戏已经完成,接下来我正在编写 AI API。参赛者将编写自己的 AI,然后我们将让他们参加比赛。获胜者的 AI 将用于 Player vs Computer 游戏。我只是在考虑存储我的游戏状态和 AI 想法的最佳结构。
我正在阅读 Deep Blue,它认为前进了 5 到 25 步。我可以想象大多数计算机能够使用 BFS 处理 5 次深度移动,但任何更深的移动,我相信我将不得不使用 DFS。
AI 将被计时,竞争 AI 将仅在本地播放,以免在 CPU 功率方面引入优势。
我现在正在阅读 Monte Carlo 和 Alpha Beta 搜索。
我对数据结构的初步想法如下:
union CHESS_MOVE {
unsigned short m;
ChessPosT pos[2];
///...
};
class ChessMoveNode {
CHESS_MOVE move;
std::set<ChessMoveNode> nextmoves;
};
class ChessMoveTree {
std::set<ChessMoveNode> next;
};
可以通过连接从根到叶的路径随时计算板。尽管随着时间的推移重新计算电路板可能会变得非常昂贵。想法?我应该存放电路板吗?棋盘存储为一个包含 64 个字符索引的数组,其中包含一个棋子编号。所以是16个字节,相比2个,但是内存的使用会省去很多板子状态的重新计算。
对于我自己的个人 AI,我将实现一个棋盘评分功能,对游戏状态进行排名,然后丢弃所有非最大游戏状态,以及修剪因选择移动而无效的游戏状态。
【问题讨论】:
-
O(1) 是为了什么?总节点数?深度?
-
如果您正在执行 alpha-beta 搜索之类的操作,则不应显式存储树。此类算法使用 DFS 来避免存储树。如果您使用的是 MCTS,情况会有所不同。明确你想要实现的算法将有助于回答这个问题。
-
@Matthieu Brucher 在游戏过程中移除所有未选择的分支。
-
"它用于计算国际象棋游戏状态。它呈指数增长,因此内存将成为一个问题" - 正确。截至目前,任何设备都不可能存储代表每种可能的国际象棋场景所需的数据。您需要找到另一种方法或引入树的深度。
-
@BugSquasher 可能的国际象棋游戏数量为 10^120。可观测宇宙中的原子数约为 10^80。即使您以某种方式使用单个位来表示移动或棋盘状态,您也不走运。
标签: c++ c++11 tree artificial-intelligence chess