召喚システムをテーマにしたWinFormアプリでオブジェクト指向を学ぶ(UserControl)

2024年8月23日

この資料では、C#のWindowsフォームアプリケーションを使って、簡単な召喚システムを実装する方法を学びます。オブジェクト指向プログラミングの基本概念であるクラス、オブジェクト、プロパティ、メソッド、そしてUserControlの使い方を理解することが目標です。


オブジェクト指向についてイメージをつかむ

例えから、理解を試みましょう

このチュートリアルを取り組む前に読んでおきましょう

ステップ1: SummonedCreature クラスの作成

まず、召喚されるクリーチャーを表現するクラスを作成します。このクラスは、クリーチャーの名前とレベルを管理し、攻撃メソッドを提供します。

プロジェクトに新しいクラスを追加し、名前を SummonedCreature とします。以下のコードを記述します。

public class SummonedCreature
{
    public string Name { get; }
    public int Level { get; }

    public SummonedCreature(string name, int level)
    {
        Name = name;
        Level = level;
    }

    public string Attack()
    {
        return $"{Name} がレベル {Level} で攻撃をした!";
    }

    public override string ToString()
    {
        return $"{Name} (レベル {Level})";
    }
}

解説

  • クラスとオブジェクト: SummonedCreature クラスはクリーチャーを作成するための設計図です。このクラスから具体的なクリーチャー(オブジェクト)を生成します。
  • プロパティ: Name と Level はプロパティで、クリーチャーの状態を保持します。プロパティはオブジェクトのデータを読み書きするための機能です。
  • コンストラクター: SummonedCreature クラスのコンストラクターは、オブジェクトが生成されたときに名前とレベルを初期化します。
  • ToString メソッド: ToString メソッドは、オブジェクトを文字列として表現するために使われます。リストボックスに表示する際、このメソッドが呼び出されます。

ステップ2: SummonControl UserControl の作成

次に、UserControlを作成し、召喚システムをカプセル化します。

UserControlは、複数のコントロール(ボタン、テキストボックスなど)をまとめ、再利用可能なカスタムコントロールを作成するためのものです。

使い方の流れ:

  1. UserControlを作成:デザインビューでコントロールを配置。
  2. ロジックを追加:必要な動作をコードで実装。
  3. フォームに配置:通常のコントロールと同様に、他のフォームにドラッグ&ドロップで追加。

メリット:

  • 再利用性: 一度作成すれば、他のプロジェクトでも使い回せます。
  • カプセル化: 複雑なロジックを1つのコントロールにまとめ、コードの管理が容易になります。
  • 保守性: コードの一元管理が可能で、バグ修正や機能追加が簡単です。

UserControlは、プログラムの構造を整理し、コードの再利用性を高めるための強力なツールです。

プロジェクトを右クリックし、「追加 > ユーザーコントロール(Windowsフォーム)」を選択します。名前を SummonControl とします。

デザインビューで ListBox をドラッグ&ドロップし、Name プロパティを creatureListBox に設定します。

SummonControl.cs に以下のコードを記述します。

public partial class SummonControl : UserControl
{
    public SummonControl()
    {
        InitializeComponent();
    }

    public SummonedCreature Summon(string name)
    {
        int level = new Random().Next(1, 101);
        return new SummonedCreature(name, level);
    }

    public void DisplayCreature(SummonedCreature creature)
    {
        creatureListBox.Items.Add(creature);
    }

    public int SelectedIndex => creatureListBox.SelectedIndex;
    public SummonedCreature SelectedCreature => creatureListBox.SelectedItem as SummonedCreature;
}

解説

  • Summon メソッド: クリーチャーを生成し、ランダムなレベルを設定します。
  • DisplayCreature メソッド: 生成されたクリーチャーをリストボックスに表示します。ToString メソッドが自動的に呼び出され、名前とレベルが表示されます。
  • SelectedCreature プロパティ: リストボックスで選択されたアイテムを SummonedCreature 型として取得します。選択されたアイテムが SummonedCreature 型でない場合は null が返されます。

ステップ3: ビルドの実行

