【问题标题】:How can I code a specific game in Prolog?如何在 Prolog 中编写特定游戏?
【发布时间】:2020-06-03 17:06:38
【问题描述】:

我在编写下述程序时遇到问题

考虑以下游戏。给出了一个带有三颗黑子、三颗白子和一个空白区域的棋盘。游戏的目标是将黑棋子与白棋子交换位置。移动规则定义以下句子: 交替移动白色和黑色块。每个棋子可以垂直或水平移动,占据一个空白空间。每一块都可以垂直或水平地跳过另一块(任何颜色)。在 Prolog 中编写一个程序,找出所有可能的方法来找到一个获胜的序列。例如,如果我们问这个问题:

? - play (w, s (w, w, w, e, b, b, b), s (b, b, b, e, w, w, w), S, R ). 

序言应该回答,例如:

S = [s (w, w, w, e, b, b, b), s (w, e, w, w, b, b, b), ..., s (b, b, b, e, w, w, w)] R = [[w, 2,4], [b, 6,2], [w, 4,6], ..., [w, 4,6]] 

这里的[ w, 2,4] 表示将白兵从位置 2 移动到位置 4。当然 Prolog 应该完整返回字母 S 和 R(不带“...”)。

棋盘上不同棋子设置的最大数量是多少?检查查询:

? - play (_, s (w, w, w, e, b, b, b), s (b, b, e, w, w, b, w), _, _).

Prolog 的回答是什么意思?提示:先解决 play/4 的问题,不用 R

还有一个游戏板,看起来像这样:

我什至不知道从哪里开始?我怎样才能做到这一点?你们能帮我解决这个问题吗?

【问题讨论】:

  • 几个小时前已经发布了同样的问题:stackoverflow.com/questions/62199178/… - 建议一起解决这个问题。
  • 除了我是第一个写这个问题的人。但我想我们都需要为学校这样做。
  • 嗯,是的。该问题甚至可能已经在“Prolog”问题堆栈中的某个位置。
  • 我看到候补提问者的问题消失了。嗯嗯。

标签: prolog state-space


【解决方案1】:

这是一个标准的state space search,至少从 50 年代中期开始就是 GOFAI 的标准范式。

准系统算法:

search(State,Path,Path) :- is_final(State),!.  % Done, bounce "Path" term
search(State,PathSoFar,PathOut) :- 
   generate_applicable_operators(State,Operators),
   (is_empty(Operators) -> fail ; true),   
   select_operator(Operators,Op,PathSoFar),
   apply_operator(State,Op,NextState), % depth-first / best first 
   search(NextState,[[NextState,Op]|PathSoFar],PathOut).

% Called like this, where Path will contain the reverse Path through
% State Space by which one may reach a final state:

search(InitialState,[[InitialState,nop]],Path).

首先您需要表示一个给定的状态,在这种情况下是棋盘的状态(在某个时间t)

我们可以列出董事会位置及其内容(w 代表 whiteb 代表 blacke 代表 empty em> token) 或列出令牌及其位置。让我们列出董事会的位置。

在 Prolog 中,可以轻松进行模式匹配的术语是合适的。这个问题已经提供了一些东西:(w, w, w, e, b, b, b)。这似乎是受到 LISP 的启发,并不能很好地适应 Prolog。让我们改用一个列表:[w, w, w, e, b, b, b]

董事会位置到列表位置的映射应为:

       +---+---+
       | 0 | 1 |
   +---+---+---+
   | 2 | 3 | 4 |
   +---+---+---+
   | 5 | 6 |
   +---+---+

我们已经完成了状态描述的设置!

然后您需要表示/定义可应用于状态的运算符(操作?):它们将有效状态转换为另一个有效状态。

运算符对应于“移动令牌”,当然并非所有运算符都适用于给定状态(如果没有令牌,则不能从字段 1 移动令牌;如果已经有令牌,则不能将令牌移动到字段 1是那里的令牌)。

所以您想编写一个谓词,将棋盘状态链接到适用于该状态的运算符:generate_applicable_operators/2

然后您需要选择要应用的运算符。这可以根据一些启发式方法(例如 A*)随机、详尽地完成,但绝对需要检查到目前为止通过状态空间所采用的路径以避免循环:select_operator/3

然后你应用运算符来生成下一个状态:apply_operator/3

最后递归调用search/3 寻找下一步行动。这一直持续到“最终状态”,在本例中为 [b, b, b, e, w, w, w]

如果要执行“广度优先搜索”,也可以使用Iterative Deepening,但必须修改算法结构。

就是这样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多