# C#の入門

# 変数と型

## 練習課題

[記入できるファイルをダウンロード](https://class.illogic.games/attachments/5)

### 変数の宣言と代入

ゲームを作っている間に、ゲームに関するいろんなデータを管理しなければならない。以下のデータについて考え、最も適する「データ型」を選択してください。

<table class="align-left" id="bkmrk-%E3%83%87%E3%83%BC%E3%82%BF%E5%9E%8B%E4%BE%8B%E3%83%97%E3%83%AC%E3%83%BC%E3%83%A4%E3%83%BC%E3%81%AE%E7%82%B9%E6%95%B0%E6%95%B4%E6%95%B0%E5%9E%8B%EF%BC%88int" style="width:98.0952%;"><colgroup><col style="width:36.938%;"></col><col style="width:26.4895%;"></col><col style="width:36.5725%;"></col></colgroup><thead><tr><td class="align-center">**データ**</td><td class="align-center">**型**</td><td class="align-center">**例**</td></tr></thead><tbody><tr><td>プレーヤーの点数</td><td class="align-left">整数型（int)</td><td class="align-left">```c#
int points = 100;
```

</td></tr><tr><td>プレーヤーの名前</td><td><details><summary>答え</summary>

文字列（string）

</details></td><td class="align-left"><details><summary>答え</summary>

```c#
string playerName;
```

</details></td></tr><tr><td class="align-left">現在持っているアイテムの数</td><td><details><summary>答え</summary>

整数型（int)

</details></td><td><details><summary>答え</summary>

```c#
int itemCount = 5;
```

</details></td></tr><tr><td class="align-left">車が走った距離</td><td><details><summary>答え</summary>

小数型（float）

</details></td><td><details><summary>答え</summary>

```c#
float distance = 25.12f;
```

</details></td></tr><tr><td class="align-left">ゲームの初期化が終わった？</td><td><details><summary>答え</summary>

ブール型（bool）

</details></td><td><details><summary>答え</summary>

```c#
bool isStarted = false;
```

</details></td></tr><tr><td class="align-left">ステージのタイトル</td><td><details><summary>答え</summary>

文字列（string）

</details></td><td><details><summary>答え</summary>

```c#
string stageName = "ステージ１"
```

</details></td></tr><tr><td>キャラクターのセリフ</td><td><details><summary>答え</summary>

文字列（string）

</details></td><td><details><summary>答え</summary>

```c#
string dialogue;
```

</details></td></tr><tr><td>ゲーム終了かどうか</td><td><details><summary>答え</summary>

ブール型（bool)

</details></td><td><details><summary>答え</summary>

```c#
bool isGameOver = true;
```

</details></td></tr><tr><td>残りの体力</td><td><details><summary>答え</summary>

整数型（int）

</details></td><td><details><summary>答え</summary>

```c#
int playerHP = 100;
```

</details></td></tr><tr><td>アイテムのコスト</td><td><details><summary>答え</summary>

整数型（int)

</details></td><td><details><summary>答え</summary>

```c#
int itemCost;
```

</details></td></tr><tr><td>レースコースの名称</td><td><details><summary>答え</summary>

文字列（string）

</details></td><td><details><summary>答え</summary>

```c#
string courseName = "レインボーコース"
```

</details></td></tr><tr><td>ステージの残り時間</td><td><details><summary>答え</summary>

小数型（float）

</details></td><td><details><summary>答え</summary>

```c#
float timeRemaining = 60.0f;
```

</details></td></tr></tbody></table>

### C#を読みましょう

以下の表は、C#で書いた命令とその日本語の意味が書いてある。空枠を完成してください。

<table class="align-left" id="bkmrk-c%23%E6%97%A5%E6%9C%AC%E8%AA%9Eint-counter%3B%E4%BD%95%E3%81%8B%E6%95%B0"><colgroup><col style="width:260px;"></col><col style="width:649px;"></col></colgroup><thead><tr><td class="align-center">**C#**</td><td class="align-center">**日本語**</td></tr></thead><tbody><tr><td>```c#
int counter;
```

</td><td>何か数える「カウンター」整数型変数を宣言</td></tr><tr><td>```c#
float height = 1.70f;
```

</td><td><details><summary>答え</summary>

「高さ」を表す小数型変数を宣言し、1.70メートルを代入

</details></td></tr><tr><td>```c#
float distance = 100;
```

</td><td><details><summary>答え</summary>

「距離」を表す小数型の変数を宣言し、100メートルで初期する

</details></td></tr><tr><td><details><summary>答え</summary>

```c#
string saveFileName = "save0001.dat"
```

</details></td><td>「セーブファイル名」専用の変数を宣言し、 「save0001.dat」を代入

</td></tr><tr><td>```c#
bool isTimeOut = false;
```

</td><td><details><summary>答え</summary>

 時間切れ（タイムアウト）を表すブール型の変数を宣言し、「いいえ」（false）で始まる。

</details></td></tr><tr><td><details><summary>答え</summary>

```c#
 int coinCount;
```

</details></td><td>ステージの中に残っている「コイン」の数の変数を宣言</td></tr><tr><td><details><summary>答え</summary>

```c#
 bool hasKeycard = false;
```

</details></td><td>プレーヤーがドアを開くための「キーカード」を拾ったかを表す変数を宣言し、「いいえ（偽）」で始まる。</td></tr><tr><td>```c#
string bossName = "";
```

</td><td><details><summary>答え</summary>

 ボスの名前を保存するための文字列型変数を宣言し、中身は空。

</details></td></tr><tr><td><details><summary>答え</summary>

```c#
int a = 10;
int b = 5;
float c = a / b;
```

</details></td><td class="align-left">整数型の変数「a」を宣言し、「10」を代入する。 整数型の変数「b」を宣言し、「5」を代入する。

小数型の変数「c」を宣言し、「ａ割るｂ」を代入する。

</td></tr><tr><td>```c#
string firstName = "太郎";
string lastName = "大原";
string fullName = lastName + " " + firstName;
```

</td><td class="align-left"><details><summary>答え</summary>

下の名前（firstName）と苗字（lastName）の文字列型変数を作成し、「太郎」と「大原」を代入する。

最後、フルネームの変数を作成し、名前と苗字を連結し、代入する。

つまり、「fullName」の中には「大原 太郎」が入っている

</details></td></tr></tbody></table>

### 初期化の値で型を決める：暗黙的な型指定「var」

今まで、変数を宣言するときに、どのデータを入れるべきかを「型」で指定しなければならない。ただ、宣言の時に一緒に何かの「値」を代入する場合、その「値」から直接に「型」を判断し、自動的に変数の「型」を指定することもできる。

この場合は、変数を「var」で宣言してください。

例：

```c#
var counter = 0;        // 0 は整数なので、counterはintになる
var height = 1.70f;     // 1.70fは実数（小数）なので、heightはfloatになる
var name = "Player 1";  // "Player 1"は文字列なので、nameはstringになる
var isGameOver = false; // falseは「偽」なので、isGameOverはboolになる
```

「var」を使うことにより、代入する数値に合わせて、型を決める

---

**Q.**<span style="white-space:pre-wrap;"> いつ「var」を使うか？</span>  
**A.**<span style="white-space:pre-wrap;"> 自由に使えるが、普通に「一時的に使い捨てる変数」を使うケースが多い。</span>

**Q.**<span style="white-space:pre-wrap;"> 使えない時もある？</span>  
**A.**<span style="white-space:pre-wrap;"> 以下の場合は「var」を使えない</span>

- 宣言のみの時（代入なし）

```c#
var number = 10;  // OK!
var number;       // NG
```

- メソッドの「引数」と「戻り値」（※メソッドについてはまた後で）
- クラスの「メンバー変数」（※クラスとメンバー変数についてはまた後で）

# 比較

## 練習課題

[記入できるファイルをダウンロード](https://class.illogic.games/attachments/7)

### C#を読みましょう

以下の表は、C#で書いた命令とその日本語の意味が書いてある。空枠を完成してください。

<table id="bkmrk-c%23-%E6%97%A5%E6%9C%AC%E8%AA%9E-a-%3E-b-%E5%A4%89%E6%95%B0%E3%80%8Ca%E3%80%8D%E3%81%AF%E5%A4%89" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:34.5633%;"></col><col style="width:65.4367%;"></col></colgroup><thead><tr><td class="align-center">**C#**

</td><td>**日本語**

</td></tr></thead><tbody><tr><td>```c#
a > b
```

</td><td>変数「a」は変数「b」よりも大きい？

</td></tr><tr><td>```c#
i <= 10
```

</td><td><details><summary>答え</summary>

変数「i」は「10」以下？

</details></td></tr><tr><td><details><summary>答え</summary>

```c#
playerHP > 0
```

</details></td><td>プレーヤーの体力は残っている？

</td></tr><tr><td>```c#
stageSelect == "Tutorial"
```

</td><td><details><summary>答え</summary>

選択されたステージはチュートリアルであるか？

</details></td></tr><tr><td>```c#
coinCount >= itemCost
```

</td><td><details><summary>答え</summary>

持っているコイン数はアイテム価格を超える？

</details></td></tr><tr><td><details><summary>答え</summary>

```c#
keyCount == 3
```

</details></td><td>鍵がちょうど3個ある？

</td></tr><tr><td><details><summary>答え</summary>

```c#
time < 60
```

</details></td><td>残りの時間は60秒未満？

</td></tr><tr><td>```c#
player != "CPU Player"
```

</td><td><details><summary>答え</summary>

プレーヤーはCPUプレーヤーではないね？

</details></td></tr></tbody></table>

### 比較を評価

以下の比較を確認し、「true」（真・はい）または「false」（偽・いいえ）をチェックしてください。ただし、事前に以下の変数をすでに作成されている：

```c#
int a = 100;
int b = 20;
float c = 5.0f;
```

<table id="bkmrk-%E6%AF%94%E8%BC%83-true-false-a-%3D%3D-1" style="border-collapse:collapse;width:100%;height:390.6px;"><colgroup><col style="width:29.7974%;"></col><col style="width:36.0094%;"></col><col style="width:34.1932%;"></col></colgroup><thead><tr style="height:29.8px;"><td class="align-center" style="height:29.8px;">**比較**</td><td class="align-center" style="height:29.8px;">**true**</td><td class="align-center" style="height:29.8px;">**false**</td></tr></thead><tbody><tr style="height:66.2px;"><td style="height:66.2px;">```c#
a == 100;
```

</td><td class="align-center" style="height:66.2px;">✔</td><td style="height:66.2px;">  
</td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
b < c
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

falseでした！ &gt;&gt;

・b は 20

・c は 5

・b は c 未満 (&lt;) ではない

</details>  
</td><td style="height:66.2px;"><details><summary>答え</summary>

✔

</details></td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
c >= a / b;
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

✔

</details></td><td style="height:66.2px;"><details><summary>答え</summary>

 &lt;&lt; trueでした！

・c は 5

・a / b ⇒ 100 /20 ⇒ 5

・5は5以上( &gt;= )である

</details></td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
c * 6 < b * 2;
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

✔

</details>  
</td><td style="height:66.2px;"><details><summary>答え</summary>

 &lt;&lt; trueでした！

・c×6 ⇒ 5×6 ⇒ 30

・b×2 ⇒ 20×2 ⇒ 40

・30は40未満（&lt;）である

</details></td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
a == b * c;
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

✔

</details></td><td style="height:66.2px;"><details><summary>答え</summary>

 &lt;&lt; trueでした！

・aは100

・b×c⇒ 20×5 ⇒ 100

・同じ（==）である

</details></td></tr><tr style="height:29.8px;"><td style="height:29.8px;">```c#
b != a - 80;
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

 falseでした！ &gt;&gt;

