如何在Prolog中编写特定的游戏?

如何在Prolog中编写特定的游戏?,prolog,state-space,Prolog,State Space,我对下面描述的程序编码有问题 考虑下面的游戏。给出了一块有三块黑石头、三块白石头和一个空白的木板。游戏的目标是用白兵交换黑兵的位置。移动规则定义了以下句子:交替移动白色和黑色片段。每个棋子可以垂直或水平移动,占据一个空白区域。每一块可以垂直或水平地跳到另一块(任何颜色)上。用Prolog编写一个程序,找出所有可能的方法来找到一个成功的序列。例如,如果我们问这个问题: ? - play (w, s (w, w, w, e, b, b, b), s (b, b, b, e, w, w, w), S,

我对下面描述的程序编码有问题

考虑下面的游戏。给出了一块有三块黑石头、三块白石头和一个空白的木板。游戏的目标是用白兵交换黑兵的位置。移动规则定义了以下句子:交替移动白色和黑色片段。每个棋子可以垂直或水平移动,占据一个空白区域。每一块可以垂直或水平地跳到另一块(任何颜色)上。用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的回答是什么意思?提示:先解决不带R的
play/4
问题

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

我根本不知道从哪里开始?我该怎么做?你们能帮我解决这个问题吗?

这是一个标准,至少从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
表示白色,
b
表示黑色,
e
表示空令牌)或列出令牌及其位置。让我们列出董事会的职位

在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移动;如果字段1中已经有令牌,则无法将令牌移动到字段1)

因此,您需要编写一个谓词,将线路板状态链接到适用于该状态的运算符:
generate\u applicative\u operators/2

然后,您需要选择要应用的运算符。这可以根据一些启发式(例如)随机、彻底地完成,但到目前为止肯定需要检查通过状态空间的路径以避免循环:
select\u operator/3

然后,您应用操作符以生成下一个状态:
apply\u operator/3

最后递归调用
search/3
查找下一步。这将一直持续到“最终状态”,在这种情况下,
[b,b,e,w,w]
已达到

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


就这样。

几个小时前,同样的问题已经发布了:-建议在这一问题上合作。除了我是第一个写这个问题的人。但我想我们都需要为学校做这些。嗯,是的。这个问题甚至可能已经在“序言”问题堆中的某个地方了。我看到另一个提问者已经消失了他/她的问题。好吧。