3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

銀河麻雀の待ちを判定するWebアプリを作った

Last updated at Posted at 2022-03-18

麻雀YouTuberの麻雀カッコイイシリーズが投稿した「銀河麻雀」。

(ルール説明は13:40くらいから)
簡単に言えば、各種類の牌に1枚ずつ「ギャラクシー牌(銀河牌)」と呼ばれる牌種が自由になる牌が入った状態での麻雀だ。
例えば、銀河1mは1p,1sとしても扱える。
銀河東は東南西北、銀河白は發中としても扱える。

銀河牌がたくさん入ると、受け入れや待ちの数が通常よりも多くなる。
銀河牌が沢山入った順子が並べば、とても人間の頭では処理しきれない、まさに銀河が広がるような麻雀となる。

前回の記事では「待ちを判定するプログラムを作った」ということを書いたが、この度こちらをWebアプリ化した。
↓こちらから使えるので、ぜひ銀河麻雀のお供に役立てて欲しい。

たとえばこんな大変な手牌でも…

こんな感じで簡単に待ちを調べられる。
(探索には数十秒くらいかかる場合があります)

image.png

以下はWebアプリ作成にあたって、前回の記事からプログラムも大幅に見直したので、その辺を書く。
プログラミングとかに興味ないひとはここから先は見なくていいよ。

バックエンドについて

以前作ったこのwebアプリのものを流用しているので、こちらを参考にして欲しい。
今回はDynamoDBも必要なく、Lambdaとつなぐだけなので結構あっさり実装できた。

プログラムの見直しについて

Lambdaでプログラムを実装し直すにあたって、前回のプログラムを大幅にリファクタリングした。

・アガリ判定のロジックを見直した。

こちらの方法を参考にして実装した。

・前回はデータの持ち方や受け渡しの部分がグチャグチャになっていたので、それらを大幅に見直した。具体的には、9×3+7列の多重Listで持っていた牌のデータを、34列のListに変えた。また、アガリ判定のフラグも、前回はBoolのリストで管理していたが、bit演算を使ってintで管理するようにした。

・再帰の処理で余計な処理をしている部分がいっぱいあったので、その辺も整理した。

ということで、リファクタ後のclass tehaiはこちら。

lambda_handler.py(一部)
class tehai:
    def __init__(self,hand):
        self.hand = [0 for _ in range(34)]
        for i in range(34):
            self.hand[i] = hand[i]

    def len(self):
        return sum(self.hand)
    
    def agari(self):
        if self.len() % 3 != 2:
            return False
            
        for i in range(34):
            if self.hand[i] > 4:
                return False

        if self.len() == 14:
            f7 = True
            for m in self.hand:
                if m % 2 != 0:
                    f7 = False
            if f7:
                return True 
        
        for i in range(34):
            if self.hand[i] >= 2:
                self.hand[i] -= 2
                
                flag = True
                for j in range(3):
                    suhai = self.hand[j*9:(j+1)*9]
                    flag = flag & mentsu(suhai)
                
                for j in range(7):
                    flag = flag & (self.hand[j+27] % 3 == 0)
                
                self.hand[i] += 2
                if flag:
                    return True
        return False
    
    def machi(self):
        flag = 0
        for i in range(34):
            self.hand[i] += 1
            if self.agari():
                flag = flag | (1 << i)
            self.hand[i] -= 1
        return flag

だいぶすっきりした。
webで公開しているアプリなので、全部のコードを晒すことは控えておく。(万が一にも脆弱性とか攻撃とかされたら嫌なので…)

色々工夫を加えたことにより、Lambdaの実行環境においては銀河牌7枚まで1分以内に計算が終わるようになった。
ただ、ここから削っていくには根本的なアルゴリズムの工夫が必要なので、回収はかなり大変そうである。
気が向いたら頑張ることにする。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?