LoginSignup
3
4

More than 3 years have passed since last update.

麻雀アプリを作りたい②〜理牌(ソート処理)〜

Posted at

麻雀アプリを作りたい①で牌を配ることはできました。
次はそれを理牌する処理を作りたいと思います。

理牌(ソート)

class Tile:
    def __init__(self, kind, value, pic):
        self.kind = kind  # 麻雀牌の種類(萬子・筒子・索子・四風牌・三元牌)
        self.value = value  # 麻雀牌の値(1~9 東南西北白発中)
        self.pic = pic  # 画像ファイル名

# 山牌 シャッフルされた136個のTileオブジェクトリストを返却
def create_yamahai():...

yamahai = create_yamahai() #山牌作成
haipai = [yamahai.pop(0) for i in range(14)]  # 配牌

haipaiにはTileクラスのオブジェクトが14個入っています。
それぞれのオブジェクトのkind(牌の種類:萬子・筒子・索子・四風牌・三元牌)
とvalue(麻雀牌の値:1~9 東南西北白発中)をくっつけてから
ソートすれば理牌すれば良さそうです。

ソート処理.py
def create_sort_key(hai: Tile):
    return f'{hai.kind}{hai.value}'

haipai.sort(key=create_sort_key)  # 理牌

sortメソッドを呼ぶことでソートできます。
key=sort_keyが何を表しているか慣れていないと難しいですね…。

sortメソッドがやってること

sortメソッドの説明の前に、
create_sort_keyメソッドの説明をしますね。
create_sort_keyメソッドは、引数として受け取ったTileオブジェクトの
kindとvalueをくっつけた文字列を返却しています。

んで、sortメソッドの中に'key='ってありますが、
これがソートするときのキー項目となります。
haipaiはリストなので、その要素であるTileオブジェクトを
create_sort_keyメソッドの引数として渡し、
戻り値の文字列(kind+valueの文字列)を使ってソートしています。

この書き方ですが、create_sort_keyメソッドを書かなくてもできます。
ラムダ式って言われている書き方です。

ラムダ式を使ってみた

上記のソート処理をラムダ式を使って書くと以下の通りになります。

ソート処理(ラムダ式Ver).py
haipai.sort(key=lambda hai: f'{hai.kind}{hai.value}')  # 理牌

haipaiリストの要素オブジェクトをhaiという変数に入れて、
:から始まる処理の結果をソートのキーとしています。

ソートキー作成用のメソッドをいちいち作成しなくていいので便利ですね!

参考:
https://docs.python.org/ja/3/howto/sorting.html#sortinghowto
https://www.headboost.jp/python-lambda/#21_sortedlambda

おまけ

PyCharmにはリスト内包表記をforループに変換したみたいに、
ラムダ式をメソッドに変換する機能があります。

スクリーンショット 2019-05-17 3.25.01.png
ラムダ式の内容を確認するときとかに使えますね!

Web表示結果

きれいに理牌できたと思います。
スクリーンショット 2019-05-17 3.32.31.png
スクリーンショット 2019-05-17 3.32.21.png

次は当たり判定を作りたいと思います。

main.py
from flask import Flask
import random

app = Flask(__name__)


# 麻雀牌のクラス
class Tile:
    NUMBERS = "pinzu", "manzu", "souzu"
    WINDS = "東南西北"
    COLORS = "白發中"

    def __init__(self, kind, value, pic):
        self.kind = kind  # 麻雀牌の種類(萬子・筒子・索子・四風牌・三元牌)
        self.value = value  # 麻雀牌の値(1~9 東南西北白発中)
        self.pic = pic  # 画像ファイル名

    def __repr__(self):
        return f'({self.kind}, {self.value}, {self.pic})\n'


# 山牌 シャッフルされた136個のTileオブジェクトリストを返却
def create_yamahai():
    tiles = [Tile(kind, value, f"{kind}_{value}.png")
             for kind in Tile.NUMBERS
             for value in range(1, 9 + 1)]
    tiles += [Tile("x_sufonpai", value, f"sufonpai_{value}.png")
              for value, label in enumerate(Tile.WINDS, 1)]
    tiles += [Tile("y_sangenpai", value, f"sangenpai_{value}.png")
              for value, label in enumerate(Tile.COLORS, 1)]
    tiles *= 4

    random.shuffle(tiles)
    return tiles


yamahai = create_yamahai() #山牌作成


@app.route('/')
def main():
    haipai = [yamahai.pop(0) for i in range(14)]  # 配牌

    haipai.sort(key=lambda hai: f'{hai.kind}{hai.value}')  # 理牌
    return ''.join(map(lambda tile: f'<img src=/static/pic/{tile.pic}>', haipai))  # 画像表示


if __name__ == '__main__':
    app.run(port=8080)
3
4
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
4