1

我的目标是开发一个简单的程序来运行一个名为“Kayles”的游戏,它类似于Skittles。你有一排瓶子,两名玩家轮流击倒它们,击倒最后一瓶的玩家获胜。您只能将 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。我要编写一个谓词 value(S,X),它将通过游戏树的深度优先搜索来计算任何游戏状态 S 的值 X。如果可能的话,我应该使用 assert 来避免搜索多次探索任何位置。

我不知道该怎么做!

到目前为止,这是我能想到的:

value(S,X) :- S = 1, ([S,T] = 1); 0.

但我敢肯定这不是那么简单,但我不知道如何开始这个问题!我已经研究过深度优先搜索,但我对它的理解还不够,无法写下这篇文章……有人知道如何开始这个问题吗?

任何帮助深表感谢!

4

1 回答 1

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|...].
于 2013-03-07T17:56:25.067 回答