我的目标是开发一个简单的程序来运行一个名为'Kayles'的游戏,类似于Skittles。你有一排瓶子,2名玩家轮流击倒他们,最后击倒最后一瓶的玩家获胜。你可以只敲下1或2瓶,它们必须彼此相邻。
该计划的第一部分是决定如何代表一个瓶子和一个空的空间。我决定使用一个列表,其中1代表一个瓶子,0代表一个空白区域。
该程序的第二部分是将当前状态打印到终端,其中瓶子用星号*表示,空格用间隙表示。
该程序的第三部分是列出并打印从当前状态可到达的所有可能的下一个状态。例如,如果你有3瓶[1,1,1],一个可能的下一个状态是[0,1,1],因为第一个瓶被击倒。所以这个谓词应该打印一个所有可能的下一个状态的列表,再次用*和空格表示。
我已成功完成上述操作,到目前为止这是我的代码:
printstate([]) :- nl.
printstate([B|L]) :- (B=0 -> write(' '); write('*')), printstate(L).
next([1|S], [0|S]).
next([1,1|S], [0,0|S]).
next([0|S], [0|T]) :- next(S,T).
next([1|S], [1|T]) :- next(S,T).
printnextstates(S,T) :- next(S,T), printstate(T), fail.
下一位是我被困住的位!所以目标是如果第一个移动的玩家可以强制获胜,则将状态的值定义为1,否则为0。我要编写一个谓词值(S,X),它将通过游戏树中的深度优先搜索来计算任何游戏状态S的值X.如果可能的话,我应该使用断言来避免搜索不止一次探索任何位置。
我不知道该怎么做!
到目前为止,这是我能想到的:
value(S,X) :- S = 1, ([S,T] = 1); 0.
但我确信这不是那么简单,但我不知道如何开始这个问题!我已经研究过深度优先搜索,但我真的不明白它写这个...有没有人知道如何开始这个问题呢?
非常感谢任何帮助!
答案 0 :(得分:0)
由于玩家可以在任何位置自由选择元素,因此问题的适当数据表示会产生显着的简化:假设我们保留了可用瓶子的列表。然后你可以只声明逻辑:
win(P) :-
move(P, P1),
\+ win(P1).
win(P) :- move(P, []).
move([_|R], R).
move([_,_|R], R).
这是一个愚蠢的测试,直到任意长度,没有注意到一个简单的递推公式给出了结果
?- setof(N, L^(between(1,20,N),length(L,N),win(L)), Wins).
Wins = [1, 2, 4, 5, 7, 8, 10, 11, 13|...].