我想写一个谓词来分析普通扑克牌手;例如给出一张“卡片”列表来标识玩家是否有4种类型;一种3;对等: 我的想法是检查相似的等级,如果不是,则删除:扑克之手Prolog
这适用于fourofakind([A,J,10,Q,A, A“])
但不是所有情况;这里有关逻辑的任何指导?
感谢
我想写一个谓词来分析普通扑克牌手;例如给出一张“卡片”列表来标识玩家是否有4种类型;一种3;对等: 我的想法是检查相似的等级,如果不是,则删除:扑克之手Prolog
这适用于fourofakind([A,J,10,Q,A, A“])
但不是所有情况;这里有关逻辑的任何指导?
感谢
由于CHAC指出,并再次有我们this post有争论,你可以使用附加成功地解析您的列表排序一次很容易。如果没有排序,你可以写:
fourofakind(Hand, X) :- append([_, [X], _, [X], _, [X], _, [X], _], Hand).
这主要是告诉序言:我想我的手有子列表4倍[X]与任何在两者之间。
或者使用什么@false描述为his reply其他线程(DCG中)在一个非常图形化等吸引人的解决方案:
four --> ..., [X], ..., [X], ..., [X], ..., [X], ... .
... --> [] | [_], ... .
?- Xs = "bacada", phrase(four, Xs).
你可能也避免做的工作基本使用过多的内置插件递归:
three_of_a_kind(Item, [Item|Tail]) :- pair(Item, Tail).
three_of_a_kind(Item, [_Item|Tail]) :- three_of_a_kind(Item, Tail).
pair(Item, [Item|Tail]) :- one(Item, Tail).
pair(Item, [_NotItem|Tail]) :- pair(Item, Tail).
one(Item, [Item|_Tail]).
one(Item, [_NotItem|Tail]) :- one(Item, Tail).
注意的是,这里one/2
相当于member/2
天真的定义。我通过查看three_of_a_kind/1
和pair/2
的工作方式,让您加入four_of_a_kind/1
的任务!删除未使用的选择点也会很有趣。
的问题是,你只检查手中的第一张牌是否出现在集合四倍。您需要为所有卡片做到这一点。
我会介绍计数的,你所看到的卡的数量的辅助谓词,并让在手中的卡主谓迭代,直到你发现了一组四:
four([H|T]) :- four0(H,1,T), !. % find a set of four Hs
four([_|T]) :- four(T). % else continue with remaining set
four0(_,4,_) :- !. % found four cards: stop
four0(X,I,[X|T]) :- !,I1 is I+1,four0(X,I1,T). % found another card: inc counter
four0(X,I,[_|T]) :- four0(X,I,T). % else continue
如果并不是因为短名单可以改进它,例如,记住已经检查或删除了哪些卡。如果清单是从一开始就排序的,那么它也会容易得多。
顺便说一下,您可以简化原始第一个子句中的嵌套列表[H,H,H,H]
,并在第二个子句中将其简化为[H1,H2|T]
。在眼睛上更容易!
谢谢,这有助于很多。我的目标是在递归思想中变得更强大,您的解决方案可以帮助我! – Androider
考虑到善加利用内建的:当你排序列表中的所有元素,会进行分组,然后检查序列变得容易:
fourofakind(Hand) :- % not intersted to what card is
fourofakind(Hand, _).
fourofakind(Hand, C) :-
msort(Hand, Sorted),
append([_, [C,C,C,C], _], Sorted).
谓词有2种形式,后者还提供了卡码。请使用msort电话:使用排序,我们失去了重复...
谢谢,我看到我需要更熟悉内建的谓词。 – Androider
这些支架非常接近,它们在我的显示器上看起来很绿。我认为我们已经用lisp完成了这个工作:) –
另请参阅此答案http://stackoverflow.com/a/4674095/12547 – Kaarel