・b は 20

・a - 80 ⇒ 100 - 80 ⇒ 20

・異なる（!=）のではない

</details></td><td style="height:66.2px;"><details><summary>答え</summary>

✔

</details></td></tr></tbody></table>

### 論理演算子で条件を連結：「かつ」と「または」

ゲームを開発しているときに、if文で同時に２つのことを確認したい場合もある。

例えば、レースゲームの勝利条件は：

- ゴールに着いた
- 時間がまだ残っている

両方とも同時に「true」だったら、ゲームの勝ちになる。２つの条件同時に満たさないといけない場合は「AND演算子」を使いましょう

#### 「かつ」演算子：AND（アンド）：`&&`

この演算子で両方の条件を満たさないと「true」にならない。２つの条件「Ａ」と「Ｂ」があるとしたら：

<table id="bkmrk-a-b-a-%26%26-b-false-fal" style="border-collapse:collapse;width:58.6905%;height:145.334px;"><colgroup><col style="width:33.3131%;"></col><col style="width:33.3131%;"></col><col style="width:33.3131%;"></col></colgroup><thead><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;">A</td><td class="align-center" style="height:29.4667px;">B</td><td class="align-center" style="height:29.4667px;">A &amp;&amp; B</td></tr></thead><tbody><tr style="height:27.4667px;"><td class="align-center" style="height:27.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:27.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:27.4667px;"><span style="color:rgb(186,55,42);">false</span></td></tr><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);">false</span></td></tr><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);">false</span></td></tr><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td></tr></tbody></table>

つまり、いずれかの条件が「false」でしたら、すべて「false」になる。上記の例で、C#にすると：

```c#
// 走行距離
float runDistance = 1235.0f;

// ゴールまでの距離
float goalDistance = 1200.0f

// 残りの時間
float timeLeft = 35.7f;

// 走行距離はゴールよりも大きく「かつ」残りの時間が０以上だったら
if (runDistance >= goalDistance && timeLeft > 0)
{
  Debug.Log("勝ち！");
}
```

これで、必ず２つの条件を満たしたら、ゲームクリアになることを保証できる。

#### 「または」演算子：OR（オア）：`||`

もう一つのパターンは「いずれかの条件が true だったら、すべて true になる」かある。例えば、あるゲームの中で２つのドアの開き方がある：

- ドアの鍵を持っている
- プレーヤーの力が十分だったら、自力で壊す

この場合は、１つだけの条件を満たしたら、ドアを開くことができるので、「または」の演算子を使えば良いでしょう。

<table id="bkmrk-a-b-a-%7C%7C-b-false-fal" style="border-collapse:collapse;width:58.6905%;height:145.334px;"><colgroup><col style="width:33.3131%;"></col><col style="width:33.3131%;"></col><col style="width:33.3131%;"></col></colgroup><thead><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;">A</td><td class="align-center" style="height:29.4667px;">B</td><td class="align-center" style="height:29.4667px;">A || B</td></tr></thead><tbody><tr style="height:27.4667px;"><td class="align-center" style="height:27.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:27.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:27.4667px;"><span style="color:rgb(186,55,42);">false</span></td></tr><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);"><span style="color:rgb(22,145,121);">true</span></span></td></tr><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);">false</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(186,55,42);"><span style="color:rgb(22,145,121);">true</span></span></td></tr><tr style="height:29.4667px;"><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td><td class="align-center" style="height:29.4667px;"><span style="color:rgb(22,145,121);">true</span></td></tr></tbody></table>

上記の例で、C#にすると：

```c#
// プレーヤーの力
float playerPower = 30;

// 今持っている鍵の数
int keyCount = 0;

// ドアの固さ
float doorHardness = 25;

// 鍵があれば「または」力は固さよりも大きければ…
if (keyCount > 0 || playerPower >= doorHardness)
{
  Debug.Log("ドアを開ける！");
}
```

この例だと、鍵がなくても力で壊せるので、ドアを開くことができる！

### 練習

以下、使った「かつ」と「または」の比較を確認し、「true」（真・はい）または「false」（偽・いいえ）を書いてください。ただし、事前に以下の変数をすでに作成されている：

```c#
int coin = 230;       // コインの数
int maxItem = 10;     // 最大のアイテムの数
int nowItem = 9;      // 現在持っているアイテムの数
int potionCost = 100; // ポーションのコスト
```

1\. 比較：

```c#
coin > potionCost && nowItem + 1 <= maxItem
```

<table id="bkmrk-true-false-%E7%AD%94%E3%81%88-%E2%9C%94-%E7%AD%94%E3%81%88-%3C" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center" style="height:29.8px;">**true**</td><td class="align-center" style="height:29.8px;">**false**</td></tr></thead><tbody><tr><td><details><summary>答え</summary>

✔

</details></td><td><details><summary>答え</summary>

&lt;&lt; trueでした！

コインは230でポーションは100なので

```c#
coin > potionCost
```

は `true`（真）である

で、持っているアイテムは9個で、最大10個なので

```c#
nowItem + 1 <= maxItem 
```

も `true`（真）である

両方とも「true」であり、「true かつ true」は「true」

</details></td></tr></tbody></table>

2\. 比較：

```c#
potionCost > coin || nowItem >= maxItem
```

<table id="bkmrk-true-false-%E7%AD%94%E3%81%88-false%E3%81%A7" style="border-collapse:collapse;width:100%;height:90.1px;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr style="height:29.8px;"><td class="align-center" style="height:29.8px;">**true**</td><td class="align-center" style="height:29.8px;">**false**</td></tr></thead><tbody><tr style="height:60.3px;"><td style="height:60.3px;"><details><summary>答え</summary>

falseでした！&gt;&gt;

ポーション（100）はコイン（230）を超えないので

```c#
potionCost > coin
```

は「false」である。

で、持っているアイテムの数（9）最大アイテム以上ではないため

```c#
nowItem >= maxItem
```

も「false」である

「false」または「false」（両方も「偽」）であるため、結果は false である

</details></td><td style="height:60.3px;"><details><summary>答え</summary>

✔

</details></td></tr></tbody></table>

3\. 比較：

```c#
potionCost * 2 <= coin && maxItem >= nowItem + 2
```

<table id="bkmrk-true-false-%E7%AD%94%E3%81%88-false-" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center" style="height:29.8px;">**true**</td><td class="align-center" style="height:29.8px;">**false**</td></tr></thead><tbody><tr><td><details><summary>答え</summary>

false でした！&gt;&gt;

ポーション２個は200で、もっといるコインは230なので

```c#
potionCost * 2 <= coin
```

は `true`（真）である

だが、持っているアイテム（9個）にさらに２つを増やすと、最大数（10個）を超えてしまうので

```c#
maxItem >= nowItem + 2
```

も `false`（偽）である

「かつ」（&amp;&amp;）は両方とも「true」じゃないとだめなので、最終結果は「false」になってしまう。

</details></td><td><details><summary>答え</summary>

✔

</details></td></tr></tbody></table>

4\. 比較：

```c#
nowItem == 0 && coin != 0
```

<table id="bkmrk-true-false-%E7%AD%94%E3%81%88-false--1" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center" style="height:29.8px;">**true**</td><td class="align-center" style="height:29.8px;">**false**</td></tr></thead><tbody><tr><td><details><summary>答え</summary>

false でした！&gt;&gt;

持っているアイテムは０ではなく、９個なので

```c#
nowItem == 0
```

は `false`（偽）である

「かつ」（&amp;&amp;）は両方とも「true」じゃないとだめなので、もう一つの条件は関係なく、最終結果は「false」になってしまう。

</details></td><td><details><summary>答え</summary>

✔

</details></td></tr></tbody></table>

5\. 比較：

```c#
maxItem - nowItem > 9 || coin > 0
```

<table id="bkmrk-true-false-%E7%AD%94%E3%81%88-%E2%9C%94-%E7%AD%94%E3%81%88-%3C-1" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center" style="height:29.8px;">**true**</td><td class="align-center" style="height:29.8px;">**false**</td></tr></thead><tbody><tr><td><details><summary>答え</summary>

✔

</details></td><td><details><summary>答え</summary>

&lt;&lt; trueでした！

maxItemは10で、nowItemは9なので

maxItem - nowItem ⇒ 10 - 9 ⇒ 1

で、1 は 9 以上ではないので、

```c#
maxItem - nowItem > 9
```

は `false`（偽）である

だが、コインの数（230）は０以上なので

```c#
coin > 0
```

も `true`（真）である

「または」( || ) の場合は、<span style="text-decoration:underline;">いずれか</span>真だったら、すべて真になるため、この比較は「true」である。

</details></td></tr></tbody></table>

# 条件分岐

## 練習課題