SummonControlをフォームに配置するには、必ずこのステップでプロジェクトを一度ビルドします。これにより、デザインビューでSummonControlがドラッグ&ドロップできるようになります。

メニューから、ビルド > ソリューションのビルド を選択してプロジェクトをビルドします。

ビルドが失敗した場合の対処方法

ビルドが失敗した場合、以下の点を確認してください。

  • エラーメッセージを確認する: エラーメッセージには、どのコード部分に問題があるかが記載されています。これを元に、コードを修正します。
  • 未定義のクラスやメソッドの使用: クラス名やメソッド名が正しく定義されているか、スペルミスがないかを確認します。
  • 外部ライブラリの不足: 必要な参照が正しく追加されているか確認します。特に、プロジェクトで外部ライブラリを使用している場合は、それらがプロジェクトに含まれていることを確認します。
  • パスや名前空間のエラー: クラスやメソッドが正しい名前空間に属しているか、正しいパスで保存されているかを確認します。

デザインビューにUserControlが表示されない場合の対処方法

ビルドが成功したにもかかわらず、デザインビューにUserControlが表示されない場合、以下の点を確認してください。

  • ビルドが完全に成功しているか: 以前のビルドエラーが残っていないか確認してください。Visual Studioを再起動して、再度ビルドを試みるのも有効です。
  • UserControlのコードにエラーがないか: UserControl内で例外が発生していると、デザインビューに表示されないことがあります。コンストラクターやInitializeComponentメソッド内に問題がないか確認してください。
  • プロジェクトのクリーン: メニューから「ビルド > ソリューションのクリーン」を選択し、その後に再度「ビルド > ソリューションのビルド」を実行します。これにより、古いビルドキャッシュがクリアされます。
  • Visual Studioの再起動: Visual Studioを再起動することで、デザインビューの問題が解消されることがあります。

これらの対策を講じることで、ビルドエラーやデザインビューにUserControlが表示されない問題に対処できます。

ステップ4: メインフォーム (Form1) の作成とデザイン

次に、メインフォームでUserControlを利用して、召喚機能と攻撃機能を実装します。

