Prolog 中的扑克牌

发布于 2024-12-20 21:50:08 字数 183 浏览 0 评论 0 原文

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

这适用于 fourofakind(["A","J",10,"Q","A","A","A"])

但不适用于所有情况;这里的逻辑有什么指导吗?

谢谢

I am trying to write a predicate to analyse common poker hands; for example given a list of "cards" identify if the player has 4 of a kind; 3 of a kind; pair etc:
My idea was to check for similar rank and remove if not:

this works for fourofakind(["A","J",10,"Q","A","A","A"])

but not all scenarios; any guidance on the logic here?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧情勿念 2024-12-27 21:50:08

问题是你只检查手中的第一张牌是否在该组中出现了四次。您需要对所有卡执行此操作。

我会引入一个辅助谓词来计算您已经看到的牌的数量,并让主要谓词迭代手上的牌,直到找到一组四张牌:

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] >。这样眼睛就更容易了!

The problem is that you only check whether the first card in the hand appears four times in the set. You will need to do that for all cards.

I would introduce an auxiliary predicate that counts the number of cards you have seen, and let the main predicate iterate over the cards in the hand until you've found a set of four:

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

If it wasn't for short lists you could improve it by, e.g., remembering what cards you already checked or removing them. It also would be much easier if the list was sorted to begin with.

BTW, you can simplify the nested list in your original first clause as [H,H,H,H], and in the second clause as [H1,H2|T]. It's easier on the eyes!

时光倒影 2024-12-27 21:50:08

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

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

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

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

Consider to put to good use the builtins: when you sort a list all elements get grouped, then check for a sequence become easy:

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

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

The predicate has 2 forms, the latter also provides the card code. Please use the msort call: using sort we lose duplicates...

苦笑流年记忆 2024-12-27 21:50:08

正如 chac 指出的那样,为了再次进行我们在 这篇文章 中进行的辩论,您可以成功使用追加一旦排序就很容易解析你的列表。如果没有排序,你可以写:

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

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

或者,使用 @false他在另一个线程(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 的简单定义。我让您通过查看 two_of_a_kind/1pair/2 的工作原理来完成添加 four_of_a_kind/1 的任务!使用 cut 来删除未使用的选择点也很有趣。

As chac pointed out and to have again the debate we had in this post, you can use append to successfully parse your list once sorted quite easily. Without sorting, you could write :

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

This basically tells prolog : I want my hand to have 4 times the sublist [X] with anything in-between.

Or, to use what @false describes as a very graphically appealing solution in his reply on the other thread (DCGs) :

four --> ..., [X], ..., [X], ..., [X], ..., [X], ... .

... --> [] | [_], ... .

?- Xs = "bacada", phrase(four, Xs).

You could too avoid using too many built-ins by doing the work with basic recursion :

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).

Note that here one/2 is equivalent to the naive definition of member/2. I let you the task of adding four_of_a_kind/1 by looking at how three_of_a_kind/1 and pair/2 work ! Use of cut would be interesting too to remove unused choice points.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文