|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Алгоритм подсчета покерной руки |
|
Алгоритм подсчета покерной руки
|
(*.*) Сообщения: 36564 |
Доброго времени суток!
Вот добрался я и до этого форума ![]() Финальный проект курса формулируется так. Надо сгенерировать колоду карт на 52 листа. Сначала нужно создать структуру данных, у которой два члена: face (номинал карты) и suit (масть). Затем нужно сформировать массив, который и будет наполнен 52 картами. Затем нужно сгенерировать 5 случайных уникальных номеров от 0 до 51 (или от 1 до 52) и на основе этих номеров сформировать покерную руку. Ну и самое главное - определить покерную комбиниацию, которая получится в рез-те. Покерные комбинации такие Flush (все одной масти) Четверка (четыре карды одного номинала) Full house (3+2) Тройка Две пары Пара Ничего Как видите, вариант упрощенный - straight (стрит) подсчитывать не нужно (курс-то для начинающих ;-) Ну и вывести надо 5 карт и название комбинации. Никаких картинок карточной колоды, все в текстовом виде. Затрудненения у меня вызвали пять уникальных случайных кард и алгоритм подсчета покерной руки. С пятью уникальными картами я вроде разобрался относительно легко. Прикрепленный файл Если я что-то упустил, то буду признателен, если вы укажете на ошибки. С подсчетом покерных комбинаций было сложнее. В конечном итоге, я его определил, но хотелось бы услышать и ваше мнение. Возможно, я что-то где-то упустил, или можно все сильно упростить. Основная идея: в руке не может быть более двух различных совпадающих номиналов карт. Т.е. если есть два туза и два короля, то пятой карте пары уже точно не будет. Значит надо подсчитать сколько раз совпали два различных номинала. Прикрепленный файл Ну а дальше уже детали. По порядку проверяем следующие условия:
Вот так я себе это представил, и вроде даже работает. Буду признателен, если вы проверите алгоритм на наличие ошибок или предложите более оптимальный вариант. Может где-то есть лишние шаги, которые можно убрать, упростив код. Спасибо за внимание. P.S. Полный код проекта прикреплен. |
|
------- Отправлено: 11:05, 18-04-2005 |
(*.*) Сообщения: 36564
|
Профиль | Сайт | Отправить PM | Цитировать hasherfrog
В общем, преподаватель сказал, что все очень хорошо и добавлять ничего не надо. Конечно, оговорился, что при финальной проверке может что-то и всплывет ![]() Ладно, я тут подумал как подсчитывать straight на основе массива, который содержит счетчики номиналов. Пусть он будет массив S. Не сортируя его я могу задать поиск первого элемента, содержащего единицу i=Array.IndexOf(S,1) a затем рассматривать следующие варианты i<0 элементов содержащих единицу нет, значит неповторяющихся номиналов нет. Это возможно только в случае 3+2 - значит Full House i=0 Самый первый элемент массива имеет значение 1. Значит у нас в руке один Ace. Проверяем на наличие straight Если А2345, что выражается как S(0)=S(1)=S(2)=S(3)=S(4) или 10JQKA, что выражается как S(0)=S(9)=S(10)=S(11)=S(12), то у нас straght, в противном случае сортируем массив и проверяем совпадение номиналов (на full house уже проверять не надо). i<=8 Проверяем на наличие straight снова таким образом. Если S(i)=S(i+1)=S(i+2)=S(i+3)=S(i+4), то у нас straight. В противном случае сортируем массив и проверяем совпадение номиналов. i>8 В этом случае straight уже быть не может, т.к. 9й элемент массива - десятка. Просто сортируем массив и проверяем совпадение номиналов. Единственное, что три раза один и тот же код сортировки и сравнения номиналов вставлять не хочется, надо как-то это иначе оформить. Но идея такая. |
------- Отправлено: 04:21, 21-04-2005 | #11 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Старый параноик Сообщения: 2423
|
Профиль | Отправить PM | Цитировать Vadikan
Эммм. Я бы исходил из того, что стрит (правильно я интерпретирую straight?) - это пять _разных(1) по номиналу, но _последовательных(2) карт. 1. Т.о. предварительную проверку на стрит можно делать уже после определения всех остальных комбинаций. Стрит получится, только если нет даже пары. Ведь все карты должны быть _разные по номиналу. Единственное, что нельзя учитывать - это флеш. Поэтому проверку на флеш стоит делать уже _после проверки на стрит (и до проверки на стрит-флеш aka флеш-рояль, емнип). 2. "Последовательность" можно определить двумя способами. 2а. Сданные карты должны дать в массиве счётчиков единицы в пяти последовательных ячейках (до сортировки по номиналу - то есть проверку на стрит надо делать самой-самой первой). Проверка такая: для i=0 to (12 - 5) если S[i]==S[i+1]==S[i+2]==S[i+3]==S[i+4] (и, кстати, == 1), то стрит. 2б. Можно опираться на номинал. Взять промежуточный массив из 5 элементов, заполнить его номиналами карт (K/4). Отсортировать по увеличению. И проверить, если будет T[0]==T[1]+1==T[2]+2==T[3]+3==T[4]+4, то стрит. Единственное, что я не помню... Туз-король-дама-валет-десять - это стрит. А вот считается ли туз-двойка-тройка-4-5 за стрит??? Ентих покеров, афаик, штук десять разновидностей. В какой ваш перпод играет??? P.S. Ну а стрит-флеш, это когда есть стрит и есть флеш :] OOOPS. Заметил несуразность. Надо делать проверку до сортировки. И тут же - надо делать проверку после сортировки :] Выходит так, что придётся делать не сильно оптимизированную программу. Либо немного запутанную по логике. |
Отправлено: 09:45, 21-04-2005 | #12 |
Старый параноик Сообщения: 2423
|
Профиль | Отправить PM | Цитировать Т.е. вариант в п. 2а. подходит без учёта п 1. - заполняем массив номиналов, прогоняем 2а, сортируем, дальше проверяем остальные комбинации.
Либо заполняем массив номиналов, сортируем, проверяем остальные комбинации, затем, если ничего нет, прогоняем 2б. |
Отправлено: 09:53, 21-04-2005 | #13 |
(*.*) Сообщения: 36564
|
Профиль | Сайт | Отправить PM | Цитировать hasherfrog
Цитата:
![]() По пункту 2а. Да вроде я таки делаю. Цитата:
По пункту 2б. Еще один промежуточный массив не очень хочется делать. Это уже третий получается... Цитата:
![]() |
|||
------- Отправлено: 09:57, 21-04-2005 | #14 |
Старый параноик Сообщения: 2423
|
Профиль | Отправить PM | Цитировать Vadikan
Спешил я, невнимательно прочёл :] У тебя же всё и расписано по полочкам, LOL. Меня сбило с толку IndexOf, я сразу полез делать своё самостийное решение :] Таки да, всё правильно, так и делай. |
Отправлено: 15:28, 21-04-2005 | #15 |
(*.*) Сообщения: 36564
|
Профиль | Сайт | Отправить PM | Цитировать hasherfrog
Да, мне тоже показалось, что ты не столько мое решение проверял, сколько свое продвигал ![]() |
------- Отправлено: 03:47, 22-04-2005 | #16 |
(*.*) Сообщения: 36564
|
Профиль | Сайт | Отправить PM | Цитировать Зашел сейчас на страничку курса почитать письма сокурсников. В день сдачи проекта сразу несколько человек писали письма с вопросами о том, как им оценить покерную руку. Учитывая то, что как сгенерировать колоду фактически об'яснялось в лекциях, то непонятно чем люди занимались раньше
![]() hand(i).face - берется из структуры данных (колоды) созданной раннее. Весьма компактно, и мне такое в голову не пришло. Тем не менее решение с массивом позволяет также просчитать и straight. Но по условиям проекта straight считать не надо было... |
------- Отправлено: 12:00, 02-05-2005 | #17 |
Старожил Сообщения: 401
|
Профиль | Отправить PM | Цитировать Vadikan
имхо этот кусок кода определит только то, что на руке есть что-то "не меньше пары", а вот что именно... тут подумать надо а с преподом согласен, циклы всегда лучше/универсальнее (вдруг кому-то в голову придет сделать 6-карточный покер ![]() |
------- Отправлено: 10:15, 03-05-2005 | #18 |
(*.*) Сообщения: 36564
|
Профиль | Сайт | Отправить PM | Цитировать aESThete
Мда... я вот сейчас посмотрел внимательнее... Не удивительно, что мне такое в голову не пришло ![]() |
------- Отправлено: 10:37, 03-05-2005 | #19 |
Старожил Сообщения: 401
|
Профиль | Отправить PM | Цитировать Vadikan
счетчиков д.б. не два, а массив счетчиков (можно плавающий, можно по кол-ву номиналов...) тогда достигаем нужной гибкости: For i = 0 to 4 For j = 0 to 4 If hand(i).face = hand(j).face And i <> j then matches(face) += 1 End If Next j Next i соответственно затем: For i = 0 to maxfaces if matches(i) = 2 pairs += 1 elseif matches(i) = 3 threes += 1 elseif matches(i) = 4 kare += 1 endif Next i это и красиво, и будет работать при любом кол-ве карт в руке, т.е. покажет все пары, тройки и каре... ![]() |
------- Отправлено: 12:18, 03-05-2005 | #20 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
FreeBSD - Кривые руки | xolod. | Общий по FreeBSD | 2 | 14-05-2009 12:02 | |
[решено] мои руки\цп\мать кто виноват и что делать) | SoA | Непонятные проблемы с Железом | 12 | 14-08-2008 17:34 | |
DNS (опустились руки) 53 порт локального сервера | Virtus1k | Microsoft Windows NT/2000/2003 | 3 | 03-01-2008 11:16 | |
Программа подсчета трафика. | NewWind | Общий по Linux | 1 | 04-06-2007 16:37 | |
Кривые руки при разгоне - и комп перестал грузится... | Shaytan | Непонятные проблемы с Железом | 13 | 06-03-2005 21:56 |
|