Это продолжение моего предыдущего вопроса о решении, готова ли рука .
Знание правил маджонга было бы превосходным, но для понимания этого вопроса также достаточно знаний о покере или роме.
В Маджонг 14 плиток (плитки как
карты в покер) расставлены по 4 сетам
и пара. Стрит ("123") всегда
использует ровно 3 плитки, не больше и не
Меньше. Набор того же вида («111»)
тоже состоит ровно из 3 плиток. это
приводит к сумме 3 * 4 + 2 = 14
плитка.
Существуют различные исключения, такие как Кан
или тринадцать сирот, которые не являются
здесь актуально. Цвета и диапазоны значений
(1-9) также не важны для
Алгоритм.
Рука состоит из 13 фишек, каждый раз, когда наступает наш ход, мы выбираем новую фишку и вынуждены сбрасывать любую фишку, поэтому мы остаемся на 13 фишках - кроме случаев, когда мы можем выиграть, используя вновь выбранную фишку.
Рука, которая может быть организована в 4 набора, и пара «готова». Рука, для которой требуется обмен только 1 плитки, называется «тенпай» или «1 с готового». Любая другая рука имеет число shanten, которое выражает, сколько плиток нужно обменять, чтобы быть в тенпай. Таким образом, рука с shanten числом 1 нуждается в 1 плитке, чтобы быть tenpai (и 2 плитки, чтобы быть готовыми, соответственно). Рука с числом shanten 5 нуждается в 5 тайлах, чтобы быть tenpai и так далее.
Я пытаюсь подсчитать число рук в руке. После нескольких часов поиска в Google и прочтения нескольких статей и статей на эту тему, эта проблема, похоже, остается нерешенной (за исключением подхода грубой силы). Самый близкий алгоритм, который я мог найти, основывался на случайности, то есть он не мог определить правильное число Шента в 100% случаев.
Правила
Я немного объясню действительные правила (упрощенно), а затем свою идею, как решить эту задачу. В маджонге есть 4 цвета, 3 нормальных, как в карточных играх (туз, сердце, ...), которые называются «человек», «булавка» и «су». Эти цвета варьируются от 1 до 9 каждый и могут использоваться для формирования прямых, а также групп одного и того же вида. Четвертый цвет называется «отличием» и может использоваться только для групп одного типа, но не для прямых. Семь почестей будут называться "E, S, W, N, R, G, B".
Давайте рассмотрим пример руки тенпая: 2p, 3p, 3p, 3p, 3p, 4p, 5m, 5m, 5m, W, W, W, E
. Далее мы выбираем E
. Это полная рука маджонга (готовая), состоящая из улицы с 2-4 булавками (помните, булавки можно использовать для стритов), тройки с 3 булавками, тройки с 5 игроками, тройки W и пары E.
Немного изменив нашу исходную руку на 2p, 2p, 3p, 3p, 3p, 4p, 5m, 5m, 5m, W, W, W, E
, мы получили 1-shanten, т. Е. Для получения тенпая требуется дополнительная плитка. В этом случае обмен 2p на 3p возвращает нас к тенпаю, поэтому, выиграв 3p и E, мы выигрываем.
1p, 1p, 5p, 5p, 9p, 9p, E, E, E, S, S, W, W
- это рука в 2 шанте. Есть 1 законченный триплет и 5 пар. В конце концов нам нужна одна пара, поэтому, как только мы выберем одну из 1p, 5p, 9p, S или W, нам нужно сбросить одну из других пар. Пример: мы выбираем 1 булавку и сбрасываем букву W. Рука теперь 1-shanten и выглядит следующим образом: 1p, 1p, 1p, 5p, 5p, 9p, 9p, E, E, E, S, S, W
. Затем мы ждем 5p, 9p или S. Предполагая, что мы выберем 5p и отбросим остаток W, мы получим следующее: 1p, 1p, 1p, 5p, 5p, 5p, 9p, 9p, E, E, E, S, S
. Эта рука в тенпай может быть завершена на 9 булавках или на S.
Чтобы не рисовать этот текст еще длиннее, вы можете прочитать больше примеров на википедии или использовать один из различных результатов поиска в Google. Все они немного более техничны, поэтому я надеюсь, что приведенного выше описания достаточно.
Алгоритм
Как уже говорилось, я хотел бы подсчитать число рук в руке. Моя идея состояла в том, чтобы разбить плитки на 4 группы в соответствии с их цветом. Далее, все тайлы сортируются в наборы в соответствующих группах, и в итоге мы получаем либо тройки, пары или отдельные тайлы в группе чести, либо, дополнительно, стриты в 3 нормальных группах. Завершенные наборы игнорируются. Пары подсчитываются, окончательное число уменьшается (нам нужна 1 пара в конце). К этому номеру добавляются отдельные плитки. Наконец, мы делим число на 2 (так как каждый раз, когда мы выбираем хорошую плитку, которая приближает нас к тенпаю, мы можем избавиться от другой нежелательной плитки).
Однако я не могу доказать, что этот алгоритм корректен, и у меня также возникают проблемы с включением прямых для сложных групп, которые содержат много плиток с близкого расстояния. Любая идея приветствуется. Я занимаюсь разработкой в .NET, но также приветствуется псевдокод или любой читаемый язык.