Prolog:游戏中的每个玩家都会玩牌。部分了解谁玩哪些牌,推断出谁玩了其他牌

时间:2016-04-26 20:36:02

标签: prolog logic clpfd

我试图用Prolog来解决一个简单的游戏,其中有3个玩家:Alice,Bob和Charlie。每个玩家秘密选择一张牌来玩牌,其中牌可以是红色或蓝色。然后洗牌并翻转。

假设爱丽丝的观点,我们知道她玩了哪张牌。因此,如果显示的卡片是蓝色,蓝色和红色,并且爱丽丝玩红色,那么她可以推断鲍勃和查理都是蓝色的。我正努力为此确定合适的原因。以下是我的基本事实:

player(alice).
player(bob).
player(charlie).

color(blue).
color(red).

% The overturned cards -- all players can see these. Order is unimportant.
cards([blue, red, red]).

played(alice, blue).

由此,我们应该能够推断鲍勃和查理各自都是红色的。我不确定如何告诉Prolog这三名球员中的每一位都在cards([blue, red, red])事实中完全打出一张牌。或许类似num_cards(blue, 1), num_cards(red, 2)的内容会更好?

作为一个稍微困难的例子,应该可以使用以下事实来推断Charlie玩了一张红牌(例如,如果Alice能够偷看Bob扮演的牌):

player(alice).
player(bob).
player(charlie).

color(blue).
color(red).

% The overturned cards -- all players can see these. Order is unimportant.
cards([blue, red, red]).

played(alice, red).
played(bob, blue).

我能找到的最类似的问题是this one,但我还没能将它应用到我的问题中。 CLPFD库肯定似乎很有用。

2 个答案:

答案 0 :(得分:1)

已经做了很好的背景搜索:+1!您链接到的问题和Boris's solution确实与此任务密切相关。

首先,我想指出你的任务在表面看起来很容易,并且表面看起来看起来适合Prolog初学者解决。在我看来,这样的任务根本不容易,当其他知识(例如:谁知道什么,在不同的层中)也必须被表示时,困难很快就会失控。我可以想象,那些完成作业任务的初学者会很快走开,感觉“我可以用Java轻松解决这个问题,但在Prolog中是不可能的”。他们无法用Java解决它的事实通常不会在最轻微的情况下打扰他们。

在这个具体案例中, 约束确实很合适。实际上,例如SICStus Prolog中提供的global_cardinality/2约束很容易解决这两个例子。

使用CLP(FD)约束时,诀窍是将您感兴趣的域映射到整数。在这种情况下,我将(任意)使用:

  • 1 blue
  • 2 红色

此外,我将简单地使用变量,每个人一个,代表该人所玩的具体“卡”(即整数)。我们的想法是指定我们所知道的,然后让约束求解器弄清楚其余部分。

所以我们在第一种情况下:

?- global_cardinality([Alice,Bob,Charlie], [1-1,2-2]),
   Alice = 1.
Alice = 1,
Bob = Charlie, Charlie = 2.

在第二种情况下:

?- global_cardinality([Alice,Bob,Charlie], [1-1,2-2]),
   Alice = 2,
   Bob = 1.
Alice = Charlie, Charlie = 2,
Bob = 1.

因此,在这两种情况下,只需说明给定的约束就足以推导出单个相应的解决方案,就像您预期的那样。

答案 1 :(得分:0)

我的提示需要一个'语法修改'来适应你的问题:从我的观点来看,将表达特定查询的事实与实体身份分开是必要的:所以,我建议进行游戏/ 2评估一组牌(当然是被推翻的牌)与牌手和牌之间的关系,表示为Player-Card

player(alice).
player(bob).
player(charlie).

color(blue).
color(red).

game(Cs, [P-C|Ps]) :-
    player(P), color(C),
    select(C, Cs, Other),
    game(Other, Ps),
    \+ memberchk(P-_, Ps).
game([], []).

现在,可以回答很多具体的问题。例如

game([blue, red, red], [alice-blue,bob-B,charlie-C]).
B = C, C = red ;
B = C, C = red ;
false.

?- so:game([blue, red, red], [alice-blue,X,Y]).
X = bob-red,
Y = charlie-red ;
...

?- game([blue, red, red], [alice-red, bob-blue, Y]).
Y = charlie-red ;
...

为避免重复解决方案,可以使用setof / 3。