【ゲーム開発のためのC#入門講座・基礎学習編】ループ処理を覚えよう【#6】

2021-12-141.0_C#基礎学習編

ループ処理って?

ループ処理とは、文字通り何度も繰り返し実行する処理のことです。

例えばドラゴンクエストのようなターン制バトルを考えてみましょう。

  1. 戦闘開始
  2. プレイヤー行動選択
  3. 敵の行動選択
  4. 行動順が早い順に選択した行動実行
  5. プレイヤーまたは敵が全滅していなければ2へ戻る
  6. プレイヤーが全滅していたらゲームオーバー、敵が全滅していたら勝利画面へ

ざっくり分けるとこんな感じでしょうか。

2~4は5の条件を満たすまで、ずっと同じことを繰り返しているんですね。こういう繰り返しの処理を実行させるためのコードをループ処理と呼びます。

ループにもいくつか種類があるのですが、今回は最も基本となるwhileループを学習していきましょう。

whileループ

whileループは、条件がtrueの間、処理を繰り返すコードです。

<構文>
while (条件)
{
    ……繰り返したい処理……
}

whileループもif文と同様、繰り返したい処理を「{}」で囲んで記述します。

それでは実際にコードを動かして確認してみましょう。

public class Hello{
    public static void Main(){
        int playerHP = 5;
        while (playerHP > 0)
        {
            playerHP = playerHP - 1;
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

これは変数「playerHP」が0より大きい間、「{}」で囲われた処理を繰り返すコードになります。

実行結果は下記の通りです。

出力エリア

4
3
2
1
0
ループ処理おわったよ!

繰り返し固定ダメージ1を受けているようなイメージですね。

それでは、ひとつずつ処理を追いかけてみましょう。

  1. playerHPに5が設定される
  2. 繰り返し条件「playerHP > 0」を満たすため、「{}」の中へ
  3. playerHPから1引いた値をplayerHPに上書き
  4. 現在のplayerHPの値を出力エリアに出力
  5. 2.へ戻る。この時、繰り返し条件を満たさない場合は「{}」の処理は行わず、その次の命令に移る
  6. 「ループ処理おわったよ!」という文字列を出力エリアに出力

きちんと3,4の処理が繰り返されていること、playerHPが0になったらループ処理をやめて次の命令実行に移っているのがわかりますね。

もし繰り返す回数が決まっていて、せいぜい4, 5回程度であれば、同じコードを直接回数分書いても同じ結果は得られます。

public class Hello{
    public static void Main(){
        int playerHP = 5;
        
        // 1回目
        playerHP = playerHP - 1;
        System.Console.WriteLine(playerHP);
        
        // 2回目
        playerHP = playerHP - 1;
        System.Console.WriteLine(playerHP);
        
        // 3回目
        playerHP = playerHP - 1;
        System.Console.WriteLine(playerHP);
        
        // 4回目
        playerHP = playerHP - 1;
        System.Console.WriteLine(playerHP);
        
        // 5回目
        playerHP = playerHP - 1;
        System.Console.WriteLine(playerHP);
        
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

ですがこれが100回、1000回となったらとてもじゃないですけどやってられないですよね。また、先程の例のように、条件次第で繰り返しの回数が変動するものや、条件がいつ満たされなくなるかわからないものは、「何度も同じコードを書いて実装する」なんて力業はできません。

whileループなら、あらゆる繰り返し処理を実現することができます。

public class Hello{
    public static void Main(){
        int playerHP = 1000; // <=例えHPが1000になっても問題なく動くよ!
        while (playerHP > 0)
        {
            playerHP = playerHP - 1;
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

見た目もとてもすっきり。便利ですね!

特にゲームは繰り返し処理の多いコンテンツです。ターン制バトルの他にも、敵が一定間隔で湧く処理やミニゲームなどでよく使うカウントダウンの表示など、何度も繰り返す処理にはループ処理が欠かせません。

また、実はUnityが用意しているゲーム制作のための基本構造(以後、フレームワークと記載)がこのループ処理になっています

Unityでプログラムを書く場合、このフレームワークを活用してコードを組んでいくことになるので、ループ処理はしっかり活用できるようになっておきましょう。

それでは、ループ処理を扱うにあたっての注意点もご紹介しておきます。

注意点①一度も実行されないこともある

whileループは最初に条件を満たすかどうかを判定し、繰り返し処理を実行するかを決めます。

つまり、最初から条件を満たしていない場合は一度も繰り返し処理は実行されません

実際に確認してみましょう。

public class Hello{
    public static void Main(){
        int playerHP = 0; // <=HPの初期値を0にしたよ!
        while (playerHP > 0)
        {
            playerHP = playerHP - 1;
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

このプログラムは下記の順で実行されるため、繰り返し処理は一度も実行されません。

  1. playerHPに0が設定される
  2. 繰り返し条件「playerHP > 0」を満たさないため、「{}」の次の命令に移る
  3. 「ループ処理おわったよ!」という文字列を出力エリアに出力

実際に実行してみてください。出力エリアには「ループ処理おわったよ!」しか表示されないはずです。

注意点②無限ループに気を付けて!

基本的にwhileループを使う時は、ループ処理内で繰り返し条件に関わる変数を操作していくことになります。

先程の例でいうとplayerHPをループ処理の中で1ずつ減らしていっているから、最終的に条件を満たさなくなり、ループ処理がきちんと終了する訳です。

ということは、もしうっかりplayerHPの減らす処理を忘れてしまっていたらどうなるでしょう?

public class Hello{
    public static void Main(){
        int playerHP = 5;
        while (playerHP > 0)
        {
            // HP減らす処理を入れておくの忘れちゃった!
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

これは永遠に条件が満たされることがないため、コンピュータはずーーーっとこの繰り返し処理を行い続けます。ゴールド・E・レクイエムもびっくり、終わりのないことが終わり状態です。

このように永遠に終わらない繰り返し処理を無限ループといいます

たぶんプログラマーなら誰もが一度は通る「やっちまった」問題です。

こうなると開発ツールがフリーズして動かせなくなったりすることもあって、対応が結構面倒臭いです。

きちんとループを抜けられるようになっているか、使う時は必ず確認するようにしましょう。

Unityでの活躍ポイント

先程もお伝えした通り、Unityというフレームワークもループ構造になっています。

せっかくなのでちょっとだけ覗いてみましょう(難しい内容なので、現時点で頑張って理解する必要はないです)。

イベント関数の実行順序 – Unity マニュアル (unity3d.com)

なんか訳わからないことがいっぱい書いてあると思いますので、スクリプトライフサイクルのフローチャートと書かれている図だけを見て欲しいです。

プログラムの処理の流れ(実行順序)を示した図のことをフローチャートといいます。

コンピュータは原則、上から順番に処理を実行していくんでしたね。だからフローチャートも上から順番に実行されるものとして表されています。ただ、よくよく見てみると右側に「↑」という矢印で、流れとは逆方向に進んで前の箇所に戻っているものがいくつかありますよね。これがループ処理を表している部分です。繰り返し実行される処理がいくつもあることが、このフローチャートからうかがえるかと思います。

このことを理解していると、実際にUnityに触れてみた時、「あれ、何でこのコード何回も実行されてしまうんだろう?」という疑問に対して「そうか、ループ処理で動いているからだ」とすぐに気づくことができるようになります。

初めてUnityに触れた時に真っ先にぶつかる問題でもあるので、頭の片隅にでも覚えておいてください。

実践演習

それでは学習したループ処理を使ってみましょう。

演習①

仕様

①変数「enemyHP」が0より大きければ②③の処理を繰り返す
②変数「enemyHP」から変数「playerAttack」を引いた値を変数「enemyHP」に上書きする。
③出力エリアに変数「enemyHP」の値を出力する
④①のループ処理終了後、出力エリアに"勝利!"と出力する

public class Hello{
    public static void Main(){
        int enemyHP = 10;
        int playerAttack = 3;
        // ↓ここにループ処理を実装しよう!
        
        // ↑ここまで
        // ↓ここにループ処理終了後の命令を実装しよう!
        
        // ↑ここまで
    }
}

演習②

下記のプログラムは無限ループするかどうか考えてみてください。

public class Hello{
    public static void Main(){
        int playerHP = 5;
        while (playerHP != 0)
        {
            playerHP = playerHP - 2;
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

答え合わせ

演習①の答え

public class Hello{
    public static void Main(){
        int enemyHP = 10;
        int playerAttack = 3;
        // ↓ここにループ処理を実装しよう!
        while (enemyHP > 0)
        {
            enemyHP = enemyHP - playerAttack;
            System.Console.WriteLine(enemyHP);
        }
        // ↑ここまで
        // ↓ここにループ処理終了後の命令を実装しよう!
        System.Console.WriteLine("勝利!");
        // ↑ここまで
    }
}

演習②の答え

無限ループします(正確にいうと無限ループにはならないのですが、実質無限ループに近い挙動になります)。

理由は変数「playerHP」の初期値が奇数(5)であるにもかかわらず2ずつ減っていくため、0になることがないからです。

  1. 5 – 2 = 3
  2. 3 – 2 = 1
  3. 1 – 2 = -1
  4. -1 – 2 = -3
  5. ……繰り返し……
public class Hello{
    public static void Main(){
        int playerHP = 5;
        // ↓条件は「0以外だったら」なので、「0」にならない限りずっと繰り返す
        while (playerHP != 0)
        {
            playerHP = playerHP - 2;
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}

まとめ

  • ループ処理とは、文字通り何度も繰り返し実行する処理のこと
  • whileループは、条件がtrueの間、処理を繰り返すコード
  • ループ処理は便利だが、最初から条件を満たしていない場合は一度も繰り返し処理は実行されないこと、条件が不一致にならない場合は無限ループが発生してしまう点に注意
  • Unityのフレームワークはループ構造になっている

それでは、今回もお疲れ様でした!

また次の記事でお会いしましょう!

Posted by yuumekou