花札(花合わせ)ゲームプログラミング

# はじめに

　本記事の目的は、ゲームの製作を通じてプログラミング技能を習得してもらうことです。

　想定する読者は、次の通りです。
* 余りの計算を学習済み(小学校4年生以上)の方
* Scracthに触れたことのある方
* ブラインドタッチができて、1分あたり140キーの速さで打鍵できる方

　実際に教えた(教える方がつまづいたことを反映した)内容を記述します。

　ゲームとしては花札の花合わせを題材に、要件は「役が覚えられないので、手札から揃いそうな役を示して欲しい」でした。以下、1.2.と発展的に作っていきたいと思います。

1. 今の手札から揃いそうな役を示す
2. 人同士の対戦ゲーム化

---

# プログラミングとは

## 概要

* コンピュータ上で動作するプログラムを作る行為
* プログラム ＝ データ + ロジック[^1]
    *  **入力データ**と**出力データ**を対応づけるロジックの集合のこと
    *  入力は人間が行う場合と、他のロジックの出力が入力となる場合がある
    *  出力も人間に行う場合と、他のロジックの入力となる場合がある
    
* データ ＝ 基本データ + 集成体[^2]
    * 基本データの種類: 整数/文字/論理/小数/列挙/参照
    * 集成体: 基本データを要素とする列のこと
        * 配列: 同じ基本データを要素とする有限列
            * 特に文字の配列は「文字列」
        * リスト: 同じ基本データを要素とする無限列
        * タプル: 異なる基本データを要素とする列
    
* ロジック: 　入力データと出力データを対応づける計算のこと[^3]
    * 命令型プログラミング: Scrachはこれに該当
        * ロジックを実行順序で記述する方法
        * 順次(sequence)と選択(selection)と反復(repetition)の3つの制御構造を持つ
    * 関数型プログラミング
        * ロジックを関数で記述する方法
    * 論理型プログラミング
        * ロジックを推論で記述する方法
  
[^1]: 本来なら「アルゴリズム　+ データ構造　＝　プログラム」　ここでは若年者向けに使用する単語を単純にした。また、設計順序に従って、アルゴリズムよりもデータを先に言及することにした。まず「アルゴリズム」という言葉が未知。

[^2]: 「データ」そのものも未知の単語。

[^3]: 未知の単語が出すぎて初回はいっぱいいっぱい。プログラミングの思考過程に慣れてもらう意味で、具体例を逐一説明していく必要があると判断した。次回はScrachプログラミングを演習として行う

---

# 花合わせゲームのプログラミング#1

## 花合わせ

プログラミング対象である花札を使った花合わせゲームは、次の通りである。

* 花合わせは花札４８枚のカードゲーム
    * 光、種、短冊、カスの４種類の札から構成[^4]
    * 札の組み合わせで役を構成