デザインビューで以下のコントロールをドラッグ&ドロップします:

  • TextBoxName: creatureNameTextBox
  • ButtonName: summonButtonText: 召喚
  • ButtonName: attackButtonText: 攻撃
  • LabelName: actionResultLabel
  • SummonControl(Name: summonControl

Form1.cs に以下のコードを記述します。

public partial class Form1 : Form
{
    private List<SummonedCreature> summonedCreatures = new List<SummonedCreature>();

    public Form1()
    {
        InitializeComponent();
    }

    private void summonButton_Click(object sender, EventArgs e)
    {
        string name = creatureNameTextBox.Text;
        SummonedCreature creature = summonControl.Summon(name);
        summonedCreatures.Add(creature);
        summonControl.DisplayCreature(creature);
        actionResultLabel.Text = $"{name} が召喚されました!";
    }

    private void attackButton_Click(object sender, EventArgs e)
    {
        SummonedCreature selectedCreature = summonControl.SelectedCreature;
        if (selectedCreature != null)
        {
            actionResultLabel.Text = selectedCreature.Attack();
        }
        else
        {
            actionResultLabel.Text = "攻撃するクリーチャーを選択してください。";
        }
    }
}

解説

  • イベントハンドラ: summonButton_Click と attackButton_Click はイベントハンドラと呼ばれ、ボタンがクリックされたときに特定の処理を実行します。これにより、ユーザーの操作に応じたアクションを実装できます。
  • summonButton_Click メソッドで、クリーチャーを召喚してリストに追加し、表示します。
  • attackButton_Click メソッドで、選択されたクリーチャーを攻撃させ、その結果をラベルに表示します。

ステップ5: アプリケーションの実行とテスト

プロジェクトをビルドし、アプリケーションを実行します。クリーチャーの名前を入力し、「召喚」ボタンを押すと、クリーチャーがリストに追加されます。リストからクリーチャーを選択して「攻撃」ボタンを押すと、そのクリーチャーの攻撃メッセージが表示されます。


まとめ

この資料を通じて、UserControlを使用して再利用可能なUIコンポーネントを作成し、カプセル化やオブジェクト指向の基本的な概念を学びました。さらに、クラス設計とメソッドの再利用性を高める実装を行い、拡張可能なアプリケーションを構築しました。

この手順を通じて、オブジェクト指向プログラミングの基本概念を実践的に学びながら、より効果的な設計手法を身につけましょう。

初学者向け:C#クラスとオブジェクトの学習ガイド

クラスとオブジェクトの基本説明

クラスとは、オブジェクトを作成するための設計図です。クラスは、共通の属性(データ)と動作(メソッド)を持つオブジェクトを定義します。たとえば、「SummonedCreature」というクラスは、ゲーム内で召喚されるクリーチャーの設計図となります。

オブジェクトは、クラスをもとに作成された実際のインスタンスです。SummonedCreature クラスから作られた具体的なクリーチャーは、各クリーチャーが異なる名前やレベルを持つ個別のオブジェクトです。

プロパティの説明

プロパティは、オブジェクトが持つデータを保持するためのメカニズムです。たとえば、SummonedCreature クラスには Name や Level というプロパティがあり、これらを使ってクリーチャーの名前やレベルを管理します。プロパティを使うことで、オブジェクトの状態を簡単に読み書きできます。

コンストラクターの役割

コンストラクターは、オブジェクトが生成されたときに初期化を行う特別なメソッドです。SummonedCreature クラスのコンストラクターでは、クリーチャーの名前とレベルが設定されます。たとえば、新しいクリーチャーを召喚する際に、その名前とレベルを指定して初期化します。

public SummonedCreature(string name, int level)
{
    Name = name;
    Level = level;
}

ToString メソッドの役割

ToString メソッドは、オブジェクトを文字列として表現するために使われます。たとえば、リストボックスにクリーチャーを表示する際、ToString メソッドが呼び出され、クリーチャーの名前とレベルが表示されます。このメソッドをオーバーライドすることで、表示される内容をカスタマイズできます。

public override string ToString()
{
    return $"{Name} (Lv {Level})";
}

イベントハンドラの基本

summonButton_Click や attackButton_Click などのメソッドは、イベントハンドラと呼ばれます。イベントハンドラは、特定のイベントが発生したときに実行されるメソッドです。たとえば、ボタンがクリックされたときに、召喚や攻撃の処理を行うことができます。

例外処理について

より堅牢なプログラムを作成するためには、例外処理も重要です。たとえば、SelectedCreature が null の場合に備えてエラーハンドリングを加えることで、プログラムがクラッシュするのを防ぐことができます。

if (SelectedCreature == null)
{
    MessageBox.Show("クリーチャーが選択されていません。");
    return;
}

UserControlの再利用性

UserControl は、UIの再利用可能なコンポーネントです。たとえば、SummonControl を作成すれば、同じ機能を複数の画面やプロジェクトで簡単に使い回すことができます。これにより、開発効率が向上し、コードの重複を減らすことができます。

as 演算子の説明

as 演算子は、オブジェクトの型を安全に変換するために使われます。変換が成功すれば指定された型のオブジェクトを返し、失敗した場合は null を返します。これにより、型の不一致によるエラーを防ぐことができます。

SelectedCreature = listBox.SelectedItem as SummonedCreature;

UML図

クラス図

シーケンス図(召喚シナリオ)

シーケンス図(攻撃シナリオ)

解説

クラス図: 

クラス間の関連性を表し、各クラスのプロパティやメソッドを示しています。Form1クラスがSummonControlSummonedCreatureクラスを使用し、SummonControlSummonedCreatureを使用する関係を描いています。

シーケンス図:

召喚シナリオ: ユーザーが「召喚」ボタンを押したときのシーケンスを表現しています。SummonControlSummonedCreatureを生成し、Form1がそれを表示する流れです。

攻撃シナリオ: ユーザーが「攻撃」ボタンを押したときのシーケンスを表現しています。選択されたクリーチャーが攻撃するか、選択されていない場合はエラーメッセージが表示される流れです。

これらのUML図を使って、コードの構造と動作を視覚的に理解することができます。