[記入できるファイルをダウンロード](https://class.illogic.games/attachments/8)

### C#の処理を完成してみましょう

1\. 以下のC#のプログラムを完成してください

```c#
// ゲームでダメージを受け、残機を確認し、ゲームオーバーかどかう判定する

int hp = 50; // 体力
int lives = 1; // 残機
int damage = 100; // ダメージ

// ダメージを受け、体力を減らす

＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿

// もし、体力が０以下だったら...

＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
{
    // 残機を一つ減らす

    ＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
}

// もし、残機がゼロだったら

＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
{
    Debug.Log("ゲームオーバー");
}

// そうじゃない場合は、残機を表示
else
{
    Debug.Log($"残機：{lives}");
}
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%82%B2%E3%83%BC%E3%83%A0%E3%81%A7%E3%83%80%E3%83%A1%E3%83%BC%E3%82%B8%E3%82%92%E5%8F%97%E3%81%91%E3%80%81%E6%AE%8B%E6%A9%9F"><summary>答え</summary>

```c#
// ゲームでダメージを受け、残機を確認し、ゲームオーバーかどかう判定する

int hp = 50; // 体力
int lives = 1; // 残機
int damage = 100; // ダメージ

// ダメージを受け、体力を減らす
hp -= damage; // または hp = hp - damage;

// もし、体力が０以下だったら...
if (hp <= 0)
{
    // 残機を一つ減らす
    lives--;
}

// もし、残機がゼロだったら
if (lives == 0)
{
    Debug.Log("ゲームオーバー");
}

// そうじゃない場合は、残機を表示
else
{
    Debug.Log($"残機：{lives}");
}
```

</details>このプログラムはコンソールで何を表示するか？その出力を書いてください：

<table id="bkmrk-" style="border-collapse:collapse;width:100%;height:87.8px;"><colgroup><col style="width:99.881%;"></col></colgroup><tbody><tr style="height:87.8px;"><td style="height:87.8px;"><details><summary>答え</summary>

ゲームオーバー

</details></td></tr></tbody></table>

---

2\. 以下のC#のプログラムを完成してください

```c#
// レースゲームで、チェックポイントを通過することにより、時間切れを延期する

float timeLeft = 8.51; // 残りの時間（秒数）
float raceDistance = 3643.43; //走行距離

float checkPoint01 = 2300; // スタート → チェックポイント1の距離
float checkPoint02 = 1500; //  チェックポイント1 → チェックポイント2距離
float goalPoint = 2500; // チェックポイント2 → ゴールまでの距離

// もし、ゴールを超えていたら...

_____________________________________________________
{
    Debug.Log("レース終了！");
}

// 一方、もし走行距離がチェックポイント２を超えたら...

_____________________________________________________
{
    Debug.Log("チェックポイント２通過！");
    timeLeft += 80;
}

// 一方、もし走行距離がチェックポイント１を超えたら...

_____________________________________________________
{
    Debug.Log("チェックポイント1通過！");
    timeLeft += 60;
}

// 残りの時間を表示
Debug.Log($"残りの時間：{timeLeft}");
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B2%E3%83%BC%E3%83%A0%E3%81%A7%E3%80%81%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9D%E3%82%A4"><summary>答え</summary>

```c#
// レースゲームで、チェックポイントを通過することにより、時間切れを延期する

float timeLeft = 8.51; // 残りの時間（秒数）
float raceDistance = 3643.43; //走行距離

float checkPoint01 = 2300; // スタート → チェックポイント1の距離
float checkPoint02 = 1500; //  チェックポイント1 → チェックポイント2距離
float goalPoint = 2500; // チェックポイント2 → ゴールまでの距離

// もし、ゴールを超えていたら...
if (raceDistance >= checkPoint01 + checkPoint02 + goalPoint)
{
    Debug.Log("レース終了！");
}

// 一方、もし走行距離がチェックポイント２を超えたら...
else if (raceDistance >= checkPoint01 + checkPoint02)
{
    Debug.Log("チェックポイント２通過！");
    timeLeft += 80;
}

// 一方、もし走行距離がチェックポイント１を超えたら...
else if (raceDistance >= checkPoint01)
{
    Debug.Log("チェックポイント1通過！");
    timeLeft += 60;
}

// 残りの時間を表示
Debug.Log($"残りの時間：{timeLeft}");
```

</details>このプログラムはコンソールで何を表示するか？その出力を書いてください：

<table id="bkmrk--2" style="border-collapse:collapse;width:100%;height:87.8px;"><colgroup><col style="width:99.881%;"></col></colgroup><tbody><tr style="height:87.8px;"><td style="height:87.8px;"><details><summary>答え</summary>

チェックポイント１通過！

残りの時間：68.51

</details></td></tr></tbody></table>

### Unityで練習

体重と身長でBMIを計算し、画面で適切な出力を表示しよう（参考：[ＢＭＩと適正体重 ](https://keisan.casio.jp/exec/system/1161228732)）

<table id="bkmrk-%E5%BC%8F%EF%BC%9Abmi-%EF%BC%9D-%E4%BD%93%E9%87%8Dkg-%C3%B7-%28%E8%BA%AB%E9%95%B7m%29" style="border-collapse:collapse;width:100%;border-width:0px;"><colgroup><col style="width:30.5952%;"></col><col style="width:69.4048%;"></col></colgroup><tbody><tr><td style="border-width:0px;"><sup>![BMI Table](https://class.illogic.games/uploads/images/gallery/2026-03/scaled-1680-/2026-03-23-172118.png)</sup></td><td style="border-width:0px;">式：BMI ＝ 体重kg ÷ (身長m)<sup>2</sup></td></tr></tbody></table>

ヒント：

- 体重と慎重の変数を作成し、適当な数値を代入
- BMIを計算
- if分でBMIの判定し、コンソールで表示

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E4%BD%93%E9%87%8D-float-weigh"><summary>答え</summary>

```c#
// 体重
float weight = 70;

// 身長
float height = 1.71;

// BMIを計算
float bmi = weight / (height * height);

if (bmi < 18.5)
{
    Debug.Log("低体重");
}
else if (bmi < 25)
{
    Debug.Log("普通体重");
}
else if (bmi < 30)
{
    Debug.Log("肥満(1度)");
}
else if (bmi < 35)
{
    Debug.Log("肥満(2度)");
}
else if (bmi < 40)
{
    Debug.Log("肥満(3度)");
}
else 
{
    Debug.Log("肥満(4度)");
}
```

</details>---

## 比較の改良

### 同じ変数をなんども「==」で比較する「switch-case」

次の問題について考えてみてください

サイコロの数値は1から6までの間にして、その値を漢字で表示したい。つまり「1」の場合は「一」、「2」の場合は「二」など。if-elseで作成するとしたら、以下のようなプログラムになる：

```c#
// サイコロの値
int dice = 5;

if (dice == 1)
{
    Debug.Log("一");
}
else if (dice == 2)
{
    Debug.Log("二");
}
else if (dice == 3)
{
    Debug.Log("三");
}
else if (dice == 4)
{
    Debug.Log("四");
}
else if (dice == 5)
{
    Debug.Log("五");
}
else if (dice == 6)
{
    Debug.Log("六");
}
else
{
    Debug.Log("無効な数値");
}
```

このプログラムは、カスケードのように「1じゃなければ、2を確認する、2じゃなければ、3を確認する」、次々に「==」で比較するパターンは時々に現れる。この場合は「switch-case」が便利。上のプログラムは以下のようになる：

```c#
// サイコロの値
int dice = 5;

switch(dice)
{
case 1: // dice == 1 と同じ 
    Debug.Log("一");
    break;
case 2: // dice == 2 と同じ
    Debug.Log("二");
    break;
case 3: // dice == 3 と同じ
    Debug.Log("三");
    break;
case 4: // dice == 4 と同じ
    Debug.Log("四");
    break;
case 5: // dice == 5 と同じ
    Debug.Log("五");
    break;
case 6: // dice == 6 と同じ
    Debug.Log("六");
    break;
default: // elseと同じ
    Debug.Log("無効な数値");
    break;
}
```

### 整数に名前を付ける「列挙」（enum）

次の問題について考えてみてください。武器の種類により、攻撃力を変える処理を作りたい。処理しやすくするため、それぞれの武器に整数を与えた：

0: 非武装（攻撃力: 1）  
1: 剣（攻撃力: 5）  
2: ナイフ（攻撃力: 2）  
3: 鉄砲（攻撃力: 10）

「switch-case」を使えば、以下のような処理になる：

```c#
int damage = 0;
int weapon = 2;
switch(weapon)
{
case 0: 
  damage = 1;
  break;
case 1: 
  damage = 5;
  break;
case 2: 
  damage = 2;
  break;
case 3: 
  damage = 10;
  break;
}
Debug.Log($"攻撃力：{damage}");
```

これでも実行ができるが、時間がたてば「０はなんだったっけ？」「１は？」のように、それぞれの整数の意味を忘れてしまう可能性がある。各数値に忘れないように、名前を付ける方法がある。「列挙」を作成することにより、各整数に読みやすい名前を付けることができる。

まず、列挙を定義しなければならない：

<span style="text-decoration:underline;">**書式**</span>

```c#
enum 列挙名 
{
  整数「0」の名前,
  整数「1」の名前,
  整数「2」の名前,
  ...
  整数「n」の名前,
}
```

武器の例で、以下の列挙は適切でしょう：

```c#
enum Weapon
{
  Unarmed, // 0:非武装
  Sword,   // 1:剣
  Knife,   // 2:ナイフ
  Pistol,  // 3:鉄砲
}
```

そして、「switch-case」はとても分かりやすくなる！

```c#
int damage;
Weapon wpn = Weapon.Knife;  // 新し「Weapon」というデータ型を使える！
switch(wpn)
{
case Weapon.Unarmed: // 「0」と同じ
  damage = 1;
  break;
case Weapon.Sword:   // 「1」と同じ
  damage = 5;
  break;
case Weapon.Knife:   //「2」と同じ
  damage = 2;
  break;
case Weapon.Pistol:  //「3」と同じ
  damage = 10;
  break;
}
Debug.Log($"攻撃力：{damage}");
```

## 練習課題

ゲームでのアイテムショップを作ろうとして、以下のアイテムとその価格が決まった：

<table id="bkmrk-%E3%83%9D%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%88%E5%B0%8F%EF%BC%89-10%E3%82%BC%E3%83%8B-%E3%83%9D%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%88" style="border-collapse:collapse;width:34.1667%;height:208.6px;"><colgroup><col style="width:66.2776%;"></col><col style="width:33.7224%;"></col></colgroup><tbody><tr style="height:29.8px;"><td style="height:29.8px;">ポーション（小）</td><td style="height:29.8px;">10ゼニ</td></tr><tr style="height:29.8px;"><td style="height:29.8px;">ポーション（大）</td><td style="height:29.8px;">25ゼニ</td></tr><tr style="height:29.8px;"><td style="height:29.8px;">木の盾</td><td style="height:29.8px;">50ゼニ</td></tr><tr style="height:29.8px;"><td style="height:29.8px;">鉄の盾</td><td style="height:29.8px;">100ゼニ</td></tr><tr style="height:29.8px;"><td style="height:29.8px;">皮のブーツ</td><td style="height:29.8px;">40ゼニ</td></tr><tr style="height:29.8px;"><td style="height:29.8px;">魔法のマント</td><td style="height:29.8px;">250ゼニ</td></tr></tbody></table>

ここで、次のプログラムをC#で作成し、Unityで確認してください

1. 各種のアイテムを表すことができる「`ItemType`」の列挙を作成
2. プレーヤーを持っているお金の変数を準備（`playerMoney` - 整数型）
3. プレーヤーが買いたいアイテムの変数を準備（`buyItem` - `ItemType`の列挙型）
4. switch-caseで定めたアイテムの価格を求める（`itemCost` - 整数）
5. 変えるかどうかをif分で判定し、コンソールで結果を表示

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E5%90%84%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%81%AE%E5%88%97%E6%8C%99%EF%BC%88%E5%90%8D%E5%89%8D%E3%82%92%E5%A4%9A%E5%B0%91"><summary>答え</summary>

```c#
// 各アイテムの列挙（名前を多少に異なる可能性あり！）
enum ItemType
{
  PotionSmall,   // ポーション（小）
  PotionLarge,   // ポーション（大）
  WoodShield,    // 木の盾
  IronShield,    // 鉄の盾
  LeatherBoots,  // 皮のブーツ
  MagicCape,     // 魔法のマント
}

// 持っているお金
int playerMoney = 150;

// 買いたいアイテム
ItemType buyItem = ItemType.WoodShield; // なんでもOK

// 買いたいアイテムの価格
int itemCost; 
switch(buyItem)
{
    case ItemType.PotionSmall:
        itemCost = 10;
        break;
    case ItemType.PotionLarge:
        itemCost = 25;
        break;
    case ItemType.WoodShield:
        itemCost = 50;
        break;
    case ItemType.IronShield:
        itemCost = 100;
        break;
    case ItemType.LeatherBoots:
        itemCost = 40;
        break;
    case ItemType.MagicCape:
        itemCost = 250;
        break;
}

// 買えるかどうかを確認
if (itemCost <= playerMoney)
{
    Debug.Log("購入可能！");
}
else
{
    Debug.Log("お金不足～");
}
    
```

</details>

# 繰り返し

## 決まられた回数を繰り返す命令「for」

[記入できるファイルをダウンロード](https://class.illogic.games/attachments/10)

### 練習課題

#### C#を読みましょう

以下の表は、C#で書いた命令とその日本語の意味が書いてある。空枠を完成してください。

<table id="bkmrk-c%23-%E6%97%A5%E6%9C%AC%E8%AA%9E-for%28int-i-%3D-0" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:33.631%;"></col><col style="width:66.4882%;"></col></colgroup><thead><tr><td class="align-center">**C#**

</td><td class="align-center">**日本語**

</td></tr></thead><tbody><tr><td>```c#
for(int i = 0; i < 10; i++)
```

</td><td>「i」という変数は 0から9までの値を変えながら、10回繰り返す</td></tr><tr><td>```c#
for(int i = 1; i <= 10; i++)
```

</td><td><details><summary>答え</summary>

「i」という変数は 1から10までの値を変えながら、10回繰り返す

</details></td></tr><tr><td>```c#
for(int i = 10; i > 0; i--)
```

</td><td><details><summary>答え</summary>

「i」という変数は 10から1までの値を変えながら、10回繰り返す

</details></td></tr><tr><td>```c#
for(int i = 0; i < 15; i+=2)
```

</td><td><details><summary>答え</summary>

「i」という変数は

0, 2, 4, 6, 8, 10, 12, 14

の値を変えながら、8回繰り返す

</details></td></tr></tbody></table>

#### Unityで練習

1〜100の整数を繰り返し、表示してください。ただし…  
「3」で割れる整数の代わりに「ho」を表示  
「5」で割れる整数の代わりに「ge」を表示  
「3」と「5」両方で割れる整数の代わりに「hoge」を表示

例：  
 1, 2, ho, 4, ge, ho, 7, 8, ho, ge, 11, ho, 13, 14, hoge, 16, 17, ho …

**<span style="text-decoration:underline;">ヒント</span>**

「余り」演算子（モジュロ、剰余演算子）を使ってください。余りの演算子は整数の割り算の余りを返す：

```c#
int a = 4 % 3;   // a は 1 になる 
int b = 6 % 3;   // b は 0 になる
int c = 12 % 5;  // c は 2 になる 
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-1%EF%BD%9E100%E7%B9%B0%E3%82%8A%E8%BF%94%E3%81%99-for%28"><summary>答え</summary>

```c#
// 1～100繰り返す
for(int i = 1; i <= 100; i++)
{
    // 3 と 5 のあまりを計算し、0 である場合は、
    // その数値で割れることである。
    bool div3 = i % 3 == 0;
    bool div5 = i % 5 == 0;

    // 両方で割れる？
    if (div3 && div5)
    {
        Debug.Log("hoge");
    }
    // 3で割れる？
    else if (div3)
    {
        Debug.Log("ho");
    }  
    // 5で割れる？
    else if (div5)
    {
        Debug.Log("ge");
    }  
    // その他
    else
    {
        Debug.Log($"{i}");
    }
}
```

</details>## 回数が決まっていない繰り返す命令「while」

for文は決まった回数（例：0～10）を繰り返す命令であるが、場合により、回数が決まっていなく、何かの条件を満たしている間には繰り返す場合もある：

 例：体力残っていたら→遊び続ける  
 例：時間切れになっていなければ→遊び続ける  
 例：敵がプレーヤーを捕まっていなければ→追いかける

**<span style="text-decoration:underline;">書式：</span>**

```c#
while(繰り返し条件)
{
    繰り返したい処理
}
```

例えば、サイコロは「6」になるまで繰り返すを書くとしたら：

```c#
int dice = 0;
while (dice != 6)
{
    // Random.RangeはUnityの機能であり、乱数を生成する
    dice = Random.Range(1, 7);  // 1〜6の間の乱数を生成（7未満）
    Debug.Log($"サイコロの値：{dice}");
}
Debug.Log("終了");
```

上記の例で、回数が決まっていなくて、サイコロは6以外だったら繰り返す処理である。

### 練習課題

以下のスクリプトでwhileを使い、完成してください（UnityでもOK）

```c#
// 体力
int playerHP = 100;

// プレーヤーが生きていたら、繰り返す
________________________
{
    Debug.Log($"現在の体力 {playerHP}");
    int damage = 30;      
    playerHP -= damage;  // 体力を減らす
}

Debug.Log("ゲームオーバー");
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E4%BD%93%E5%8A%9B-int-playerh"><summary>答え</summary>

```c#
// 体力
int playerHP = 100;

// プレーヤーが生きていたら、繰り返す
while(playerHP > 0)
{
    Debug.Log($"現在の体力 {playerHP}");
    int damage = 30;      
    playerHP -= damage;  // 体力を減らす
}

Debug.Log("ゲームオーバー");
```

</details>このプログラムはコンソールで何を表示するか？その出力を書いてください：

<table id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:99.881%;"></col></colgroup><tbody><tr><td><details><summary>答え</summary>

現在の体力 100

現在の体力 70

現在の体力 40

現在の体力 10

</details></td></tr></tbody></table>

# 配列

## 練習課題

[記入できるファイルをダウンロード](https://class.illogic.games/attachments/11)

### C#を読みましょう

以下の表は、C#で書いた命令とその日本語の意味が書いてある。空枠を完成してください。

<table id="bkmrk-c%23-%E6%97%A5%E6%9C%AC%E8%AA%9E-int-%5B%5D-number" style="border-collapse:collapse;width:100%;height:429.7px;"><colgroup><col style="width:43.1477%;"></col><col style="width:56.8523%;"></col></colgroup><thead><tr style="height:29.8px;"><td class="align-center" style="height:29.8px;">**C#**

</td><td class="align-center" style="height:29.8px;">**日本語**</td></tr></thead><tbody><tr style="height:66.2px;"><td style="height:66.2px;">```c#
int [] numbers = new int[10]
```

</td><td style="height:66.2px;">10個の整数が入る「numbers」という配列を作成</td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
int [] numbers;
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

整数型の配列を宣言のみ（初期化なし）

</details></td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
string [] names = new string[5];
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

5個の文字列が入る「names」という配列を作成

</details></td></tr><tr style="height:59.3px;"><td style="height:59.3px;"><details><summary>答え</summary>

```c#
names[0] = "たろう";
```

</details></td><td style="height:59.3px;">「names」配列の一番最初（先頭）は「たろう」にする</td></tr><tr style="height:16.5px;"><td style="height:16.5px;"><details><summary>答え</summary>

```c#
names[4] = "おおはら";
```

</details></td><td style="height:16.5px;">「names」配列の一番最後（後尾）は「おおはら」にする</td></tr><tr style="height:66.2px;"><td style="height:66.2px;">```c#
int a = numbers[3];
```

</td><td style="height:66.2px;"><details><summary>答え</summary>

配列「numbers」の先頭から４つ目の要素を変数「a」の中に代入

</details></td></tr><tr style="height:59.3px;"><td style="height:59.3px;"><details><summary>答え</summary>

```c#
float [] distances = new float[3];
distances[0] = 1.3f;
distances[1] = 4.5f;
distances[2] = 7.9f;

// または
float [] distances = 
   new float[3] { 1.3f, 4.5f, 7.9f };
```

</details></td><td style="height:59.3px;">少数型の配列「distances」を宣言し、1.3f, 4.5f, 7.9f の３つの数値で初期化する</td></tr></tbody></table>

### C#の処理を完成してみましょう

１．配列とfor文を使い、以下のスクリプトを完成してください（UnityでもOK）  
 ※：文字列の長さは「変数名.Length」で求めることができる  
 例：

```c#
string s = "Hello!";
int size = s.Length; // 文字列「s」の長さを求める
Debug.Log(size); // 6 を表示する
```

 ※：期待の結果は「最も長いフルーツ名は: grapefruit」

```c#
// フルーツの名前の配列
string [] fruits = {"lemon", "mikan", "orange", "grapefruit", "kiwi"};

// 最も長い文字列（結果）
string maxFruit = "";

// フルーツ1個ずつ確認
for (________; _________; ________)
{
    // i番目のフルーツを求める
    string f = _______________;

    // もし、今回のフルーツ名の方が長ければ
    if (f.Length > maxFruit.Length)
    {
        // 最も長いフルーツを更新
        ___________________;
    }
}

// 最大の長さのフルーツ名を表示
Debug.Log($"最も長いフルーツ名は: {______________}");
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%83%95%E3%83%AB%E3%83%BC%E3%83%84%E3%81%AE%E5%90%8D%E5%89%8D%E3%81%AE%E9%85%8D%E5%88%97-str"><summary>答え</summary>

```c#
// フルーツの名前の配列
string [] fruits = {"lemon", "mikan", "orange", "grapefruit", "kiwi"};

// 最も長い文字列（結果）
string maxFruit = "";

// フルーツ1個ずつ確認
for (int i = 0; i < 5; i++)
{
    // i番目のフルーツを求める
    string f = fruits[i];

    // もし、今回のフルーツ名の方が長ければ
    if (f.Length > maxFruit.Length)
    {
        // 最も長いフルーツを更新
        maxFruit = f;
    }
}

// 最大の長さのフルーツ名を表示
Debug.Log($"最も長いフルーツ名は: {maxFruit}");
```

</details>２．配列とfor文を使い、以下のスクリプトを完成してください（UnityでもOK）

```c#
// 4人分のスコア（整数型）の配列を準備してください
_____ scores = ___________;

//１人目のスコアは100点
__________= 100;

//２人目のスコアは80点
__________= 80;

//３人目のスコアは180点
__________= 180;

//４人目のスコアは20点
__________= 20;

// 同様に、4人分の名前（文字列型）の配列を準備してください
// それぞれの名前は「太郎」「さくら」「オオハラ」「Unity」

______ names = __________;
_______________;
_______________;
_______________;
_______________;

// for文を使って一人ずつのプレーヤーとスコアを表示する
for (________; _________; ________)
{
    Debug.Log($"名前：{________} → {_________}");
}
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-4%E4%BA%BA%E5%88%86%E3%81%AE%E3%82%B9%E3%82%B3%E3%82%A2%EF%BC%88%E6%95%B4%E6%95%B0%E5%9E%8B%EF%BC%89%E3%81%AE%E9%85%8D"><summary>答え</summary>

```c#
// 4人分のスコア（整数型）の配列を準備してください
int[] scores = int[4];

//１人目のスコアは100点
scores[0] = 100;

//２人目のスコアは80点
scores[1] = 80;

//３人目のスコアは180点
scores[2] = 180;

//４人目のスコアは20点
scores[3] = 20;

// 同様に、4人分の名前（文字列型）の配列を準備してください
// それぞれの名前は「太郎」「さくら」「オオハラ」「Unity」

string[] names = string[4];
names[0] = "太郎";
names[1] = "さくら";
names[2] = "オオハラ";
names[3] = "Unity";

// for文を使って一人ずつのプレーヤーとスコアを表示する
for (int i = 0; i < 4; i++)
{
    Debug.Log($"名前：{names[i]} → {score[i]}");
}
```

</details>## 自由に伸びる配列 : List

 配列を作るときに、事前にサイズを決めないといけないが、場合により、サイズが分からない可能性がある。例えば、同じゲームでも、プレーヤーによって拾うアイテムの数が変わるので、事前にアイテムの配列のサイズが分からない。

 その場合は、サイズが自動的に変わる「リスト」を使うと便利。「List」は、要素を増やすほど、段々サイズが伸びる"配列"（正しい名称は「コレクション」）である。

 便利であるが、弱点もある：リストは配列と比べて処理が遅い。数十～数百の要素以内だったら、あまり違いがないが、要素を増やすほど（数万程度）、Listの方が明らかに遅い。

### Listの宣言、使い方

<table id="bkmrk-%E5%AE%A3%E8%A8%80-list%3C%E5%9E%8B%3E-%E5%A4%89%E6%95%B0%E5%90%8D%3B-%E4%BB%A3%E5%85%A5%EF%BC%88%E4%BD%9C" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:16.012%;"></col><col style="width:84.1072%;"></col></colgroup><tbody><tr><td>宣言</td><td>```c#
List<型> 変数名;
```

</td></tr><tr><td>代入（作成）</td><td>```c#
変数名 = new List<型>();
```

</td></tr></tbody></table>

例：

```c#
// 名前のリストを作成
List<string> names = new List<string>();

// リストに名前を追加する
names.Add("たろう");
names.Add("さくら");
names.Add("おおはら");

// 0番目の名前を表示（配列と同じ）
Debug.Log(names[0]); // 「たろう」を表示

// 要らなくなった場合、リストから削除できる
names.Remove("たろう");

// 0番目の名前を表示（配列と同じ）
Debug.Log(names[0]); // 「さくら」を表示
```

### 練習

プレーヤーのスコアを表示するスクリプトを配列からリストに書き換える

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%82%B9%E3%82%B3%E3%82%A2%EF%BC%88%E6%95%B4%E6%95%B0%E5%9E%8B%EF%BC%89%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88%E3%82%92%E6%BA%96"><summary>答え</summary>

```c#
// スコア（整数型）のリストを準備してください
List<int> scores = new List<int>();

//１人目のスコアは100点
scores.Add(100);

//２人目のスコアは80点
scores.Add(80);

//３人目のスコアは180点
scores.Add(180);

//４人目のスコアは20点
scores.Add(20);

// 同様に、4人分の名前（文字列型）の配列を準備してください
// それぞれの名前は「太郎」「さくら」「オオハラ」「Unity」
List<string> names = new List<string>();
names.Add("太郎");
names.Add("さくら");
names.Add("オオハラ");
names.Add("Unity");

// for文を使って一人ずつのプレーヤーとスコアを表示する
for (int i = 0; i < 4; i++)
{
    Debug.Log($"名前：{names[i]} → {score[i]}");
}
```

</details>## 配列・リスト専用の繰り返し命令 : foreach

「for」を使って配列をループする方法を見てきた。変数を使って、インデックスを0から配列の最後まで一つずつ繰り返す。例えば：

```c#
string [] names = string[4] { "アリス", "ボブ", "チャーリー", "ジョン" };
for (int i= 0; i < 4; i++)
{
  string n = names[i]
  Debug.Log(n);
}
```

C#では、配列やリストをもっと簡単にループする方法がある。「`foreach`」（フォー・イーチ）を使うと、インデックス用の変数を用意しなくても、リストの各要素を順番に取り出すことができる。先ほどの例はこうなる：

```c#
string [] names = string[4] { "アリス", "ボブ", "チャーリー", "ジョン" };
foreach(string n in names)
{
  Debug.Log(n);
}
```

ただし、注意点が二つある。

1. `foreach`は常に要素を一つずつ順番に処理する。一部の要素をスキップしたい場合は、通常の`for`ループを使う必要がある。
2. `foreach`は読み取り専用である。リストや配列の要素を変更したい場合も、通常の`for`ループを使う必要がある。

### 練習

最も長いフルーツの名前を求めるスクリプトを更新し、`for`から`foreach`に書き換える

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%83%95%E3%83%AB%E3%83%BC%E3%83%84%E3%81%AE%E5%90%8D%E5%89%8D%E3%81%AE%E9%85%8D%E5%88%97-str-1"><summary>答え</summary>

```c#
// フルーツの名前の配列
string [] fruits = ["lemon", "mikan", "orange", "grapefruit", "kiwi"];

// 最も長い文字列（結果）
string maxFruit = "";

// フルーツ1個ずつ確認
foreach(string f in fruits)
{
    // もし、今回のフルーツ名の方が長ければ
    if (f.Length > maxFruit.Length)
    {
        // 最も長いフルーツを更新
        maxFruit = f;
    }
}

// 最大の長さのフルーツ名を表示
Debug.Log($"最も長いフルーツ名は: {maxFruit}");
```

</details>

# メソッド

## 練習問題

### C#を読みましょう

```c#
int Sum(int a, int b)
{
    return a + b;
}
```

説明：

<table id="bkmrk-%EF%BC%92%E3%81%A4%E3%81%AE%E6%95%B4%E6%95%B0%EF%BC%88a%E3%81%A8b%EF%BC%89%E3%82%92%E8%B6%B3%E3%81%97%E3%81%A6%E3%80%81%E3%81%9D%E3%81%AE%E7%B5%90%E6%9E%9C%E3%82%92" style="border-collapse:collapse;width:100%;"><tbody><tr><td>２つの整数（aとb）を足して、その結果を整数として返す</td></tr></tbody></table>

```c#
int Max(int a, int b)
{
    if (a > b)
        return a;
    else
        return b;
}
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%EF%BC%92%E3%81%A4%E3%81%AE%E6%95%B4%E6%95%B0%EF%BC%88a%E3%81%A8b%EF%BC%89%E3%81%AE%E6%9C%80%E3%82%82%E5%A4%A7%E3%81%8D%E3%81%84%E6%95%B0"><summary>答え</summary>

２つの整数（aとb）の最も大きい数値（最大値）を返す

</details>```c#
bool CheckHasItem(string[] itemList, string item)
{
    for (int i = 0; i < itemList.Length; i++)
    {
        if (itemList[i] == item)
            return true;
    }
    return false;
}
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%E3%80%8Citemlist%E3%80%8D%E9%85%8D%E5%88%97%E3%81%AE%E4%B8%AD%E3%81%AB%E3%80%81%E3%80%8C"><summary>答え</summary>

「itemList」配列の中に、「item」という文字列が入っているかどうかを確認し、あったら「true」を返し、なければ、「false」を返す。つまり、アイテム存在しているかどうかを確認。

</details>### Unityで練習

１．配列で作った「[最も長いフルーツ](https://class.illogic.games/books/c/page/0353a#bkmrk-c%23%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E5%AE%8C%E6%88%90%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%82%87%E3%81%86)」のスクリプトを更新し、「`FindLongString`」というメソッドにしよう。配列を引数として渡し、最も長い文字列を返すようにてください。

使い方の例：

```c#
void Start()
{
    string [] fruits = {"lemon", "mikan", "orange", "grapefruit", "kiwi"};

    // このメソッドを作ってください
    string maxFruit = FindLongString(fruits);　  

    // grapefruitを表示されるはず
    Debug.Log($"最も長いフルーツ名は: {maxFruit}");
}

// ここからメソッドを作る...
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E6%9C%80%E3%82%82%E9%95%B7%E3%81%84%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E6%8E%A2%E7%B4%A2-str"><summary>答え</summary>

```c#
// 最も長い文字列を探索
string FindLongString (string [] fruits)
{
  　// 最も長い文字列
    string maxFruit = "";
    
    // フルーツ1個ずつ確認
    foreach(string f in fruits)
    {
        // もし、今回のフルーツ名の方が長ければ
        if (f.Length > maxFruit.Length)
        {
            // 最も長いフルーツを更新
            maxFruit = f;
        }
    }

  　// 結果を返す
    return maxFruit;
}
```

</details>---

２．「じゃんけん」ゲーム結果の判定メソッド「`CheckJanken`」を作成してみてください。

 前提条件：

- グーは「0」、チョキは「1」、パーは「2」として表現する
- グー、チョキ、パー（0, 1, 2）以外の数値入れたら、エラーを返す
- プレーヤーは２人（AとB）
- 判定の結果は：Aの勝ち：1、Bの勝ち：２、ひきわけ：0、エラー：-1
- メソッド名：`CheckJanken`
    - 引数：各プレーヤーの選択肢
    - 戻り値：判定の結果

使い方の例１（Aの勝ち）

```c#
void Start()
{
  int playerA = 1; // チョキ
  int playerB = 2; // パー
  int result = CheckJanken(playerA, playerB);　// 1を返す（Aの勝ち）
  Debug.Log (result)
}
```

使い方の例２（Bの勝ち）

```c#
void Start()
{
  int playerA = 0; // グー
  int playerB = 2; // パー
  int result = CheckJanken(playerA, playerB);　// 2を返す（Bの勝ち）
  Debug.Log(result);
}
```

使い方の例３（あいこ）

```c#
void Start()
{
  int playerA = 2; // パー
  int playerB = 2; // パー
  int result = CheckJanken(playerA, playerB);　// 0を返す（あいこ）
  Debug.Log(result);
}
```

使い方の例４（エラー）

```c#
void Start()
{
  int playerA = 4; // ???
  int playerB = 2; // パー
  int result = CheckJanken(playerA, playerB);　// -1を返す（エラー）
  Debug.Log(result);
}
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%81%98%E3%82%83%E3%82%93%E3%81%91%E3%82%93%E3%81%AE%E7%B5%90%E6%9E%9C%E3%81%AE%E5%88%A4%E5%AE%9A%E3%82%92%E6%B1%82%E3%82%81"><summary>答え</summary>

```c#
// じゃんけんの結果の判定を求める
// playerA: プレーヤーAの選択肢（0:グ, 1:チョキ, 2:パー)
// playerB: プレーヤーBの選択肢（0:グ, 1:チョキ, 2:パー)
// 戻り値：
//  -1：エラー（無効な選択肢)
//   0：あいこ
//   1：プレーヤーAの勝ち
//   2：プレーヤーAの勝ち
int CheckJanken (int playerA, int playerB)
{
    // エラーを確認（プレーヤーA）
    if (playerA < 0 || playerA > 2)
    {
        return -1;
    }
  　// エラーを確認（プレーヤーB）
    if (playerB < 0 || playerB > 2)
    {
        return -1;
    }
    
    // あいこ
    if (playerA == playerB)
    {
        return 0;
    }
    
    // プレーヤーAの勝ち
    if ((playerA == 0 && playerB == 1) || (playerA == 1 && playerB == 2) || (playerA == 2 && playerB == 0))
    {
        return 1;
    }
    
    // プレーヤーBの勝ちしかのこらない！
    return 2;
}
```

</details>

# クラス

## C#の純粋クラス vs MonoBehaviour

お気づきかもしれないが、通常のC#クラスとUnityの「`MonoBehaviour`」クラスにはいくつかの違いがある。基本的に、どちらのクラスもプロパティ（クラス変数）とメソッドを持てる。しかし、大きな違いもある。

1. 通常のC#クラスはUnityエディターでは使用できない。GameObjectにアタッチできるのは`MonoBehaviour`のみである。
2. 通常のC#クラスは`new`キーワードを使ってインスタンス化するが、`MonoBehaviour`は直接インスタンス化できない。

<table id="bkmrk-%E9%80%9A%E5%B8%B8%E3%81%AEc%23%E3%82%AF%E3%83%A9%E3%82%B9-monobehavio" style="border-collapse:collapse;width:100%;height:517.834px;"><colgroup><col style="width:50%;"></col><col style="width:50%;"></col></colgroup><thead><tr style="height:29.8px;"><td class="align-center" style="height:29.8px;">**通常のC#クラス**</td><td class="align-center" style="height:29.8px;">**MonoBehaviour**</td></tr></thead><tbody><tr><td>一般 C# のものであり、Unity 以外でも使える

</td><td>Unity専用のキーワードである（Unity以外に使えない）

</td></tr><tr style="height:158.567px;"><td style="height:158.567px;">「`: MonoBehaviour`」がつかない

```c#
class Player
{
  // メンバー変数とメソッド
}
```

</td><td style="height:158.567px;">「`: MonoBehaviour`」がつく

```c#
class Enemy : MonoBehaviour
{
  // メンバー変数とメソッド
}
```

</td></tr><tr style="height:120.167px;"><td style="height:120.167px;">`new` をつかい、クラスからインスタンスを作成

```c#
// クラスから具体的に使える「p1」のプレーヤーを作成
Player p1 = new Player(); 
```

</td><td style="height:120.167px;">`new` を使えない

```c#
Enemy e = new Enemy(); // エラーが発生する
```

</td></tr><tr style="height:209.3px;"><td style="height:209.3px;">UnityでGameObjectにアタッチ不可

[![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/spTimage.png)](https://class.illogic.games/uploads/images/gallery/2026-04/spTimage.png)

</td><td style="height:209.3px;">UnityでGameObjectにアタッチ可能

[![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/image.png)](https://class.illogic.games/uploads/images/gallery/2026-04/image.png)

</td></tr></tbody></table>

### どれを使う？

では、どちらをいつ使うべきか？基本的な目安として、GameObjectに機能を追加したい場合は`MonoBehaviour`を使う。例えば、プレイヤーの入力に基づいてGameObjectを制御したい場合や、画面上のスコアを更新したい場合は、その処理に専念する`MonoBehaviour`を作ればよい。

ゲーム内で通常表示されない内部処理にはC#クラスを使うパターンはよくある。例えば、プレイヤーのインベントリを管理するC#クラスや、ファイルのセーブ・ロードを制御するC#クラスを作ることができる。

## アクセス修飾子

基本的な目安として、データを保護しクラスの外部から誤って値を変更しないよう、クラスのメンバー変数は常に「`private`」に設定する。

クラスの外部から値にアクセスする必要がある場合は、`public`メソッドまたは`public`ゲッター（下記の例を参照）を使うことができる。

`MonoBehaviour`の場合、Unityがエディターで変数を変更できるようにする必要がある。これは変数を`private`のままにし、変数に`[SerializeField]`を追加することで実現できる。

- <span style="text-decoration:underline;">やりたいこと</span>：Unityにある数値を公開し、エディター（Inspector）で編集できるようにしたい 例：車の速度

<table id="bkmrk-ng-%E6%AD%A3%E3%81%97%E3%81%84%E6%96%B9%E6%B3%95-%E4%B8%8A%E8%A8%98%E3%81%AE%E4%BE%8B%E3%81%A8%E5%90%8C%E6%A7%98%E3%81%AB%E3%80%81un" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center">**NG**</td><td class="align-center">**正しい方法**</td></tr></thead><tbody><tr><td>上記の例と同様に、Unityに限らず、どこからも編集できる変数なので、大変危ない！

```c#
class Car : MonoBehaviour
{
  　// 車の速度をUnityから編集したいため、publicにした！
    public int Speed; 
}
```

</td><td>`private`にし、`[SerializeField]` をつければ良い。

```c#
class Car : MonoBehaviour
{
  　// UnityのInspectorから変えることができるが、
    // 他のクラスからアクセス不可
    [SerializeField]
    private int speed; 
}
```

</td></tr></tbody></table>

- <span style="text-decoration:underline;">やりたいこと</span>：ある数値を別のクラスで読みたい。  
     例：プレーヤーを持っているお金

<table id="bkmrk-ng-%E6%AD%A3%E3%81%97%E3%81%84%E6%96%B9%E6%B3%95-public%EF%BC%88%E5%85%AC%E9%96%8B%EF%BC%89%E3%81%AB" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center">**NG**</td><td class="align-center">**正しい方法**</td></tr></thead><tbody><tr><td>public（公開）にすると、Player以外からアクセスでき、誤って数値を消したり可能性があるので、「public」を避けよう。

```c#
class Player
{
  　// これを避けましょう！
    public int Money; 
}
```

</td><td>１．まず、メンバー変数を非公開にし（`private`）、メソッドで取得。

```c#
class Player
{
  　// privateで変数を保護
    private int money;

  　// メソッドで数値を返し、外から代入できない
    public int GetMoney()
    {
        return money;
    }
}
```

２．もう少し賢い方法は、「ゲッター」を使うこと：

```c#
class Player
{
  　// Moneyというメンバー変数は：
    //「get」（取得）は公開である
    //「set」（代入）は非公開である
    public int Money { get; private set; }
}
```

</td></tr></tbody></table>

- <span style="text-decoration:underline;">やりたいこと</span>：ある数値を別のクラスで更新した。  
     例：プレーヤーの体力。

<table id="bkmrk-ng-%E6%AD%A3%E3%81%97%E3%81%84%E6%96%B9%E6%B3%95-%E3%81%93%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AF%E3%80%81%E6%94%BB%E6%92%83%E3%82%84%E5%9B%9E%E5%BE%A9" style="border-collapse:collapse;width:100%;"><colgroup><col style="width:50.0596%;"></col><col style="width:50.0596%;"></col></colgroup><thead><tr><td class="align-center">**NG**</td><td class="align-center">**正しい方法**</td></tr></thead><tbody><tr><td>この場合は、攻撃や回復アイテムで現在の体力の数値を別のクラスから変えたい場合もあると思い、「public」にした。

```c#
class PlayerHP : MonoBehaviour
{
    // 最大体力はUnityで調整できるようにする
    [SerializeField]
    private int maxHP;
  
  　// 当然、攻撃などで、現在の体力を外からでも変えたい
    public int nowHP; 
}
```

ただ、ここは大きなお落とし穴がある。次の例を考えてください：

・最大耐力 `maxHP `は 120 に設定にした

・現在の体力 `nowHP `は 50 である

・回復アイテムを使用し、+100を回復

とすると、`nowHP + 100 = 150` であり、最大体力を超えてしまう！

同様に 80 の攻撃を受け取るとしたら：`nowHP - 80 = -30 `

マイナス体力になってしまった！

</td><td>１．まず、メンバー変数を非公開にし（`private`）、代入の取得のメソッドを作成。

```c#
class PlayerHP : MonoBehaviour
{
    // 最大体力はUnityで調整できるようにする
    [SerializeField]
    private int maxHP;
  
  　// 体力を保護する
    private int nowHP; 

    // 読み込む専用
    public int GetHP() 
    {
        return nowHP;
    }

    // 書き込む専用
    public int SetHP(int value)
    {
        // 数値の制限を確認
        // Mathf.Min は 2つの引数の最小値を返す
        nowHP = Mathf.Min(value, maxHP); 
        
        // Mathf.Max は 2つの引数の最大値を返す
        nowHP = Mathf.Max(value, 0); 
    }
}
```

これで、SetHPでは、体力が必ず `0 ～ maxHP`の間になることを保証できる。

２．もう少し賢い方法は、「ゲッター」と「セッター」を使うこと：

```c#
class PlayerHP : MonoBehaviour
{
    // 最大体力はUnityで調整できるようにする
    [SerializeField]
    private int maxHP;
  
  　// 非公開で中身を守る
    private int nowHP;

    // 公開ゲッターとセッター
    public int NowHP
    {
        // 取得
        get { return nowHP; } 

        // 代入
        set { 
          nowHP = Mathf.Min(value, maxHP);
          nowHP = Mathf.Max(value, 0);
        }
    }
}
```

</td></tr></tbody></table>

## 練習課題

単純なインベントリを作成してみましょう：

- アイテムを表すクラスを作る（ファイル名：`Item`） 
    - アイテム名を代入と取得できるようにする
    - 数も代入と取得できるようにする
    - 使用例

```c#
Item coin = new Item();
coin.Name = "コイン";
coin.Count = 20;
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E4%BD%95%E3%81%8B%E3%81%AE%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%82%92%E8%A1%A8%E3%81%99%E3%82%AF%E3%83%A9%E3%82%B9-"><summary>答え</summary>

```c#
// 何かのアイテムを表すクラス
class Item
{
    // アイテム名（非公開）
    private string name;
    
    // アイテムの数（非公開）
    private int count;

    // アイテム名（公開）
    public string Name { 
        get { return name }
        set { name = value; }
    }
    
    // アイテムの数（公開）
    public string Count { 
        get { return count }        

        // マイナスアイテムは無意味なので、必ず0以上にする
        set { name = Mathf.Max(0, count); } 
    }    
}
```

</details>- アイテムを管理する「`Inventory`」クラスを作成（ファイル名：`Inventory`） 
    - アイテムを何個も追加できるようにする（ヒント：[自由に伸びる配列](https://class.illogic.games/books/c/page/0353a#bkmrk-%E8%87%AA%E7%94%B1%E3%81%AB%E4%BC%B8%E3%81%B3%E3%82%8B%E9%85%8D%E5%88%97-%3A-list)！）
    - 中身のすべてを確認できるようにする
    - 使用例

```c#
Inventory inv = new Inventory();
inv.Add(coin); // 先作ったコインを追加
inv.Print();   // Debug.Logで中身を表示する：「コイン：20」
```

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%82%92%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B-clas"><summary>答え</summary>

```c#
// アイテムを管理する
class Inventory
{
    // アイテムのリスト
    private List<Item> items = new List<Item>();
    
    // 追加メソッド
    public void Add(Item item)
    {
        items.Add(item);
    }
    
    // 表示メソッド
    public void Print()
    {
        foreach(Item i in items)
        {
            Debug.Log($"{i.Name} : {i.Count}");
        }
    }    
}
```

</details>- テスト用のスクリプトを作成（ファイル名：`RunTest`） 
    - コイン20個を作成し、インベントリに追加
    - ポーション２個を作成し、インベントリに追加
    - ナイフ１個を作成し、インベントリに追加
    - インベントリの中身を表示

<details id="bkmrk-%E7%AD%94%E3%81%88-%2F%2F-%E7%A2%BA%E8%AA%8D%E7%94%A8%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88-clas"><summary>答え</summary>

```c#
// 確認用のスクリプト
class RunTest : MonoBehaviour
{
    void Start()
    {
        Item coin = new Item();
        coin.Name = "コイン";
        coin.Count = 20;
        
        Item potion = new Item();
        potion.Name = "ポーション";
        potion.Count = 2;
        
        Item knife = new Item();
        knife.Name = "ナイフ";
        knife.Count = 1;
        
        Inventory inv = new Inventory();
        inv.Add(coin);
        inv.Add(potion);
        inv.Add(knife);
        
        inv.Print();        
    }
}
```

</details>

# 総合練習

変数、条件分岐、配列（またはリスト）、列挙、メソッドとクラスを使い、以下のスクリプト作りましょう

## ポーカー手札の判定

参考：[ポーカー・ハンドの一覧](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%BC%E3%82%AB%E3%83%BC%E3%83%BB%E3%83%8F%E3%83%B3%E3%83%89%E3%81%AE%E4%B8%80%E8%A6%A7)

### 目標

手札にある５枚のカードを確認し、評価し、Debug.Logで判定を表示。

例：A♥ A♦ 10♣ 7♦ 3♠ - ワンペア

を表示するのは目標である

### 解析

かなり大きな課題なので、わかりやすい「ミニ課題」に分割しましょう！

#### スート

スートは「ハート（Heart）、ダイヤ（Diamond）、クラブ（Club）、スペード（Spade）」のことである。固定である値なので、[列挙](https://class.illogic.games/books/c/page/f7177#bkmrk-%C2%A0)として表現できるので、「`CardSuit`」の列挙を作る：

<details id="bkmrk-cardsuit%E5%88%97%E6%8C%99%EF%BC%88%E7%AD%94%E3%81%88%EF%BC%89-%2F%2F-%E3%82%AB%E3%83%BC"><summary>CardSuit列挙（答え）</summary>

```c#
// カードのスート（列挙）を宣言
public enum CardSuit
{
	Heart,
	Spade,
	Diamond,
	Club,
}
```

</details>#### カード

カードはスートと数値を持っているし、最後に表示しないといけないので、カードから文字列に変換できるメソッドがほしい。  
 ※ ポイント：数値は１～１３まで確保しましょう。

<details id="bkmrk-card%E3%82%AF%E3%83%A9%E3%82%B9%EF%BC%88%E7%AD%94%E3%81%88%EF%BC%89-using-un"><summary>Cardクラス - メンバー変数（答え）</summary>

```c#
// MonoBehaviour（Unityのクラス）ではないので
public class Card
{
	// カードの数字
	private int number;

	// カードのスート
	private CardSuit suit;

	// カードの数字
	public int Number
	{
		get { return number; }
		set
		{
			// Mathf.Clampは最小値と最大値の制限をかける
			number = Mathf.Clamp(value, 1, 13);
		}
	}

	// カードのスート
	public CardSuit Suit
	{
		get { return suit; }
		set { suit = value; }
	}
}
```

</details>##### 文字列にする

文字列にするとき「１，１１、１２、１３」は「Ａ、Ｊ、Ｑ、Ｋ」にする。

```c#
// 文字列にするメソッド
public string ConvertToString()
{
}
```

<details id="bkmrk-card%E3%82%AF%E3%83%A9%E3%82%B9---converttos"><summary>Cardクラス - ConvertToString メソッド</summary>

```c#
public class Card　//（続き）
{
	// 文字列にするメソッド
	public string ConvertToString()
	{
		string result = "";

		// 数字を文字列にする
		if (number >= 2 && number <= 10) // 2～10までの場合
		{
			result = $"{number}"; // 数字を文字列にする
		}
		else if (number == 1) // 「A」の場合
		{
			result = "A";
		}
		else if (number == 11) // 「J」の場合
		{
			result = "J";
		}
		else if (number == 12) // 「Q」の場合
		{
			result = "Q";
		}
		else // 「K」の場合
		{
			result = "K";
		}

		// 模様も文字列にして、連結する
		switch (suit) // "suit"で切り替える
		{
			case CardSuit.Heart:
				result += "♥"; // ハート
				break;
			case CardSuit.Diamond:
				result += "♦"; // ダイヤ
				break;
			case CardSuit.Club:
				result += "♣"; // クラブ
				break;
			case CardSuit.Spade:
				result += "♠"; // スペード
				break;
		}

		return result;
	}
}
```

</details>#### ハンド

ハンドはカード５枚のことである。まず、メンバー変数を考えましょう。必ず5枚になるので、伸びるリスト必要なく、ただの配列で十分。

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---setcard-%E3%83%A1%E3%82%BD"><summary>Handクラス - メンバー変数（答え）</summary>

```c#
// 手札を表すクラス（C#クラス)
public class Hand
{
    // カードの配列 
    Card[] cards = new Card[5]; // 5枚
}
```

</details>また、それぞれのカード（１枚目、２枚目、３枚目、４枚目、５枚目）の設定できるメソッドもほしい。

```c#
// カードを設定
// i: 位置（0～4）
// suit: スート
// number: 数値
public void SetCard(int i, CardSuit suit, int number)
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---setcard%E3%83%A1%E3%82%BD%E3%83%83"><summary>Handクラス - SetCardメソッド</summary>

```c#
public class Hand //（続き）
{
	// カードを設定
  　// i: 位置（0～4）
    // suit: スート
    // number: 数値
	public void SetCard(int i, CardSuit suit, int number)
	{
		// 範囲を確認
		if (i < 0 || i > 5)
		{
			Debug.Log("無効なカードの位置!");
			return; // なにもしない
		}

		// 新しいカードを作る
		Card card = new Card();
		card.Suit = suit;
		card.Number = number;
		
		// 設定
		cards[i] = card;
	}
}
```

</details>#### 評価・判定

つぎ、それぞれのハンドの役を評価しましょう。個別に対応すれば、楽になるでしょう。

##### 枚数を数える

まず、「同じ数値のカード何枚あるのか」はよく現れるパターンであるので、メソッドにしましょう：

```c#
// 同じカードの枚数を数える
// number: 数えたい数値（1〜13）
private int CountSameNumber(int number)
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---countsamen"><summary>Handクラス - CountSameNumber メソッド</summary>

```c#
// 同じカードの枚数を数える
// number: 数えたい数値（1〜13）
private int CountSameNumber(int number)
{
    // 範囲を確認
    if (number < 1 || number > 13)
    {
        Debug.Log("無効なカードの数値!");
        return 0; // なにもしない
    }
    
    int count = 0;
    foreach (Card c in cards)
    {
        if (c.Number == number)
            count++;
    }

    return count;
}
```

</details>##### ワンペア

同じ数値のカードが２枚ある？ - `CountSameNumber` を活用！

```c#
// ワンペアであるか？
private bool IsOnePair()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isonepair-"><summary>Handクラス - IsOnePair メソッド</summary>

```c#
// ワンペアであるか？
private bool IsOnePair()
{
    // いずれかの２枚のカードは同じ数値だったら、ワンペアになる
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameCard(i) == 2)
            return true;
    }
    return false;
}
```

</details>##### ツーペア

ワンペアと似ているが、１つ目のペアの数値は２つ目のペアと異なることが前提条件であるので、ご注意ください！

```c#
// ワンペアであるか？
private bool IsTwoPair()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---istwopair-"><summary>Handクラス - IsTwoPair メソッド</summary>

```c#
// ツーペアであるか？
private bool IsTwoPair()
{
    // ワンペアと似ているが、２つのペアは異なるカードじゃないとだめ
    int match = 0;  // １つ目のペアの数値
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameCard(i) == 2)
            match = i;
    }
    
    // なにも一致しなかった
    if (match == 0)
        return false;
    
    // もう一つのペアがないか確認する
    for (int i = 1; i <= 13; i++)
    {
        // ２枚がある「かつ」前のペアと異なる
        if (CountSameCard(i) == 2　&& i != match)
            return true;
    }
    
    return false;
}	
```

</details>##### スリー・オブ・ア・カインド

ワンペアと似ているが、２枚ではなく、３枚を確認すべき。

```c#
// スリー・オブ・ア・カインドであるか？
private bool IsThreeOfAKind()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isthreeofa"><summary>Handクラス - IsThreeOfAKind メソッド</summary>

```c#
// スリー・オブ・ア・カインドであるか？
private bool IsThreeOfAKind()
{
    // いずれかの３枚のカードは同じ数値だったら、 スリー・オブ・ア・カインドになる
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameCard(i) == 3)
            return 3;
    
    return false;
}	
```

</details>##### ストレート

これは新しいやつ！すべての数値が連続であることが確認すべき。

ヒント：

- まず、最も数値が小さいカードを求める
- ストレートであれば、以下は事実である： 
    - 最も小さいカード +0 → 1枚
    - 最も小さいカード +1 → 1枚
    - 最も小さいカード +2 → 1枚
    - 最も小さいカード +3 → 1枚
    - 最も小さいカード +4 → 1枚

```c#
// ストレートであるか？
private bool IsStraight()
{     
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isstraight"><summary>Handクラス - IsStraight メソッド</summary>

```c#
// ストレートであるか？
private bool IsStraight()
{
    // 連続になっているのかを確認が必要
    // 例えば: 8-9-10-J(11)-Q(12)
    
    // まず、最低のカードを求めましょう
    int smallCard = 14; // Kよりも高いから始まる
    foreach (Card c in cards)
    {
        if (c.Number < smallCard)
            smallCard = c.Number; // 最低カードを更新
    }
    
    // では、5枚も連続であれば、各カード +1 は
    // 必ず１枚ずつがあるはず
    for (int i = smallCard; i < smallCard + 5; i++)
    {
        // 1つだけ！
        if (CountSameNumber(i) != 1)
            return false;
    }
    
    // 順番に１枚ずつがあった！
    return true;

    // メモ：A-K-Q-J-10 に対応していない
    // 興味がある学生、ご自分でお試しください。		
}
```

</details>##### フラッシュ

すべてのカードが同じスートであるかを確認しましょう！

```c#
// フラッシュであるか？
private bool IsFlush()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isflush-%E3%83%A1%E3%82%BD"><summary>Handクラス - IsFlush メソッド</summary>

```c#
// フラッシュであるか？
private bool IsFlush()
{
    // すべて同じスートでであればOK
    CardSuit suit = cards[0].Suit;
    
    // 残りのを確認
    foreach(Card c in cards)
    {
        if (c.Suit != suit)
            return false;
    }
    
    return true;
}
```

</details>##### フールハウス

これはツーペアと似ているが、２枚と２枚ではなく、２枚と３枚のパターンである

```c#
// フルハウスであるか？
private bool IsFullHouse()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isfullhous"><summary>Handクラス - IsFullHouse メソッド</summary>

```c#
// フルハウスであるか？
private bool IsFullHouse()
{
    // ツーペアと似ているが、枚数は２枚と３枚になる
    int match = 0;  // １つ目のペアの数値
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameNumber(i) == 2)
            match = i;
    }
    
    // なにも一致しなかった
    if (match == 0)
        return false;
    
    // 残りの3枚を数える
    for (int i = 1; i <= 13; i++)
    {
        // ３枚がある「かつ」前のペアと異なる
        if (CountSameNumber(i) == 3　&& i != match)
            return true;
    }
    
    return false;
}
```

</details>##### フォー・オブ・ア・カインド

もうわかるでしょう～

```c#
// フルハウスであるか？
private bool IsFullHouse()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isfourofak"><summary>Handクラス - IsFourOfAKind メソッド</summary>

```c#
// フォー・オブ・ア・カインドであるか？
private bool IsFourOfAKind()
{
    // いずれかの４枚のカードは同じ数値だったら、 フォー・オブ・ア・カインドになる
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameNumber(i) == 4)
            return true;
    
    return false;
}	
```

</details>##### ストレートフラッシュ

ストレート「かつ」フラッシュである

```c#
// ストレートフラッシュであるか？
private bool IsStraightFlush()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---isstraight-1"><summary>Handクラス - IsStraightFlush メソッド</summary>

```c#
// ストレートフラッシュであるか？
private bool IsStraightFlush()
{
    // ストレート「かつ」フラッシュなので…
    return IsStraight() && IsFlush();
}
```

</details>##### 結果を表示

最後、強い→弱い順番で各判定を確認し、手札の中身とその結果をコンソールで表示しましょう：

```c#
// ハンドの判定し、表示する
public void CheckResult()
{
}
```

<details id="bkmrk-hand%E3%82%AF%E3%83%A9%E3%82%B9---checkresul"><summary>Handクラス - CheckResult メソッド</summary>

```c#
// ハンドの判定し、表示する
public void CheckResult()
{
    // まず、ハンドの文字列を構築
    string result = "";
    foreach (Card c in cards)
    {
        result += c.ConvertToString();
    }

    result += " - ";
    
    // 強い→弱い順番で評価
    if (IsStraightFlush())
    {
        result += "ストレートフラッシュ";
    }
    else if (IsFourOfAKind())
    {
        result += "フォー・オブ・ア・カインド";
    }
    else if (IsFullHouse())
    {
        result += "フルハウス";
    }
    else if (IsFlush())
    {
        result += "フラッシュ";
    }
    else if (IsStraight())
    {
        result += "ストレート";
    }
    else if (IsThreeOfAKind())
    {
        result += "スリー・オブ・ア・カインド";
    }		
    else if (IsTwoPair())
    {
        result += "ツーペア";
    }
    else if (IsOnePair())
    {
        result += "ワンペア";
    }
    else
    {
        result += "ハイカード";
    }
    
    // 最後に表示
    Debug.Log(result);
}
```

</details>### 確認用のスクリプト

いくつかのハンドを確認してみてください（[ダウンロード](https://class.illogic.games/attachments/12)）

```c#
// TestPoker.cs

using UnityEngine;

public class TestPoker : MonoBehaviour
{
    void Start()
    {
        // いろんな組み合わせを試す
        Hand hand = new Hand();

        // フールハウス
        hand.SetCard(0, CardSuit.Heart, 8);
        hand.SetCard(1, CardSuit.Club, 8);
        hand.SetCard(2, CardSuit.Diamond, 8);
        hand.SetCard(3, CardSuit.Heart, 11);
        hand.SetCard(4, CardSuit.Spade, 11);
        hand.CheckResult();
        
        // ストレート
        hand.SetCard(0, CardSuit.Heart, 5);
        hand.SetCard(1, CardSuit.Club, 7);
        hand.SetCard(2, CardSuit.Diamond, 8);
        hand.SetCard(3, CardSuit.Heart, 6);
        hand.SetCard(4, CardSuit.Spade, 9);
        hand.CheckResult();

        // ストレートフラッシュ
        hand.SetCard(0, CardSuit.Spade, 5);
        hand.SetCard(1, CardSuit.Spade, 7);
        hand.SetCard(2, CardSuit.Spade, 8);
        hand.SetCard(3, CardSuit.Spade, 6);
        hand.SetCard(4, CardSuit.Spade, 9);
        hand.CheckResult();
        
        // ツーペア
        hand.SetCard(0, CardSuit.Heart, 5);
        hand.SetCard(1, CardSuit.Diamond, 5);
        hand.SetCard(2, CardSuit.Club, 12);
        hand.SetCard(3, CardSuit.Spade, 12);
        hand.SetCard(4, CardSuit.Diamond, 13);
        hand.CheckResult();
        
        // ハイカード
        hand.SetCard(0, CardSuit.Heart, 5);
        hand.SetCard(1, CardSuit.Diamond, 1);
        hand.SetCard(2, CardSuit.Club, 8);
        hand.SetCard(3, CardSuit.Spade, 12);
        hand.SetCard(4, CardSuit.Diamond, 9);
        hand.CheckResult();
    }
}
```

#### 期待の結果

[![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/Lmeimage.png)](https://class.illogic.games/uploads/images/gallery/2026-04/Lmeimage.png)