Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Алгоритм подсчета покерной руки

Ответить
Настройки темы
Алгоритм подсчета покерной руки

(*.*)


Сообщения: 36564
Благодарности: 6696


Конфигурация

Профиль | Сайт | Отправить PM | Цитировать


Изменения
Автор: Vadikan
Дата: 19-04-2005
Вложения
Тип файла: txt project.txt
(8.0 Kb, 23 просмотров)
Тип файла: txt five_integers.txt
(1.2 Kb, 42 просмотров)
Тип файла: txt calc_hand.txt
(2.6 Kb, 34 просмотров)
Доброго времени суток!

Вот добрался я и до этого форума Сразу скажу, что программист я никакой, и весь мой опыт программирования сводится к нескольким заданиям в рамках курса VB.NET в универе. Курс предназначен для людей, не имеющих опыта программирования, и знакомит с элементарными понятиями. Поскольку курс преподается на англ. языке, я знаю только английскую терминологию. Предположу, что array - массив, a data structure - структура данных.

Финальный проект курса формулируется так. Надо сгенерировать колоду карт на 52 листа. Сначала нужно создать структуру данных, у которой два члена: face (номинал карты) и suit (масть). Затем нужно сформировать массив, который и будет наполнен 52 картами. Затем нужно сгенерировать 5 случайных уникальных номеров от 0 до 51 (или от 1 до 52) и на основе этих номеров сформировать покерную руку. Ну и самое главное - определить покерную комбиниацию, которая получится в рез-те. Покерные комбинации такие

Flush (все одной масти)
Четверка (четыре карды одного номинала)
Full house (3+2)
Тройка
Две пары
Пара
Ничего

Как видите, вариант упрощенный - straight (стрит) подсчитывать не нужно (курс-то для начинающих ;-) Ну и вывести надо 5 карт и название комбинации. Никаких картинок карточной колоды, все в текстовом виде.

Затрудненения у меня вызвали пять уникальных случайных кард и алгоритм подсчета покерной руки. С пятью уникальными картами я вроде разобрался относительно легко.

Прикрепленный файл

Если я что-то упустил, то буду признателен, если вы укажете на ошибки.

С подсчетом покерных комбинаций было сложнее. В конечном итоге, я его определил, но хотелось бы услышать и ваше мнение. Возможно, я что-то где-то упустил, или можно все сильно упростить.

Основная идея: в руке не может быть более двух различных совпадающих номиналов карт. Т.е. если есть два туза и два короля, то пятой карте пары уже точно не будет. Значит надо подсчитать сколько раз совпали два различных номинала.

Прикрепленный файл

Ну а дальше уже детали. По порядку проверяем следующие условия:
  1. Если все карты одной масти, то flush (масти берутся из массива на основе 5 уникальных чисел, сгенерированных ранее)
  2. Если первый счетчик равен 4, то у нас четверка.
  3. Если счетчики 3+2 или 2+3, то у нас full house.
  4. Если первый счетчик равен 3, то тройка (причем, второй счетчик может быть равен 3 только в случае 2+3).
  5. Если счетчики 2+2, то две пары.
  6. Если первый счетчик равен 2, то пара (причем второй счетчик может быть равен 2 только в случае 3+2 или 2+2)
  7. Ну а во всех остальных случаях нету даже пары.

Вот так я себе это представил, и вроде даже работает. Буду признателен, если вы проверите алгоритм на наличие ошибок или предложите более оптимальный вариант. Может где-то есть лишние шаги, которые можно убрать, упростив код.

Спасибо за внимание.

P.S. Полный код проекта прикреплен.

-------
Канал Windows 11, etc | Чат @winsiders


Отправлено: 11:05, 18-04-2005

 

(*.*)


Сообщения: 36564
Благодарности: 6696

Профиль | Сайт | Отправить 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й элемент массива - десятка. Просто сортируем массив и проверяем совпадение номиналов.

Единственное, что три раза один и тот же код сортировки и сравнения номиналов вставлять не хочется, надо как-то это иначе оформить. Но идея такая.

-------
Канал Windows 11, etc | Чат @winsiders


Отправлено: 04:21, 21-04-2005 | #11



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить 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


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Т.е. вариант в п. 2а. подходит без учёта п 1. - заполняем массив номиналов, прогоняем 2а, сортируем, дальше проверяем остальные комбинации.

Либо заполняем массив номиналов, сортируем, проверяем остальные комбинации, затем, если ничего нет, прогоняем 2б.

