Prolog 中的卡片表示

发布于 2024-10-11 20:34:58 字数 1049 浏览 11 评论 0原文

我正在努力学习Prolog。这是我使用这种语言的第一步。作为练习,我想编写可以识别一些扑克牌的程序(同花顺,四张,葫芦等)。

我正在寻找 Prolog 中良好的卡片表示形式。我需要能够检查一张牌是否比另一张牌大,牌是否适合等等。

我已经从代码开始:

rank(2).
rank(3).
rank(4).
rank(5).
rank(6).
rank(7).
rank(8).
rank(9).
rank(t).
rank(j).
rank(q).
rank(k).
rank(a).

value(2, 2).
value(3, 3).
value(4, 4).
value(5, 5).
value(6, 6).
value(7, 7).
value(8, 8).
value(9, 9).
value(t, 10).
value(j, 11).
value(q, 12).
value(k, 13).
value(a, 14).
%value(a, 1).

suite(d).
suite(h).
suite(c).
suite(s).

rank_bigger(X, Y) :-
               value(X, A),
               value(Y, B),
               A > B.

这使我有可能检查 A 级是否大于 J 级。

但我不确定如何表示单张卡。该表示应包含牌的等级和花色。 Ace 也存在一些问题,因为 Ace 的排名为 14,但也可以是顺子 1。

所以我的问题是,如果我想制定如下规则,如何表示卡片:

isStraight(C1, C2, C3, C4, C5) :- 
                                  [...]

或者

isStraightFlush(C1, C2, C3, C4, C5) :- 
                                       [...]

我确信如果您了解语言,这是一个简单的问题,但从 C 或 python 等语言“切换”思维并不那么容易。 :-)

I'm trying to learn Prolog. This are my first steps with this language. As exercise I want to write program which can recognize some poker hands (Straight flush, Four of a kind, Full house etc.).

I'm looking for good card representation in Prolog. I need to have possibility to check if one card is bigger than other, if cards are suited and so one.

I have started with code:

rank(2).
rank(3).
rank(4).
rank(5).
rank(6).
rank(7).
rank(8).
rank(9).
rank(t).
rank(j).
rank(q).
rank(k).
rank(a).

value(2, 2).
value(3, 3).
value(4, 4).
value(5, 5).
value(6, 6).
value(7, 7).
value(8, 8).
value(9, 9).
value(t, 10).
value(j, 11).
value(q, 12).
value(k, 13).
value(a, 14).
%value(a, 1).

suite(d).
suite(h).
suite(c).
suite(s).

rank_bigger(X, Y) :-
               value(X, A),
               value(Y, B),
               A > B.

That give mi possibility to check if rank A is bigger than for example J.

But I'm not sure how to represent single card. This representation should contains rank of card and also suit. There is also some issue with Ace because Ace have rank 14 but it can be also 1 in straight.

So my question is how to represents cards if I want to make rules like:

isStraight(C1, C2, C3, C4, C5) :- 
                                  [...]

or

isStraightFlush(C1, C2, C3, C4, C5) :- 
                                       [...]

I'm sure that this is kind of simple question if you know language, but it is not so easy to 'switch' thinking from languages like C or python. :-)

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

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

发布评论

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

