麻雀アプリを作りたい①で牌を配ることはできました。
次はそれを理牌する処理を作りたいと思います。
#理牌(ソート)
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 東南西北白発中)をくっつけてから
ソートすれば理牌すれば良さそうです。
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メソッドを書かなくてもできます。
ラムダ式って言われている書き方です。
###ラムダ式を使ってみた
上記のソート処理をラムダ式を使って書くと以下の通りになります。
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ループに変換したみたいに、
ラムダ式をメソッドに変換する機能があります。
次は当たり判定を作りたいと思います。
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)