【Visual Studio】 C#コンソールアプリで数当てゲームを作ろう

【Visual Studio】 C#コンソールアプリで数当てゲームを作ろう

目次

はじめに
学習目標
プロジェクトの作成
コードの解説
拡張版:機能を追加してみよう
追加機能の解説
まとめ

はじめに

今回は、Visual Studioを使ってC#のコンソールアプリケーションで「数当てゲーム」を作成します
このゲームは、ランダムに決定された1から100までの数字を、ユーザーが予想して当てるシンプルなゲームです
この記事では、プログラミング初心者の方でも理解できるよう、一つひとつの処理を詳しく解説していきます

学習目標

  • この記事を読み終える頃には、以下のことができるようになります
  • Visual Studioでコンソールアプリケーションプロジェクトを作成する
  • 乱数生成の仕組みを理解する
  • ユーザー入力の受け取りと検証処理を実装する
  • 条件分岐(if文)を活用した判定処理を作成する
  • ループ処理(while文)でゲームを継続させる
  • 例外処理でエラーハンドリングを行う

プロジェクトの作成

1.Visual Studioの起動とプロジェクト作成
  1. Visual Studioを起動します
  2. 「新しいプロジェクトの作成」をクリック
  3. 「コンソールアプリ」を選択(C#)
  4. プロジェクト名を「NumberGuessingGame」に設定
  5. 場所を任意のフォルダに指定
  6. 「作成」をクリック
2.初期コードの確認

プロジェクトを作成すると、Program.csファイルに以下のコードが自動生成されます

<code>csharp// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");</code>

このコードを削除して、数当てゲームのコードを記述していきます
基本版の数当てゲーム実装
まずは最もシンプルな数当てゲームを作成しましょう
以下のコードを書きます

<code>using System;

namespace NumberGuessingGame
{
    class Program
    {
        static void Main(string&#91;] args)
        {
            // ゲームの説明
            Console.WriteLine("=== 数当てゲーム ===");
            Console.WriteLine("1から100までの数字を当ててください!");
            Console.WriteLine();

            // 乱数生成器の作成
            Random random = new Random();
            int targetNumber = random.Next(1, 101); // 1から100までの乱数
            
            int attempts = 0; // 試行回数
            bool isCorrect = false; // 正解フラグ

            // ゲームのメインループ
            while (!isCorrect)
            {
                attempts++;
                Console.Write($"{attempts}回目の予想を入力してください: ");
                
                // ユーザー入力の取得
                string input = Console.ReadLine();
                
                // 入力値の数値変換
                if (int.TryParse(input, out int guess))
                {
                    // 予想と正解の比較
                    if (guess == targetNumber)
                    {
                        Console.WriteLine($"正解です!答えは {targetNumber} でした!");
                        Console.WriteLine($"{attempts} 回で正解しました!");
                        isCorrect = true;
                    }
                    else if (guess &lt; targetNumber)
                    {
                        Console.WriteLine("もっと大きい数字です。");
                    }
                    else
                    {
                        Console.WriteLine("もっと小さい数字です。");
                    }
                }
                else
                {
                    Console.WriteLine("有効な数字を入力してください。");
                    attempts--; // 無効な入力は試行回数に含めない
                }
                
                Console.WriteLine();
            }

            Console.WriteLine("ゲーム終了!何かキーを押してください。");
            Console.ReadKey();
        }
    }
}</code>

コードが書けたらデバックしてみます
デバックに成功すると数当てゲームが始まります
まずは適当な数字を入力しEnterキーを押すと入力した数字より大きいか小さいかヒントが出ます
ヒントをもとに正解の数字を当てるシンプルなゲームが出来ました

コードの解説

乱数生成部分
<code>csharp<code>Random random = new Random();
int targetNumber = random.Next(1, 101);</code></code>

Random クラス: 疑似乱数を生成するためのクラスです。
Next(1, 101): 1以上101未満(つまり1から100まで)の整数を生成します

ユーザー入力処理
<code>csharp<code>string input = Console.ReadLine();
if (int.TryParse(input, out int guess))</code></code>

Console.ReadLine(): ユーザーからの入力を文字列として受け取ります
int.TryParse(): 文字列を整数に変換を試みます。変換に成功した場合はtrueを返し、失敗した場合はfalseを返します。これにより、不正な入力に対する例外処理を安全に行えます。

条件分岐による判定
<code>csharp<code>if (guess == targetNumber)
{
    <em>// 正解処理</em>
}
else if (guess &lt; targetNumber)
{
    <em>// 数字が小さい場合</em>
}
else
{
    <em>// 数字が大きい場合</em>
}</code></code>

この三段階の条件分岐により、ユーザーの予想に対して適切なヒントを提供します

拡張版:機能を追加してみよう

基本版が出来たら、以下の機能を追加してゲームをより楽しくしてみましょう
拡張版の完全なコード

<code>using System;

namespace NumberGuessingGame
{
    class Program
    {
        static void Main(string&#91;] args)
        {
            bool playAgain = true;
            
            while (playAgain)
            {
                PlayGame();
                
                Console.WriteLine("\nもう一度プレイしますか? (y/n): ");
                string response = Console.ReadLine().ToLower();
                playAgain = (response == "y" || response == "yes");
                
                Console.Clear(); // 画面をクリア
            }
            
            Console.WriteLine("ゲームを終了します。ありがとうございました!");
            Console.ReadKey();
        }
        
        static void PlayGame()
        {
            // ゲームの説明
            Console.WriteLine("╔═══════════════════════════════════╗");
            Console.WriteLine("║         数当てゲーム              ║");
            Console.WriteLine("╚═══════════════════════════════════╝");
            Console.WriteLine();
            
            // 難易度選択
            int maxNumber = SelectDifficulty();
            
            // 乱数生成
            Random random = new Random();
            int targetNumber = random.Next(1, maxNumber + 1);
            
            int attempts = 0;
            int maxAttempts = CalculateMaxAttempts(maxNumber);
            bool isCorrect = false;
            
            Console.WriteLine($"1から{maxNumber}までの数字を{maxAttempts}回以内で当ててください!");
            Console.WriteLine();
            
            // ゲームのメインループ
            while (!isCorrect &amp;&amp; attempts &lt; maxAttempts)
            {
                attempts++;
                Console.Write($"残り{maxAttempts - attempts + 1}回 - 予想を入力してください: ");
                
                string input = Console.ReadLine();
                
                if (int.TryParse(input, out int guess))
                {
                    // 入力範囲チェック
                    if (guess &lt; 1 || guess > maxNumber)
                    {
                        Console.WriteLine($"1から{maxNumber}までの数字を入力してください。");
                        attempts--; // 無効な入力は試行回数に含めない
                        continue;
                    }
                    
                    // 予想と正解の比較
                    if (guess == targetNumber)
                    {
                        Console.WriteLine("🎉 正解です! 🎉");
                        Console.WriteLine($"答えは {targetNumber} でした!");
                        Console.WriteLine($"{attempts} 回で正解しました!");
                        
                        // スコア評価
                        EvaluateScore(attempts, maxAttempts);
                        isCorrect = true;
                    }
                    else
                    {
                        // ヒントの表示
                        string hint = GetHint(guess, targetNumber, maxNumber);
                        Console.WriteLine(hint);
                        
                        // 温度ヒント(近さを表現)
                        string temperatureHint = GetTemperatureHint(guess, targetNumber);
                        Console.WriteLine(temperatureHint);
                    }
                }
                else
                {
                    Console.WriteLine("有効な数字を入力してください。");
                    attempts--;
                }
                
                Console.WriteLine();
            }
            
            // ゲーム終了時の処理
            if (!isCorrect)
            {
                Console.WriteLine("😢 残念!回数制限に達しました。");
                Console.WriteLine($"正解は {targetNumber} でした。");
            }
        }
        
        static int SelectDifficulty()
        {
            Console.WriteLine("難易度を選択してください:");
            Console.WriteLine("1. 簡単 (1-50)");
            Console.WriteLine("2. 普通 (1-100)");
            Console.WriteLine("3. 難しい (1-500)");
            Console.WriteLine("4. 超難しい (1-1000)");
            Console.Write("選択 (1-4): ");
            
            while (true)
            {
                string input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        Console.WriteLine("簡単モードを選択しました。");
                        return 50;
                    case "2":
                        Console.WriteLine("普通モードを選択しました。");
                        return 100;
                    case "3":
                        Console.WriteLine("難しいモードを選択しました。");
                        return 500;
                    case "4":
                        Console.WriteLine("超難しいモードを選択しました。");
                        return 1000;
                    default:
                        Console.Write("1から4までの数字を入力してください: ");
                        break;
                }
            }
        }
        
        static int CalculateMaxAttempts(int maxNumber)
        {
            // 2進探索の理論値 + 余裕を持たせる
            return (int)Math.Ceiling(Math.Log2(maxNumber)) + 3;
        }
        
        static string GetHint(int guess, int target, int maxNumber)
        {
            int difference = Math.Abs(guess - target);
            double percentage = (double)difference / maxNumber * 100;
            
            if (guess &lt; target)
            {
                if (percentage > 50)
                    return "📈 もっと大きい数字です(かなり離れています)";
                else if (percentage > 20)
                    return "📈 もっと大きい数字です(まあまあ離れています)";
                else if (percentage > 5)
                    return "📈 もっと大きい数字です(少し離れています)";
                else
                    return "📈 もっと大きい数字です(とても近いです!)";
            }
            else
            {
                if (percentage > 50)
                    return "📉 もっと小さい数字です(かなり離れています)";
                else if (percentage > 20)
                    return "📉 もっと小さい数字です(まあまあ離れています)";
                else if (percentage > 5)
                    return "📉 もっと小さい数字です(少し離れています)";
                else
                    return "📉 もっと小さい数字です(とても近いです!)";
            }
        }
        
        static string GetTemperatureHint(int guess, int target)
        {
            int difference = Math.Abs(guess - target);
            
            if (difference &lt;= 2)
                return "🔥 超熱い!";
            else if (difference &lt;= 5)
                return "🌡️ 熱い!";
            else if (difference &lt;= 10)
                return "😊 温かい";
            else if (difference &lt;= 20)
                return "😐 ぬるい";
            else if (difference &lt;= 50)
                return "🧊 冷たい";
            else
                return "❄️ 超冷たい";
        }
        
        static void EvaluateScore(int attempts, int maxAttempts)
        {
            double percentage = (double)attempts / maxAttempts;
            
            if (percentage &lt;= 0.3)
                Console.WriteLine("🏆 素晴らしい!天才的です!");
            else if (percentage &lt;= 0.5)
                Console.WriteLine("🥇 とても良い成績です!");
            else if (percentage &lt;= 0.7)
                Console.WriteLine("🥈 良い成績です!");
            else if (percentage &lt;= 0.9)
                Console.WriteLine("🥉 まずまずの成績です。");
            else
                Console.WriteLine("💪 次回はもっと頑張りましょう!");
        }
    }
}</code>

上記のコードに上書きが出来れば再度デバックを実行します
先ほどとは違う画面で難易度選択から始まりました
難易度を選択した後は先ほど同様数字を当てていきます

追加機能の解説

1. 難易度選択機能
<code>csharp<code>static int SelectDifficulty()</code></code>
<code>static int SelectDifficulty()
        {
            Console.WriteLine("難易度を選択してください:");
            Console.WriteLine("1. 簡単 (1-50)");
            Console.WriteLine("2. 普通 (1-100)");
            Console.WriteLine("3. 難しい (1-500)");
            Console.WriteLine("4. 超難しい (1-1000)");
            Console.Write("選択 (1-4): ");
            
            while (true)
            {
                string input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        Console.WriteLine("簡単モードを選択しました。");
                        return 50;
                    case "2":
                        Console.WriteLine("普通モードを選択しました。");
                        return 100;
                    case "3":
                        Console.WriteLine("難しいモードを選択しました。");
                        return 500;
                    case "4":
                        Console.WriteLine("超難しいモードを選択しました。");
                        return 1000;
                    default:
                        Console.Write("1から4までの数字を入力してください: ");
                        break;
                }
            }</code>

ユーザーが難易度を選択できる機能です。数字の範囲を変更することで、ゲームの難易度を調整します。

2. 制限回数システム
<code>csharp<code>static int CalculateMaxAttempts(int maxNumber)
{
    return (int)Math.Ceiling(Math.Log2(maxNumber)) + 3;
}</code></code>

2進探索の理論値を基に、適切な試行回数制限を設定します。これにより、ゲームにスリルを追加します。

3. 詳細なヒントシステム
  • 距離ベースのヒント: 予想と正解の差に基づいてヒントの詳細度を変更
  • 温度ヒント: 「熱い」「冷たい」などの直感的な表現でヒントを提供
4. スコア評価システム
<code>csharp<code>static void EvaluateScore(int attempts, int maxAttempts)</code></code>

試行回数に基づいてプレイヤーの成績を評価し、モチベーションを向上させます。

まとめ

  • 今回は、Visual StudioでC#コンソールアプリケーションを使った数当てゲームを作成しました
    このプロジェクトを通じて、以下の重要な概念を学習できました
  • 乱数生成: Randomクラスの使用方法
  • ユーザー入力処理: Console.ReadLine()とint.TryParse()の活用
  • 例外処理: 安全な型変換とエラーハンドリング
  • ループ処理: while文を使った繰り返し処理
  • 条件分岐: if-else文を使った判定処理
  • メソッド分割: 機能ごとのメソッド分割によるコードの整理
    この基礎的なゲームを作成できれば、より複雑なアプリケーション開発への第一歩となります
    ぜひ様々な機能を追加して、オリジナルのゲームに発展させてください