【ゲーム開発のためのC#入門講座・基礎学習編】最終課題にチャレンジしてみよう【#7】

1.0_C#基礎学習編

まずは一言

ここまでありがとうございました&お疲れ様でした!

え、もう最終課題なの?

はい。基礎学習編はここで終了です。

多少C#や他言語を学習したことのある人からすると「あれは学習しないの? これも学習しないの?」という疑問がいっぱい出てくるかもしれないですね。

ただ、プログラムの本当に基礎的な部分はこれまで紹介したものだけで十分です。究極的に言ってしまえば、理論上はこれまで紹介したものだけでもゲームは作れます。

もちろん、あくまで理論上は、です。これまで紹介したものだけで作ろうとすると大変過ぎて死んでしまいます。Unityを触った時にもチンプンカンプンになってしまうので「プログラミング未経験者がUnityでゲーム開発を行うためのC#学習コンテンツを提供する」という目的も達成できていません。

なので、今後も学習コンテンツは提供していきます。

ただし、これまでご紹介してきたものがC#に限らずプログラミングの基礎であることは間違いないです。特に次回以降学習していく内容はこの基礎学習編の応用にあたるものばかりです。

基礎学習編をしっかり理解できていれば、以降も継続して学習していけると思います。

この入門講座を始めるにあたり、自分の中で、

  • どこまでが本当に基礎中の基礎なのかを明確にしたい(まずはここまで覚えればいいんだ、という区切りを未経験者・初心者に持って欲しい)
  • ページ数などの都合で入門書籍等ではどうしても詰め込みがちな基礎を、緩やかなステップアップ構造で提供したい

という意図があったので、このような構成にさせてもらっています。

それでは、最終課題にぜひチャレンジ……とその前に、最終課題攻略に必要なループ処理の便利機能や小ネタをここで学習しておきましょう。

ループ処理の便利機能①break

ループ処理を使っていると、特定の条件を満たしていたらその時点でループ処理を中断したい、ということがあります。これはbreakという命令を使うことで実現できます。

