【问题标题】:java draughts AI (multithreaded)java 草稿 AI(多线程)
【发布时间】:2012-05-12 11:03:24
【问题描述】:

这是我在这里的第一个问题,如果我做错了什么,请告诉我...

我目前正在用 Java 制作草稿游戏。事实上,除了人工智能之外,一切都正常。 AI 目前是单线程的,使用 minimax 和 alpha-beta 修剪。这段代码有效,我认为,它只是很慢,我只能深入我的游戏树 5。

  1. 我有一个函数可以接收我的主板、一个深度(从 0 开始)和一个最大深度。在这个 maxdepth 处,它会停止,返回棋盘上棋子最多的玩家的值(-1,1 或 0)并结束递归调用。
  2. 如果尚未达到最大深度,我会计算所有可能的动作,并一一执行,以某种方式将我的更改存储到主板。
  3. 我还使用 alpha-beta 修剪,例如当我找到一个可以让玩家获胜的动作时,我不会在意接下来可能的动作。
  4. 我从该主板状态递归地计算下一组移动。退出递归调用时,我撤消了这些更改(从第 2 点开始)。我存储这些递归调用返回的值并在它们上使用极小值。

情况就是这样,现在我有一些问题。 我想更深入地研究我的游戏树,因此我必须减少计算移动所需的时间。

  1. AI 可能的动作(例如 AI 可以选择的动作)的值总是 0 是否正常?或者如果我可以更深入地研究递归,这种情况会改变吗?因为此时我只能进行 5 次深度 (maxdepth) 的递归,否则会花费太长时间。
  2. 我不知道它是否有用,但我可以如何将此递归转换为多线程递归。我认为这可以将工作时间除以某个值...

有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: java artificial-intelligence


    【解决方案1】:

    1. AI的可能动作(例如AI可以选择的动作)的值总是0是否正常?

    对我来说听起来很奇怪。如果可能的移动数为 0,则该玩家不能玩他的回合。这应该不是很常见,还是我误解了什么?

    如果您所指的值代表该动作的“分数”,那么显然“总是 0”表示所有动作都同样好,这显然不是一个很好的 AI 算法。

    2.我不知道它是否有用,但是如何将此递归转换为多线程递归。我认为这可以将工作时间除以某个值...

    我相信它会非常有用,尤其是考虑到如今大多数机器都有多个内核。

    让事情变得复杂的是你的“尝试一个动作,记录它,撤消它,尝试下一步”的方法。这表明您正在使用可变数据结构,这使得并行化算法变得极其复杂。

    如果我是你,我会让边框/游戏状态由一个不可变数据结构来表示。然后,您可以将每个递归调用视为一个单独的任务,并使用线程池来处理它们。您将接近 CPU 的最大利用率,同时大大简化代码(通过删除整个恢复到先前状态的代码)。

    假设您的机器上确实有多个内核,这可能会让您更深入地了解树。

    【讨论】:

    • 1.后者是案例。我知道我进入树越深,就有可能获得 1 或 -1 的增长,但这需要时间。 2.起初我复制了整个棋盘的待办事项/撤消动作(不可变)。我根本不知道如何正确分离这些任务。
    • 这可能是真的。在每个递归调用中,您通常有多少个子选择?
    • 一开始,大概有9个子选项。我不能更深入,因为它需要太长时间:(
    • 在游戏中期,您将有 > 20 个选择,a/b 修剪会将其平均减少到 10 个。这意味着 10 个核心只会为您的深度增加 1 个级别(层)。
    • @notused:你说2. At first I copied the whole board todo/undo a move (immutable)。在每次修改之前简单地对可变数据结构进行深拷贝,并不能将其变成一个好的不可变数据结构。
    【解决方案2】:

    我强烈推荐阅读这本书:

    One Jump Ahead: Computer Perfection At Checkers

    它将为您提供有关跳棋游戏中计算机 AI 的深入历史,并可能为您的评估功能提供一些帮助。

    不要让评估函数只给不同的棋子打分 1/0/-1,而是给每个常规棋子打 100 分,给国王打 200 分。然后给块结构奖金。例如,如果我的棋子形成了一个无法被捕获的安全结构,那么我会得到奖励。如果我的棋子独自在棋盘中间,那么我会得到负奖金。正是这种片段配置的丰富功能将使您的程序运行良好。最终得分为双方选手的评价之差。

    此外,您不应该以统一的深度停止搜索。静止搜索会扩展搜索,直到棋盘“安静”。在跳棋的情况下,这意味着棋盘上没有强制捕获。如果您不这样做,您的程序将运行得非常糟糕。

    正如其他人所建议的那样,转置表可以很好地减小搜索树的大小,尽管程序运行速度会稍微慢一些。我还推荐历史启发式,它易于编程,并且将大大改善树中移动的顺序。 (有关这方面的更多信息,请参阅 Google 历史启发式。)

    最后,董事会的代表可以产生很大的影响。搜索的快速实现不会在每次应用移动时都复制棋盘,而是尝试快速修改棋盘以应用和撤消移动。

    【讨论】:

    • 我会考虑的。我会尝试不同的评分系统。我会尝试增加我的搜索深度。我仍然不知道转置表。关于最后一点:目前我不复制整个板,移动,跟踪更改,然后在必要时撤消更改。
    【解决方案3】:

    (我假设您所说的草稿是指我们在美国所说的检查员。)

    我不确定我是否了解游戏树中的评分系统。您是否通过说“如果玩家的棋子比对手多,位置得分 1 分,玩家的棋子少 -1 分,如果他们的棋子数量相同,则得分为 0 分?”

    如果是这样,那么您的算法可能只是前五步的捕获厌恶,或者事情正在解决,以便所有捕获都是平衡的。我对跳棋并不十分熟悉,但似乎不可能在游戏中只有五步棋就可以做到这一点。如果它只有 5 个(其中一个层是一个玩家的移动,而不是一组完整的对立移动),这可能并不罕见。

    您可能想通过输入一个您绝对知道正确答案的棋盘位置来测试这一点,也许棋盘上只有两个棋子,其中一个棋子可以捕获。

    不过,作为一般原则,棋盘评估功能没有多大意义——它忽略了棋子和加冕棋子之间的区别,将三人优势与单人优势相同件优势。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-21
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多