Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Алгоритмы > Нахождение лучшей комбинации карт |
Автор: azesmcar 21.5.2009, 14:01 | ||
Добрый день, есть 5 карт, нужно найти лучшую комбинацию которую можно составить из этих карт в соответствии с правилами игры в покер. Т.е. 10 J Q K A - Royal Flush 7 8 9 10 J - Straight Flush 4 4 4 4 - Four of a Kind 3 3 3 2 2 - Full House ... и так далее нужно написать функцию которая принимает массив из 5 карт и возвращает комбинацию. есть идеи, но мне не нравятся проверки будут какие-то запутанные, т.е. например проверка pair, 3 of a kind и 4 of a kind практически одно и тоже..но проверка на флэш - очень сильно отличается, если все делать в одной функции - будет запутанно..если разделить - будет медленно. пятой точкой чую что можно красивее и быстрее. Есть такая мысль, сгенерировать какие-то комбинации, хранить хэш, можно текстовый, можно числовой..не актуально. Короче из карт вычислять какое-то значение и проверять с заранее сгенерированными. Хочу сделать что-то вроде этого..
есть идеи как можно сгенерировать и этот хранить хэш? хранить все возможные комбинации разумеется нереально ![]() |
Автор: Akina 21.5.2009, 14:22 |
Формализуй карты и проверяй по шаблонам. |
Автор: azesmcar 21.5.2009, 14:25 |
ээээ...можно подробнее? |
Автор: azesmcar 21.5.2009, 20:14 |
задача решена следующим методом берем массив размером в 13 элементов, инициализируем нулями. пробегаемся по нашим картам и инкрементируем значение по индексу - соответствующему значению нашей карты т.е. (туз - 0 элемент, 2 - первый элемент, 3 - второй элемент...итд) одновременно в цикле устанавлиаем булевый флаг в true - если все карты одной масти и в false если соответственно нет. Потом остается пробежатся по полученному массиву и устанавливаем еще один булевый флаг в true если в массиве есть очередь из 5 карт или очередь из 4 карт начинающаяся с десятки с условием что в картах есть туз (т.е. первый элемент массива - установлен в 1). Дальше все просто. if (is_flash && is_sequence && m[0].is_ace) return royal_flush; else if (is_flash && is_sequence) return straight_flush; ...и так далее. это в принципе решение для будущего поколения. Но все же 1. хотелось бы услышать мнения 2. хотелось бы все таки описанным в самом начале методе (хэшированием) |
Автор: LOD77 22.5.2009, 17:18 |
Предлагаю следующий принцип представления данных Я не очень знаком с правилами покера. Предполагается что масти карт в нем равнозначны. Тогда каждую карту (ее номинал) кодируем в пятиричной системе счисления. То есть 2-ки будут единицами, 3-ки пятерками, 4-ки 25-ками 5- 125 6 - 625 7 - 3125 8 - 15625 9 - 78125 10 - 390625 J - 1953125 Q - 9765625 K - 48828125 A - 244140625 Все как раз укладывается в длинное целое (32 разряда) После этого каждую покерную комбинацию кодируем. То есть для 10 J Q K A - Royal Flush получим: 1*390625+1*1953125+1*9765625+1*48828125+1*244140625, а для 3 3 3 2 2 - Full House получим: 3*5+2*1 после этого исходную комбинацию карт тоже кодируем, а дальше (внимание!) выполняем над исходной комбинацией карт и очередной покерной комбинацией (можно по возрастанию до конца, но лучше по убыванию до первой встречной) операцию аналогичную "логическому И" (AND). И если результат совпал с покерной комбинацией, то это она и есть. Теперь поподробнее об операции "логическое И" Выполняется поразрядно без переноса. Принцип следующий: результатом соответствующего разряда является "пересечение" множеств элементов в операндах. То есть в нашем случае это классический MIN. То есть если в исходной комбинации 3 двойки, а в покерной только 1, то результатом будет одна двойка. Ну например: Разряды: A Q J 10 9 8 7 6 5 4 3 2 Покерная комбинация: 0 0 1 1 1 1 1 0 0 0 0 0 Исходная комбинация: 1 0 2 0 1 0 1 0 0 0 0 0 Результат: 0 0 1 0 1 0 1 0 0 0 0 0 Как мы видим, результат не совпал с покерной комбинацией, следовательно ее там нет. Ну вот где-то так видится... |
Автор: Soah 23.5.2009, 19:22 |
azesmcar, если изменить немного твой вариант, то можно сделать с комбинациями. Разделяем хэш на четыре части: 1. сколько раз повторяется каждая карта - 5 символов 2. очередь из 5 карт - 1 символ(нет-0, да-1) 3. все 5 карт одинаковой масти - 1 символ(нет-0, да-1) 4. очередь из 5 карт, все 5 карт одинаковой масти, есть туз и 10 - 1 символ(нет-0, да-1) Получаем такую таблицу: 11111:1:1:1 - royal flush 11111:1:1:0 - straight flush 41000:0:0:0 - four of a kind 14000:0:0:0 - four of a kind 32000:0:0:0 - full house 23000:0:0:0 - full house 11111:0:1:0 - flush 11111:1:0:0 - straight 11300:0:0:0 - three of a kind 13100:0:0:0 - three of a kind 31100:0:0:0 - three of a kind 12200:0:0:0 - two pairs 21200:0:0:0 - two pairs 22100:0:0:0 - two pairs 11120:0:0:0 - one pairs 11210:0:0:0 - one pairs 12110:0:0:0 - one pairs 21110:0:0:0 - one pairs Получаем комбинацию: 1. Сортируем карты 2. берем массив размером в 13 элементов, инициализируем нулями 3. пробегаемся по нашим картам и инкрементируем значение по индексу - соответствующему значению нашей карты 4. берем строку размером в 5 элементов, инициализируем нулями("00000") 5. пробегаемся по массиву, и если там не нуль, то добавляем число в строку - получаем первую часть хэша 6. проверяем есть ли очередь из 5 карт - получаем вторую часть хэша 7. проверяем если одинаковая масти - получаем третью часть хэша 8. проверяем если royal flush(очередь из 5 карт, все 5 карт одинаковой масти, есть туз и 10) 9. соединяем все части |
Автор: azesmcar 25.5.2009, 14:35 |
Soah![]() ![]() если вдуматься - все что написано делать надо - хочешь не хочешь. т.е. это минимум, дальше либо искать, либо просто возвращать через условия. Условий не так много, в принципе смысла хешировать я так думаю нет, быстрее все равно не выйдет ![]() Спасибо. ![]() |