评论(3

飘落散花 2024-10-18 20:34:58

你可以使用 unicode 和 SWI 来制作漂亮的程序......

:- op(200, xf, ♥).
:- op(200, xf, ♦).
:- op(200, xf, ♣).
:- op(200, xf, ♠).
:- op(200, xf, ♡).
:- op(200, xf, ♢).
:- op(200, xf, ♧).
:- op(200, xf, ♤).

main :- print([2♠,3♦,'K'♥,10♠,3♣]),
        isFlush(2♠,3♦,'K'♥,10♠,3♣).

isFlush(♥(_),♥(_),♥(_),♥(_),♥(_)).
isFlush(♦(_),♦(_),♦(_),♦(_),♦(_)).
isFlush(♣(_),♣(_),♣(_),♣(_),♣(_)).
isFlush(♠(_),♠(_),♠(_),♠(_),♠(_)).

You can use unicode and SWI to make pretty programs...

:- op(200, xf, ♥).
:- op(200, xf, ♦).
:- op(200, xf, ♣).
:- op(200, xf, ♠).
:- op(200, xf, ♡).
:- op(200, xf, ♢).
:- op(200, xf, ♧).
:- op(200, xf, ♤).

main :- print([2♠,3♦,'K'♥,10♠,3♣]),
        isFlush(2♠,3♦,'K'♥,10♠,3♣).

isFlush(♥(_),♥(_),♥(_),♥(_),♥(_)).
isFlush(♦(_),♦(_),♦(_),♦(_),♦(_)).
isFlush(♣(_),♣(_),♣(_),♣(_),♣(_)).
isFlush(♠(_),♠(_),♠(_),♠(_),♠(_)).
心不设防 2024-10-18 20:34:58

您可以使用 Rank-Suite 形式将卡片表示为术语。

为了检查牌是否来自同一花色,定义一个谓词:

same_suit(_-S, _-S).

您可以使用此谓词来检查您是否有同花:

?- Cards = [1-d, 2-d, 3-d, 4-d, 5-d], maplist(same_suit(_-S), Cards).
Cards = [1-d, 2-d, 3-d, 4-d, 5-d],
S = d.

为了检测您是否有一对、两对、三张同花、葫芦,或四种,您只需计算手牌中的数量,然后将结果映射到手牌的名称。

% Count the number of pairs in the given list of cards.
count_pairs([], 0).

count_pairs([R-_ | Cs], Pairs) :-
    count_rank(R, Cs, RankCount),
    count_pairs(Cs, Pairs0),
    Pairs is RankCount + Pairs0.


% Count the number of cards with the given rank
count_rank(R, Cs, RankCount) :-
    count_rank(R, Cs, 0, RankCount).


count_rank(_, [], RankCount, RankCount) :- !.

count_rank(R, [R-_ | Cs], RankCount0, RankCount) :-
    !,
    RankCount1 is RankCount0 + 1,
    count_rank(R, Cs, RankCount1, RankCount).

count_rank(R, [_ | Cs], RankCount0, RankCount) :-
    count_rank(R, Cs, RankCount0, RankCount).


% Map the number of pairs to the name of the hand
pairs_hand(1, one_pair).
pairs_hand(2, two_pair).
pairs_hand(3, three_of_a_kind).
pairs_hand(4, full_house).
%pairs_hand(5, 'NOT POSSIBLE').
pairs_hand(6, four_of_a_kind).

用法示例:

?- count_pairs([q-c, q-d, q-s, j-s, q-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 6,
Hand = four_of_a_kind.

?- count_pairs([j-c, q-d, q-s, j-s, q-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 4,
Hand = full_house.

?- count_pairs([j-c, q-d, q-s, j-s, 7-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 2,
Hand = two_pair.

You could represent cards as terms with the form Rank-Suite.

In order to check if the cards come from the same suite define a predicate:

same_suit(_-S, _-S).

You can use this predicate to check if you have a flush:

?- Cards = [1-d, 2-d, 3-d, 4-d, 5-d], maplist(same_suit(_-S), Cards).
Cards = [1-d, 2-d, 3-d, 4-d, 5-d],
S = d.

In order to detect if you have a pair, two pairs, three of a kind, full house, or four of a kind you can just count the number of pairs in the hand and then map the result to the name of the hand.

% Count the number of pairs in the given list of cards.
count_pairs([], 0).

count_pairs([R-_ | Cs], Pairs) :-
    count_rank(R, Cs, RankCount),
    count_pairs(Cs, Pairs0),
    Pairs is RankCount + Pairs0.


% Count the number of cards with the given rank
count_rank(R, Cs, RankCount) :-
    count_rank(R, Cs, 0, RankCount).


count_rank(_, [], RankCount, RankCount) :- !.

count_rank(R, [R-_ | Cs], RankCount0, RankCount) :-
    !,
    RankCount1 is RankCount0 + 1,
    count_rank(R, Cs, RankCount1, RankCount).

count_rank(R, [_ | Cs], RankCount0, RankCount) :-
    count_rank(R, Cs, RankCount0, RankCount).


% Map the number of pairs to the name of the hand
pairs_hand(1, one_pair).
pairs_hand(2, two_pair).
pairs_hand(3, three_of_a_kind).
pairs_hand(4, full_house).
%pairs_hand(5, 'NOT POSSIBLE').
pairs_hand(6, four_of_a_kind).

Usage examples:

?- count_pairs([q-c, q-d, q-s, j-s, q-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 6,
Hand = four_of_a_kind.

?- count_pairs([j-c, q-d, q-s, j-s, q-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 4,
Hand = full_house.

?- count_pairs([j-c, q-d, q-s, j-s, 7-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 2,
Hand = two_pair.
云朵有点甜 2024-10-18 20:34:58

使用成对列表,card(rank, suite) 作为手牌。定义谓词来计算每手牌中每个排名重复的次数,按计数反向排序,并且您在 [4,1] 中有扑克,在 [3,2]< /code>、[3|_] 中的三重奏等。稍微多做一些排序和计数工作就会显示同花和顺子。使用关系 higher(a,b)equal(a,b) 代替数值,它们适用于等级和手牌(以及花色,如果该规则适用)。

因为手中只有五张牌,所以您可以枚举可能性而不是排序......您的选择。

注意:我删除了代码示例,因为它们包含太多语法和逻辑错误。

Use a list of pairs, card(rank, suite) for the hand. Define predicates to count the number of times each rank is repeated in a hand, sort inversely by count, and you have poker in [4,1], full in [3,2], trio in [3|_], etc. A little more work with sorting and counting will reveal flushes and straights. Instead of numerical values, use relationships higher(a,b) and equal(a,b) that apply to both ranks and to hands (and to suits, if that rule applies).

Because there are only five cards in a hand, you can get away with enumerating the possibilities instead of sorting... your choice.

Note: I removed the code samples because they contained too many syntax and logic errors.

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