![花札一覧](http://hirobee.oops.jp/hanahuda/h00.gif)

|役|説明|
|:-:|:--|
|カス|![カス](http://hirobee.oops.jp/hanahuda/h01.gif)|
|短冊|![短冊](http://hirobee.oops.jp/hanahuda/h02.gif)|
|赤短|![赤短](http://hirobee.oops.jp/hanahuda/h04.gif)|
|青短|![青短](http://hirobee.oops.jp/hanahuda/h05.gif)|
|タネ|![タネ](http://hirobee.oops.jp/hanahuda/h03.gif)|
|猪鹿蝶|![猪鹿蝶](http://hirobee.oops.jp/hanahuda/h06.gif)|
|三光|![三光](http://hirobee.oops.jp/hanahuda/h07.gif)|
|四光|![四光](http://hirobee.oops.jp/hanahuda/h08.gif)|
|雨四光|![雨四光](http://hirobee.oops.jp/hanahuda/h09.gif)|
|五光|![五光](http://hirobee.oops.jp/hanahuda/h10.gif)|
|花見で一杯|![菊種札](http://hirobee.oops.jp/hanahuda/h12.gif) <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192607/3c883c6d-f3a6-cc7f-8f85-73400eb06580.png" width="58" />|
|月見で一杯|![菊種札](http://hirobee.oops.jp/hanahuda/h12.gif) <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192607/618ebe06-e859-0500-77cd-bf8b0e2e2cff.png" width="56" />|
|月札|各月4枚そろった場合|

[^4]: 画像は http://hirobee.oops.jp/hanahuda/yaku.htm より

---

## 手札が構成し得る役を示すプログラム

 例えば、手札に猪札がある場合、猪札が含まれる役には「猪鹿蝶」がある。したがって、手札が構成し得る役を示すには、役「猪鹿蝶」を計算結果とすればよい。

### 手札の1枚がどの役になるのか/条件if-thenブロック

手札に含まれる札を大括弧[]、役を構成する札を小括弧()を使用すると、役「猪鹿蝶」は次の通りである。

<dl>
<dt>　例１) 役「猪鹿蝶」</dt>
<dd>手札[猪札] なら 猪鹿蝶(猪札, 鹿札, 蝶札)</dd>
<dd>手札[鹿札] なら 猪鹿蝶(猪札, 鹿札, 蝶札)</dd>
<dd>手札[鹿札] なら 猪鹿蝶(猪札, 鹿札, 蝶札)</dd>
</dl>

　これをScratchでは制御if-thenブロックで次の通りに記述できる。
![スクリーンショット 2022-03-30 12.05.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192607/ea00bfd1-5980-a636-c913-129be5fa19e3.png)

　if-thenブロックの中が同じなら、演算orブロックでまとめることもできる。
![スクリーンショット 2022-03-30 12.08.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192607/98437815-ba25-cad8-6f45-38e13d7e20d2.png)

同様に、役「花見で一杯」と「月見で一杯」を考える。

<dl>
<dt>　例2) 役「花見で一杯」</dt>
<dd>手札[菊種札] なら 花見で一杯(菊種札, 桜光札)</dd>
<dd>手札[桜光札] なら 花見で一杯(菊種札, 桜光札)</dd>
<dt>　例3) 役「月見で一杯」</dt>
<dd>手札[菊種札] なら 月見で一杯(菊種札, 坊主光札)</dd>
<dd>手札[坊主光札] なら 月見で一杯(菊種札, 坊主光札)</dd>
</dl>

　つまり、手札が菊種札である場合両方に該当するため、計算結果として「花見で一杯」と「月見で一杯」が得られなければならない。ここで、花見で一杯や月見で一杯に限らず他にも役があることを考えると、役の**全てを通して**特定の1枚の札に対して、該当する役を示す計算が必要なことがわかるだろう。

--- 

### Scratchプログラミング演習#1: ブロック

* 例1,2,3以外の役を判定するロジックをブロック[^5]を使って作ろう
    * カス/タネ/短冊/青短/赤短
    * 三光/四光/雨四光/五光

[^5]: Scratchのブロックは戻り値を持たない手続き。引数にリストを取れない。

### 復習: プログラム＝データ＋ロジック

　プログラムは、データとロジックの集合であった。ロジックは入力データと出力データを伴う。今回の場合のロジックは**共通して**次の通りである。

* 入力データ: 札
* 出力データ: 該当する役

　役は複数あるので、示す役を計算するロジックは役の数だけ必要となる。演習#1では、役の数だけ必要なロジックを作成した。

　ロジックは入力データと出力データの対応づけだと言及した。
* ロジックを考える前に、プログラミング対象からどんなデータを識別するか
* そのデータをどのようなロジックに切り分けていくか
* 切り方は方法論といい、今回はScrachを前提としているので命令型プログラミングの方法論-**実行順序**で切り分けた。
* 命令型プログラミングの方法論とは順次、選択、反復の組み合わせでロジックを構成する方法である

### 小まとめ: プログラミングの学習要素

* 実行順序の制御構造
    * 条件ブロック/if-then
* 演算
    * 比較ブロック/==
    * 論理和ブロック/or
* モジュール
    * 定義ブロック/procedure

---

# 花合わせゲームプログラミング#2

## おさらい

## データ構造の導入と定回反復

　花札ゲームは少なくとも次のデータで構成されている、と考える。

 1. 札データ: 1月から12月まで各月4枚計48枚。
 1. 手札データ: 札データを要素とする集合
 1. 役データ: 各々の役を構成する札データの集合。手札データと同じで、札データを要素する集合

* 役データをリストで構成して、「リストになにか含まれるか？」式を使ってみよう
* 「何が含まれるか」式は定回反復と同等

制御の繰り返しを使って、手札が複数の場合に拡張してみよう
    * 計算結果がどうなるかな？

　手札[菊種札, 猪札, 鹿札]の場合、役としては、花見で一杯・月見で一杯・猪鹿蝶の3つでなければならない。
しかし、演習#1のプログラムのままでは、計算結果として花見で一杯・月見で一杯・猪鹿蝶・猪鹿蝶と四つの結果を得てしまう。これを正しく、「花見で一杯・月見で一杯・猪鹿蝶」3つにするにはどうすればよいか？