public class Hello{
    public static void Main(){
        int playerHP = 5;
        while (playerHP > 0)
        {
            playerHP = playerHP - 1;
            if (playerHP == 3)
            {
                // ↓ここにbreakがあるよ!
                break;
            }
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}
出力エリア

4
ループ処理おわったよ!

変数「playerHP」が3になったらループ処理が中断されているのがわかりますね。

このようにループ処理内で「break」という命令を記述すると、そこでループ処理を中断することができます

whileループで指定した条件とは別に中断条件を組み込みたい場合や、後述の小ネタで活用できます。

ループ処理の便利機能②continue

ループ処理を使っていると、例えば特定の条件を満たす時だけループ処理をスキップしたい、ということがあります。これはcontinueという命令を使うことで実現できます。

public class Hello{
    public static void Main(){
        int playerHP = 5;
        while (playerHP > 0)
        {
            playerHP = playerHP - 1;
            if (playerHP == 3)
            {
                // ↓ここにcontinueがあるよ!
                continue;
            }
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}
出力エリア

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

変数「playerHP」が3の時だけ、以降の処理(12行目)がスキップされているのがわかりますね。

このようにループ処理内で「continue」という命令を記述すると、それ以降の処理をスキップして次のループ処理に移行することができます

例えばパーティ全員を順番にループ処理したいが、戦闘不能になっているキャラクターはスキップしたい時などに使えます。

ループ処理の小ネタ「意図的な無限ループ」

特定の条件を満たすまで実行し続けるwhileループ。条件の指定を間違えちゃうと無限ループしちゃうから気を付けて、という話をしたかと思います。

が、あえて無限ループさせることもあります

どういうこと? と疑問が湧くと思うので、まずは実例を見てみましょう。

public class Hello{
    public static void Main(){
        int playerHP = 5;
        while (true)
        {
            playerHP = playerHP - 1;
            if (playerHP <= 0)
            {
                break;
            }
            System.Console.WriteLine(playerHP);
        }
        System.Console.WriteLine("ループ処理おわったよ!");
    }
}
出力エリア

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

わざとwhileの条件に「true」を設定し、永遠に条件を満たし続けるように(無限ループするように)しています。

その上で、ループ処理内で特定条件を満たしたらループ処理を中断するように設定しています。なので、結果的に無限ループは発生せず、きちんと正常に動作するという訳です。

何でわざわざこんなことするの? というと、例えばループ処理が終了する条件がひとつじゃなかったり、複雑な条件が絡み合う場合は、whileに条件を指定するよりもループ内で中断処理を記述した方が便利なことがあるからです。

public class Hello{
    public static void Main(){
        int player1HP = 5;
        int player2HP = 2;
        while (true)
        {
            player1HP = player1HP - 1;
            if (player1HP <= 0)
            {
                break;
            }
            System.Console.Write("player1のHP:");
            System.Console.WriteLine(player1HP);
            
            player2HP = player2HP - 1;
            if (player2HP <= 0)
            {
                break;
            }
            System.Console.Write("player2のHP:");
            System.Console.WriteLine(player2HP);
        }

        System.Console.WriteLine("ループ処理おわったよ!");
        
        System.Console.Write("player1の最終的なHP:");
        System.Console.WriteLine(player1HP);
        
        System.Console.Write("player2の最終的なHP:");
        System.Console.WriteLine(player2HP);
    }
}
出力エリア

player1のHP:4
player2のHP:1
player1のHP:3
ループ処理おわったよ!
player1の最終的なHP:3
player2の最終的なHP:0

これはプレイヤーが二人いて、どちらかのHPが0になったら終了するループ処理です。

このように複数の条件や複雑な条件でループ処理を制御したい場合、whileの部分は意図的に無限ループにするということがあります。

もちろん実際には無限ループにならないよう、ループ処理内で必ず処理が中断されるように実装しなければなりません。

また、今後学習予定の方法を使えば無限ループにしなくても同じことができるようになるので、あくまで小ネタとして覚えておいてください。

最終課題

君と殴り合う戦闘シミュレーションを作ってみましょう!

下記仕様を満たすプログラムを作ってください。

仕様

・int型の変数「playerHP」(初期値25)が存在する
・int型の変数「playerAttack」(初期値10)が存在する
・int型の変数「enemyHP」(初期値50)が存在する
・int型の変数「enemyAttack」(初期値8)が存在する
・下記の処理を繰り返す(意図的な無限ループ)
 ①enemyHPからplayerAttack分の数値を引く
 ②enemyHPが0以下だったらループ処理を中断する
 ③現在のenemyHPを表示
 ④playerHPからenemyAttack分の数値を引く
 ⑤playerHPが0以下だったらループ処理を中断する
 ⑥現在のplayerHPを表示
・ループ処理終了後、
 enemyHPが0以下だった場合は出力エリアに"勝利!"と表示する。
 上記以外の場合は出力エリアに"ゲームオーバー"と表示する。
・最後に、最終的なenemyHPとplayerHPを表示

テンプレート
public class Hello{
    public static void Main(){
        // ↓ここに仕様を満たすコードを書いていこう!
        
        // ↑ここまで
    }
}

基礎学習編で学んできた下記すべての技術を活用する必要があります。

  • 数値と文字列
  • 変数と型
  • 条件分岐と比較演算子
  • ループ処理

忘れてしまっていることがあったら過去の記事を見直してみましょう。

もしどこから手を付けていいか迷ってしまった時には、上から順番にひとつずつ実装することを心掛けてみてください。それがコンピュータが実行する順番でもあります。

もちろん不明点・疑問点等あればコメントやTwitterでお声かけいただいてもOKです。

グッドファイト!(KOFアテナ風

答え合わせ

public class Hello{
    public static void Main(){
        // ↓ここに仕様を満たすコードを書いていこう!
        int playerHP = 25;
        int playerAttack = 10;
        int enemyHP = 50;
        int enemyAttack = 8;
        while (true)
        {
            enemyHP = enemyHP - playerAttack;
            if (enemyHP <= 0)
            {
                break;
            }
            System.Console.Write("enemyHP:");
            System.Console.WriteLine(enemyHP);
            
            playerHP = playerHP - enemyAttack;
            if (playerHP <= 0)
            {
                break;
            }
            System.Console.Write("playerHP:");
            System.Console.WriteLine(playerHP);
        }
        
        if (enemyHP <= 0) 
        {
            System.Console.WriteLine("勝利!");
        }
        else 
        {
            System.Console.WriteLine("ゲームオーバー");
        }
        
        System.Console.Write("最終的なenemyHP:");
        System.Console.WriteLine(enemyHP);
        
        System.Console.Write("最終的なplayerHP:");
        System.Console.WriteLine(playerHP);
        // ↑ここまで
    }
}

実行した結果、下記の結果となっていればOKです。

出力エリア

enemyHP:40
playerHP:17
enemyHP:30
playerHP:9
enemyHP:20
playerHP:1
enemyHP:10
ゲームオーバー
最終的なenemyHP:10
最終的なplayerHP:-7

せっかくなので、変数「enemyAttack」を6にしてみましょう。

有終の美、勝利の文字が出力されれば成功です。

出力エリア

enemyHP:40
playerHP:19
enemyHP:30
playerHP:13
enemyHP:20
playerHP:7
enemyHP:10
playerHP:1
勝利!
最終的なenemyHP:0
最終的なplayerHP:1

最後に

改めてお疲れ様でした!

最後に作っていただいたのはスマホなんかでよくある、プレイヤーと敵が交互に殴り合うオートバトルの雛形となります。ここに行動順だったり、スキルの選択機能だったりを追加することで、RPGの戦闘システムを作ることができます。そう考えると、これまで学習してきたことがきちんとゲーム開発に近づいていっているという手応えが感じられるのでないでしょうか。

今後は基礎学習編の発展系を学んでいき、地盤をきちんと固めてから、オブジェクト指向と呼ばれる現代プログラミングの超重要スキルを学んでいきます。なるべく挫折しないようスモールステップを心掛けていきますので、今後もお付き合いいただければ幸いです。

それでは、次は基礎拡張編でお会いしましょう!

Posted by yuumekou