c# - 具有复杂板表示的 AI : simulating a single possible move

标签 c# artificial-intelligence

<分区>

我目前正在使用 C# 开发基于回合制的基于网格的策略游戏(类似于魔法门之英雄无敌和奇迹时代)。首先关注战斗部分。
一个格子上有多个单元,轮流进行攻击、射击、施法、移动等。

在 AI 编程上遇到了一些困难。我想要一个可以提前计划的人工智能,所以我认为寻找最佳行动的过程可能是这样的:

  1. 生成可能的 Action 列表
  2. 对于每个可能的移动:
    • 模拟移动
    • 评估状态

然后我在 Minimax 算法中重复这个过程,有点类似于创建国际象棋 AI。

与制作国际象棋 AI 的最大区别在于“棋盘表示”(或状态);这个游戏有很多复杂性,简单地将状态存储为整数数组是不够的。有多个单位,各种领域,储存生命值,攻击类型,他们如何移动和特殊能力等等......。

所以我面临的问题是在“模拟移动”部分。我需要制作一个像 (previous state, move) => state 这样的函数。我通常复制以前的状态并在副本上执行移动。但是我找不到一种有效的方法来复制将执行移动的状态,因为它非常复杂,有很多不同的对象。并且此举不应改变之前的状态。

什么是模拟走法而不让它影响当前棋盘的良好代码结构?

这可能可以通过为每一步都设置一个 Undo() 方法来完成,但是随着逻辑变得复杂,将很难跟踪所有已更改的内容。

我可能正在寻找某种软件设计模式,或者如果有人做过类似的事情,我想知道他们是否遇到过这个问题。

Stack Overflow 上的很多问题都在谈论棋盘游戏 AI,但它似乎总是与具有简单棋盘表示的国际象棋/井字棋有关。

最佳答案

这看起来也是大多数约束规划求解器 处理的问题。一般来说,这些实现了 Command 之间的混合。和 Memento图案。其工作方式如下:

您需要一个代表游戏状态的类(此处称为State)。包含例如棋盘状态、可以移动的当前玩家、每个玩家拥有的资源(如果这是游戏的一部分)等的东西。您最好将此类状态设为 ICloneable 的实例。 : 这样就可以克隆状态并对它进行假设处理。

所以:

     ICloneable
          ^
          |
+-------------------+
|       State       |
+-------------------+
|+ Clone() : Object |
+-------------------+

接下来你有一个类IMove这代表了国家可能采取的行动。 IMove可以Alter State .在大多数情况下,此类方法返回的内容为 IAlterResult。 : 一个存储一些数据的对象,例如撤消移动。

+------------------------------+
|            IMove             |
+------------------------------+
|+ Alter(State) : IAlterResult |
+------------------------------+

+---------------------+
|    IAlterResult     |
+---------------------+
|+ Undo(State) : void |
+---------------------+

例如,如果您从棋盘上移除一 block 棋子,IAlterResult存储那件作品所在的位置,以防万一您撤消移动,IAlterResult可以将棋子(作为示例)放回棋盘上。

每次你做一个IMove ,你推对应的IAlterResultStack<IAlterResult> 上.因此,该堆栈会跟踪已完成的移动,并且可以通过迭代弹出 IAlterResult 来跟踪。 s 并执行 Undo命令带来 State回到原来的状态。

大多数约束规划求解器交错 State 的副本与 IAlterResults .因此,堆栈看起来像。

+---------------+
| AlterResult5  |
| AlterResult4  |
| Copy2         |
| AlterResult3  |
| AlterResult2  |
| AlterResult1  |
| Original copy |
+---------------+

如果你想回溯四个状态,你可以先看看是否有可用的副本,只需弹出前两个更改(没有 Undo ing)然后使用 Copy2并撤销 AlterResult3AlterResult2 .如果撤消操作需要大量计算结果,这可以获得一些效率。

您还可以将您的移动存储在 IAlterMove 中在这种情况下 - 如果移动无法撤消,或者很难撤消 - 您可以简单地回溯到最后保存的副本并执行堆栈中的所有移动。因此,例如,如果您想撤消最后一步( AlterResult5 )但结果无法撤消,则可以使用 Copy2并重做存储在 AlterResult4 中的移动.

关于c# - 具有复杂板表示的 AI : simulating a single possible move,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30448557/

相关文章:

artificial-intelligence - 为什么允许对角线移动会使 A* 和曼哈顿距离 Not Acceptable ?

artificial-intelligence - 学习概率图形模型的好资源

c# - 在 C# winforms 应用程序中使用 SQLite - 一些基本问题?

c# - .NET 是否有办法将空字符串解析为 String.Empty?

c# - 在通过 P/Invoke 获取的 C++ 结构上设置 C# 回调

c# - 如何从具有 ASPX 扩展名的 URL 提供图像?

c# - 如何以编程方式从后面的代码更改选定的 tabItem 标题颜色

machine-learning - 神经网络将数据分为 3 类,没有规则

javascript - Tensorflow.js 神经网络中的反向传播

neural-network - 在反向传播算法中更新权重