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

[麻雀アプリを作りたい①](https://qiita.com/kph7mgb/items/cd7bdcc0fbc58e31ffb6)で牌を配ることはできました。
次はそれを理牌する処理を作りたいと思います。

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

# 山牌　シャッフルされた１３６個の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ループに変換したみたいに、
ラムダ式をメソッドに変換する機能があります。

<img width="1062" alt="スクリーンショット 2019-05-17 3.25.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363095/92267a5a-3be2-38e6-c34f-33f9a19c369d.png">
ラムダ式の内容を確認するときとかに使えますね！


#Web表示結果
きれいに理牌できたと思います。
<img width="1268" alt="スクリーンショット 2019-05-17 3.32.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363095/f792b4b4-95af-8a48-0260-79a729194b23.png">
<img width="1268" alt="スクリーンショット 2019-05-17 3.32.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363095/6eedb92d-44cc-9e61-100d-3f7e75691cc2.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'


# 山牌　シャッフルされた１３６個の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)
```