4

Я пытаюсь изучить Prolog. Это мои первые шаги с этим языком. В качестве упражнения я хочу написать программу, которая может распознать некоторые покерные руки (прямой флеш, четыре вида, полный дом и т. Д.).Представления карт в 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. 

Это даст ми возможность проверить, если ранг А больше, чем, например, J.

Но я не уверен, как представлять одну карту. Это представление должно содержать ранг карты, а также костюм. Существует также проблема с Ace, потому что Ace имеет ранг 14, но он может быть также 1 в прямой.

Так что мой вопрос заключается в том, как представляет карты, если я хочу, чтобы правила, как:

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

или

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

Я уверен, что это вроде простой вопрос, если вы знаете язык , но не так-то просто «переключить» мышление с таких языков, как C или python. :-)

ответ

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. 
+0

Спасибо за ответ! Опять же, мне нужно проанализировать это. :) – Adam

2

Используйте список пар, card(rank, suite) за руку. Определите предикаты для подсчета количества повторений каждого ранга в руке, сортировки обратно пропорционально по счету, а у вас есть покер в [4,1], полный в [3,2], трио в [3|_] и т. Д. Немного больше работы по сортировке и подсчету покажут флеши и натуралы. Вместо числовых значений используйте отношения higher(a,b) и equal(a,b), которые применяются как к рангу, так и к рукам (и к иски, если это правило применяется).

Потому что в руке всего пять карт, вы можете уйти с перечислением возможностей вместо сортировки ... по вашему выбору.

Примечание: Я удалил образцы кода, потому что они содержали слишком много синтаксических и логических ошибок.

+0

Благодарим за ответ. Мне нужно время подумать об этом. Я вернусь с вопросами. ;) – Adam

+0

-1. Этот код довольно глючный (строчные «r» и «s», 1 + count), вы на самом деле его запускали ?! – Kaarel

+0

@Kaarel Прошло некоторое время с тех пор, как я последний раз программировал в Prolog. Спасибо, что указали на ошибки. Я сделаю попытку исправить код. – Apalala

10

Вы можете использовать юникод и 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(♠(_),♠(_),♠(_),♠(_),♠(_)). 
+1

☝ ... ✓ (это здорово!) – sharky

+0

Спасибо, приятно знать. Но я думаю, что останусь с традиционными письмами. – Adam

+0

Это действительно круто, и очень пролог! – Apalala