【问题标题】:Cards representation in PrologProlog 中的卡片表示
【发布时间】:2011-06-08 01:38:15
【问题描述】:

我正在尝试学习 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.

这使 mi 有可能检查等级 A 是否大于例如 J。

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

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

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

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

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

【问题讨论】:

    标签: prolog poker


    【解决方案1】:

    您可以使用 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(♠(_),♠(_),♠(_),♠(_),♠(_)).
    

    【讨论】:

    • 谢谢,很高兴知道。但我想我会继续使用传统字母。
    【解决方案2】:

    您可以使用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.
    

    【讨论】:

    • 感谢您的回答!再次,我需要分析它。 :)
    【解决方案3】:

    使用对子列表,card(rank, suite) 表示手牌。定义谓词来计算每个等级在一手牌中重复的次数,按计数反向排序,你在[4,1] 有扑克,在[3,2] 有扑克,在[3|_] 有三重奏等。更多的排序工作数数会显示同花顺和顺子。使用关系higher(a,b)equal(a,b) 而不是数值,它们适用于等级和手牌(如果适用该规则,也适用于花色)。

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

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

    【讨论】:

    • 感谢您的回答。我需要一些时间来考虑一下。我会带着问题回来。 ;)
    • -1。这段代码有很多错误(小写的'r'和's'; 1 + count),你真的运行了吗?!
    • @Kaarel 自从我上次在 Prolog 中编程已经有一段时间了。感谢您指出错误。我会尝试修复代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多