Отправлено: 09:53, 21-04-2005 | #13


(*.*)


Сообщения: 36564
Благодарности: 6696

Профиль | Сайт | Отправить PM | Цитировать


hasherfrog
Цитата:
Надо делать проверку до сортировки. И тут же - надо делать проверку после сортировки :]
Вот-вот
По пункту 2а. Да вроде я таки делаю.
Цитата:
(и, кстати, == 1)
ну я же сказал, что ищу первый элемент, который равен единице, с ним же и остальные сравниваю.
По пункту 2б. Еще один промежуточный массив не очень хочется делать. Это уже третий получается...
Цитата:
Туз-король-дама-валет-десять - это стрит. А вот считается ли туз-двойка-тройка-4-5 за стрит???
Я вроде учел оба варианта Для этого i=0 выделено в отдельный пункт.

-------
Канал Windows 11, etc | Чат @winsiders


Отправлено: 09:57, 21-04-2005 | #14


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Vadikan
Спешил я, невнимательно прочёл :] У тебя же всё и расписано по полочкам, LOL.
Меня сбило с толку IndexOf, я сразу полез делать своё самостийное решение :]
Таки да, всё правильно, так и делай.

Отправлено: 15:28, 21-04-2005 | #15


(*.*)


Сообщения: 36564
Благодарности: 6696

Профиль | Сайт | Отправить PM | Цитировать


hasherfrog
Да, мне тоже показалось, что ты не столько мое решение проверял, сколько свое продвигал Я уже сделал: алгоритм сравнения повторющихся номиналов запихал в subroutine, и все работает как надо. Со straight-flush я не стал заморачиваться, и так уже сделано больше, чем требовалось в проекте. Бонусных очков все равно не предусмотрено...

-------
Канал Windows 11, etc | Чат @winsiders


Отправлено: 03:47, 22-04-2005 | #16


(*.*)


Сообщения: 36564
Благодарности: 6696

Профиль | Сайт | Отправить PM | Цитировать


Зашел сейчас на страничку курса почитать письма сокурсников. В день сдачи проекта сразу несколько человек писали письма с вопросами о том, как им оценить покерную руку. Учитывая то, что как сгенерировать колоду фактически об'яснялось в лекциях, то непонятно чем люди занимались раньше Но речь не об этом. Преподаватель ответил сразу всем студентам, а не только тем, кто задавал вопрос. Он об'яснил, что надо считать совпадения номиналов, и сказал, что обычно студенты пишут очень болшие блоки IF/ELSE (бедные преподы потом в них разбираются ;-), но поскольку для вычисления "Пары" понадобится проверка десяти условий, то проблему подсчета совпадений номиналов он бы решил так:
Код: Выделить весь код
For i = 0 to 4
 For j = 0 to 4
   If hand(i).face = hand(j).face AndAlso i <> j
     matches += 1
   End If
 Next j
Next i
hand(i).face - берется из структуры данных (колоды) созданной раннее. Весьма компактно, и мне такое в голову не пришло. Тем не менее решение с массивом позволяет также просчитать и straight. Но по условиям проекта straight считать не надо было...

-------
Канал Windows 11, etc | Чат @winsiders


Отправлено: 12:00, 02-05-2005 | #17


Старожил


Сообщения: 401
Благодарности: 10

Профиль | Отправить PM | Цитировать


Vadikan
имхо этот кусок кода определит только то, что на руке есть что-то "не меньше пары", а вот что именно... тут подумать надо
а с преподом согласен, циклы всегда лучше/универсальнее (вдруг кому-то в голову придет сделать 6-карточный покер )

-------
Успехов.


Отправлено: 10:15, 03-05-2005 | #18


(*.*)


Сообщения: 36564
Благодарности: 6696

Профиль | Сайт | Отправить PM | Цитировать


aESThete
Мда... я вот сейчас посмотрел внимательнее... Не удивительно, что мне такое в голову не пришло Как ни крути, но придется работать с двумя числами, представляющимии совпадения номиналов. Я-то изначально два счетчика делал (второй прикрепленный файл), хотя там наверное можно было упростить как-то.

-------
Канал Windows 11, etc | Чат @winsiders


Отправлено: 10:37, 03-05-2005 | #19


Старожил


Сообщения: 401
Благодарности: 10

Профиль | Отправить 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



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Алгоритм подсчета покерной руки

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
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




 
Переход