【问题标题】:Poker Hand in PrologProlog中的扑克牌
【发布时间】:2013-01-08 02:12:06
【问题描述】:

我正在尝试编写一个谓词来分析常见的扑克牌;例如,给定一个“卡片”列表,确定玩家是否有 4 个同类; 3种;对等: 我的想法是检查相似的排名,如果不是,则删除:

这适用于四种类型(["A","J",10,"Q","A","A","A"])

但不是所有场景;这里的逻辑有什么指导吗?

谢谢

【问题讨论】:

  • 这些括号太近了,在我的显示器上看起来是绿色的。我以为我们已经用 lisp 解决了这个问题 :)
  • 另请参阅此答案stackoverflow.com/a/4674095/12547

标签: prolog dcg


【解决方案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]。眼睛更舒服!

【讨论】:

  • 谢谢,这很有帮助。我的目标是让我的递归思维变得更强大,而您的解决方案正好帮助了我!
【解决方案2】:

考虑充分利用内置函数:当您对列表进行排序时,所有元素都会被分组,然后检查序列变得容易:

fourofakind(Hand) :-  % not intersted to what card is
 fourofakind(Hand, _).

fourofakind(Hand, C) :-
 msort(Hand, Sorted),
 append([_, [C,C,C,C], _], Sorted).

谓词有2种形式,后者还提供卡号。请使用 msort 调用:使用排序我们会丢失重复项...

【讨论】:

  • 谢谢,我知道我需要更加熟悉内置谓词。
【解决方案3】:

正如 chac 所指出的并再次与我们在this post 中进行的辩论一样,您可以使用 append 成功解析您的列表,一旦排序很容易。没有排序,你可以写:

fourofakind(Hand, X) :- append([_, [X], _, [X], _, [X], _, [X], _], Hand).

这基本上告诉序言:我希望我的手有 4 倍的子列表 [X],中间有任何东西。

或者,使用 @false 在另一个线程 (DCG) 上的 his reply 中描述为非常具有图形吸引力的解决方案:

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/1pair/2 的工作原理,我让您完成添加four_of_a_kind/1 的任务!使用 cut 来删除未使用的选择点也很有趣。

【讨论】:

  • append/2 并非在所有 Prolog 系统中都可用,并且 OP 没有指定他是否使用 SWI。
  • true,如果append/2 不可用,msort 解决方案更具可读性,所以我想我会选择(如果想使用 append ofc !)。
  • 谢谢,我喜欢这种方法可以满足我的一切需求。我肯定需要更熟悉内置的
猜你喜欢
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多