错误:在策划游戏中脱离全局堆栈

时间:2017-01-24 18:07:01

标签: prolog

我正在尝试实施策划游戏,规则可以在https://en.wikipedia.org/wiki/Mastermind_(board_game)上找到。

程序生成四种不同颜色的序列。 玩家有10个回合来猜测代码。

我知道代码可以改进,但是现在我正在尝试解决全局堆栈错误。当我计算白钉的数量时会发生这种情况,但并非总是如此。可能问题在于共同或不同的谓词(或两者)。

我是Prolog的初学者,我很感激任何帮助。

请在https://github.com/kmdeoliv/mastermind

上找到代码

1 个答案:

答案 0 :(得分:1)

member1替换为memberchk,您的代码会更好用。之所以会让你大吃一惊!让我们为你的member1/2谓词添加一些“调试printfs”:

member1(X,[H|_]) :- format('testing ~w == ~w?~n', [X,H]), X==H,!.
member1(X,[_|T]) :- format('looking in tail ~w for ~w~n', [T,X]), member1(X,T).

似乎工作正常,对吧?

?- member1(bar, [foo,bar,baz]).
testing bar == foo?
looking in tail [bar,baz] for bar
testing bar == bar?
true.

顺便说一句,memberchk/2做同样的事情:

?- memberchk(bar, [foo,bar,baz]).
true.

好吧,我们得到“真实”。 :)但是如果我传递一些奇怪的东西会发生什么,比如变量而不是列表?

?- memberchk(bar, V).
V = [bar|_G483709].

啊,好吧,memberchk/2将此作为某种断言,它位于列表的顶部(这是因为它执行member/2所做的但只有一个解决方案)。 member1/2做了什么?

?- member1(bar, V).
looking in tail _G478121 for bar
testing bar == _G478129?
looking in tail _G478130 for bar
testing bar == _G478138?
looking in tail _G478139 for bar
testing bar == _G478147?
looking in tail _G478148 for bar
testing bar == _G478156?
looking in tail _G478157 for bar
testing bar == _G478165?
looking in tail _G478166 for bar
testing bar == _G478174?
looking in tail _G478175 for bar
testing bar == _G478183?
...
eventually, boom, stack depth exceeded

令人惊讶的是,您的代码实际上已进入此案例!请注意,您有条件在一侧定义变量而不在另一侧定义变量:

(B1==B2 -> K is J + 1; K is J + 0, LB1=[B1],LB2=[B2]),

如果B1不等于B2,LB1LB2会假设什么值?它们仍未被实例化!然后几行后你无条件地追加它们:

append(LA1,LB1,AB1),
append(LC1,LD1,CD1),
append(AB1,CD1,L1),

所以到目前为止,L1 = LA1 + LB1 + LC1 + LD1,但LB1是纯变量!这可能发生在任何的LX1 / LX2变量上,然后您最终输入member1/2列表中的某种洞!

顺便说一句,这不是Prolog中的错误。例如,有时您希望将列表的尾部留下未实例化的差异列表。

现在,我已经为你提供了其他一些建议,但我认为现在故事的寓意是你应该尽可能使用内置的谓词。 :)