将棋サンプル(経過)

2023年3月1日

クラス図

// 必要な名前空間を読み込む
using System;
using System.Drawing;
using System.Windows.Forms;

// Shogiという名前の名前空間を定義する
namespace Shogi
{
    // Form1という名前のクラスを定義する。このクラスは、Formクラスを継承する
    public partial class Form1 : Form
    {
        // 選択された駒を表すPieceオブジェクトを取得または設定するプロパティ
        public Piece SelectedPiece { get; set; }

        // コンストラクタ
        public Form1()
        {
            // コンポーネントの初期化
            InitializeComponent();

            // マウスの移動イベントをハンドルするメソッドを登録する
            board1.BoardMouseMoved += BoardMouseMove;
            // マウスクリックイベントをハンドルするメソッドを登録する
            board1.BoardMouseClicked += BoardMouseClick;
            // 駒を作成する
            CreatePiece(Koma.Hu, 2, 7);
            CreatePiece(Koma.Hu, 1, 7);
        }

        // マウスクリックイベントをハンドルするメソッド
        private void BoardMouseClick(object sender, (Point mousePos, Point fugou) Pos)
        {
            // 選択された駒がない場合、処理を終了する
            if (SelectedPiece == null)
            {
                return;
            }

            // 選択された駒がすでに選択されている場合、駒を移動させる
            if (SelectedPiece.IsSelected)
            {
                board1.SetPiece(SelectedPiece, Pos.fugou.X, Pos.fugou.Y);
                SelectedPiece.IsSelected = false;
            }
        }

        // 駒を作成するメソッド
        private void CreatePiece(Koma koma, int x, int y)
        {
            // komaの種類に応じて、駒を生成する
            switch (koma)
            {
                case Koma.Hu:
                    board1.SetPiece(new Hu(this), x, y);
                    break;
                case Koma.Kyou:
                    break;
                case Koma.Kei:
                    break;
                case Koma.Gin:
                    break;
                case Koma.Kin:
                    break;
                case Koma.Kaku:
                    break;
                case Koma.Hi:
                    break;
                case Koma.Ou:
                    break;
                default:
                    break;
            }
        }

        // マウスの移動イベントをハンドルするメソッド
        private void BoardMouseMove(object sender, (Point mousePos, Point fugou) Pos)
        {
            // マウスの座標をラベルに表示する
            label2.Text = Pos.mousePos.ToString();
            //pictureBox1.Location = Pos.mousePos;
            // 駒の座標をラベルに表示する
            label3.Text = Pos.fugou.ToString();
        }

        // button2がクリックされたときのイベントをハンドルするメソッド
        private void button2_Click(object sender, EventArgs e)
        {
            // button1の位置を上に移動する
            button1.Top += 39;
        }

        // button3がクリックされたときのイベントをハンドルするメソッド
        private void button3_Click(object sender, EventArgs e)
        {
            // button1の位置を左に移動する
            button1.Left += 35;
        }
    }


    //int y = 9;
    //private void button6_Click(object sender, EventArgs e)
    //{
    //    board1.SetPiece(fu, 2, --y);
    //}
}

このコードは、将棋の盤面を表すWindowsフォームアプリケーションの一部です。以下に、コードの各部分の機能を説明します。

  1. using文 必要な名前空間を読み込むために使用されます。このコードでは、System、System.Drawing、およびSystem.Windows.Formsの名前空間を使用しています。
  2. Shogi名前空間 この名前空間は、このコードで定義されています。Shogiという名前空間は、将棋の盤面を表すWindowsフォームアプリケーションで使用されます。
  3. Form1クラス このクラスは、Windowsフォームアプリケーションの主要なクラスであり、Formクラスを継承しています。このクラスでは、選択された駒を表すPieceオブジェクトの取得または設定ができるSelectedPieceプロパティが定義されています。
  4. コンストラクタ Form1クラスのコンストラクタであり、このコードで初めて呼び出されるメソッドです。コンポーネントの初期化、マウスの移動イベントとクリックイベントの登録、そして2つの歩の駒を作成するCreatePieceメソッドを呼び出しています。
  5. マウスクリックイベントをハンドルするメソッド board1という名前の盤面をクリックしたときに呼び出されるメソッドで、SelectedPieceがnullでない場合、SelectedPieceをクリックした場所に移動させます。
  6. 駒を作成するメソッド 指定された駒の種類と座標を使用して、board1の盤面上に新しい駒を作成します。
  7. マウスの移動イベントをハンドルするメソッド board1の盤面上でマウスが移動したときに呼び出され、ラベルに現在のマウスの座標と駒の座標を表示します。
  8. button2がクリックされたときのイベントをハンドルするメソッド button1の位置を上に移動させます。
  9. button3がクリックされたときのイベントをハンドルするメソッド button1の位置を左に移動させます。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Shogi
{
    // UserControlを継承したBoardという名前のクラスを宣言する。
    internal partial class Board : UserControl
    {
        // 公開された Piece の二次元配列 Pieces を宣言する。
        public Piece[,] Pieces = new Piece[10, 10];

        // セルの幅と高さを定義するための int 変数を宣言する。
        int cellWidth;
        int cellHeight;

        // ボードの余白を定義するための int 変数を宣言する。
        int paddingLeft = 5;
        int paddingRight = 5;
        int paddingTop = 3;
        int paddingBottom = 3;

        // Imageプロパティを宣言する。
        public Image Image { get; set; }

        // マウスが動いたときとクリックされたときのイベントを宣言する。
        public event EventHandler<(Point, Point)> BoardMouseMoved;
        public event EventHandler<(Point, Point)> BoardMouseClicked;

        // Boardクラスのコンストラクタを定義する。
        public Board()
        {
            // InitializeComponent()メソッドを呼び出す。
            InitializeComponent();

            // セルの幅と高さを計算する。
            cellWidth = (Size.Width - (paddingLeft + paddingRight)) / 9;
            cellHeight = (Size.Height - (paddingTop + paddingBottom)) / 9;

            // boardPictureのMouseClickイベントとMouseMoveイベントにそれぞれ、OnMouseClickメソッドとOnMouseMoveメソッドを関連付ける。
            boardPicture.MouseClick += OnMouseClick;
            boardPicture.MouseMove += OnMouseMove;
        }

        // boardPictureのマウスがクリックされたときに呼び出されるメソッドを定義する。
        void OnMouseClick(object sender, MouseEventArgs e)
        {
            // BoardMouseClickedイベントを呼び出す。
            BoardMouseClicked.Invoke(this, GetSignFromScreenPosition(e.Location));
        }

        // boardPictureのマウスが動いたときに呼び出されるメソッドを定義する。
        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            // BoardMouseMovedイベントを呼び出す。
            BoardMouseMoved.Invoke(this, GetSignFromScreenPosition(e.Location));
        }

        /*
            public static Point GetSignFromScreenPosition(Point pos)
            {
               var sign = board[(pos.X - 189) % 35, (pos.Y - 19) % 39];
               return sign;
            }
        */

        // スクリーン座標からマス目座標を計算して返すメソッドを定義する。
        public (Point mousePos, Point fugou) GetSignFromScreenPosition(Point mousePosition)
        {
            int x = RoundToNearestCell(mousePosition.X + Left, cellWidth) - cellWidth / 2;
            int y = RoundToNearestCell(mousePosition.Y + Top, cellHeight) - cellHeight / 2;

            return (new Point(x, y), ScreenPositionToSignPosition(x, y));
        }

        // ScreenPositionToSignPositionメソッド:スクリーン座標を盤上の座標に変換する。
        private Point ScreenPositionToSignPosition(int x, int y)
        {
            // スクリーン上のx, y座標を、Location.X、Location.Y、paddingLeft、paddingTop、cellWidth、cellHeightを使って、盤上の座標に変換する。
            int posX = (x - Location.X + paddingLeft) / cellWidth;
            int posY = (y - Location.Y + paddingTop) / cellHeight;
            // 盤上のx, y座標を新しいPointオブジェクトにして返す。
            return new Point(9 - posX, 1 + posY);
        }

        // SignPositionToScreenPositionメソッド:盤上の座標をスクリーン座標に変換する。
        private Point SignPositionToScreenPosition(int x, int y)
        {
            // 盤上のx, y座標を、Location.X、Location.Y、paddingLeft、paddingTop、cellWidth、cellHeightを使って、スクリーン上の座標に変換する。
            int posX = Location.X + paddingLeft + 4 + (9 - x) * cellWidth;
            int posY = Location.Y + paddingTop + 6 + (y - 1) * cellHeight;
            // スクリーン上のx, y座標を新しいPointオブジェクトにして返す。
            return new Point(posX, posY);
        }

        // RoundToNearestCellメソッド:valueをcellSizeで最も近い整数に丸める。
        private int RoundToNearestCell(double value, int cellSize)
        {
            return (int)Math.Round(value / cellSize) * cellSize;
        }

        // SetPieceメソッド:指定された駒を指定された位置にセットする。
        public void SetPiece(Piece piece, int x, int y)
        {
            // 盤上の駒の配列をループして、指定された駒を探し、その位置をnullにして、指定された位置に駒をセットする。
            for (int i = 0; i < Pieces.GetLongLength(0); i++)
            {
                for (int j = 0; j < Pieces.GetLongLength(1); j++)
                {
                    if (Pieces[i, j] == piece)
                    {
                        Pieces[i, j] = null;
                        Pieces[x, y] = piece;
                        break;
                    }
                }
            }
            // 駒の位置を、盤上の座標からスクリーン上の座標に変換して、駒のLocationにセットする。
            piece.Location = SignPositionToScreenPosition(x, y);
        }
    }
}

このコードは、将棋の盤面を表すクラスである「Board」を定義しています。このクラスは、「UserControl」クラスを継承しています。

以下は、このクラスで定義されている主なメンバーの説明です。

  • 変数・フィールド
    • Pieces:将棋の駒の配置を表す2次元配列。
    • cellWidth:マスの幅を表す整数値。
    • cellHeight:マスの高さを表す整数値。
    • paddingLeft:左側の余白の幅を表す整数値。
    • paddingRight:右側の余白の幅を表す整数値。
    • paddingTop:上部の余白の幅を表す整数値。
    • paddingBottom:下部の余白の幅を表す整数値。
    • Image:盤面に表示する画像を表すプロパティ。
  • イベント
    • BoardMouseMoved:マウスが動いたときに発生するイベント。
    • BoardMouseClicked:マウスがクリックされたときに発生するイベント。
  • メソッド
    • Board():コンストラクタ。盤面の初期化を行う。
    • OnMouseClick():マウスがクリックされたときに呼び出されるメソッド。
    • OnMouseMove():マウスが動いたときに呼び出されるメソッド。
    • GetSignFromScreenPosition():スクリーン座標から盤面上の座標を計算するメソッド。
    • ScreenPositionToSignPosition():盤面上の座標からスクリーン座標を計算するメソッド。
    • SignPositionToScreenPosition():盤面上の座標からスクリーン座標を計算するメソッド。
    • RoundToNearestCell():指定された座標を最も近いマス目に丸めるメソッド。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Shogi
{
    // Pieceクラスの定義。abstract修飾子が付いており、抽象クラスであることを示します。
    // partial修飾子が付いているため、このクラスは複数のファイルに分割されている可能性があります。
    public abstract partial class Piece : UserControl
    {
        // Pieceクラスが属するフォームのインスタンスを保持するフィールド。
        Form1 form;

        // 駒が選択されているかどうかを表すフラグを保持するフィールド。
        private bool isSelected;

        // 駒が選択されているかどうかを取得・設定するためのプロパティ。
        public bool IsSelected
        {
            get => isSelected;
            set
            {
                isSelected = value;
                // 駒の背景色を変更します
                PieceBackColor = isSelected ? Color.Red : Color.White;
            }
        }

        // 駒の種類を保持するプロパティ。
        public Koma koma { get; private set; }

        // 駒の画像を設定するためのプロパティ。
        public Image Image
        {
            set
            {
                peacePictreBox.Image = value;
            }
        }

        // 駒の背景色を設定するためのプロパティ。
        public Color PieceBackColor
        {
            set
            {
                peacePictreBox.BackColor = value;
            }
        }

        // Pieceクラスのコンストラクタ。フォームのインスタンスを受け取ります。
        public Piece(Form1 form)
        {
            // コンポーネントの初期化を行います。
            InitializeComponent();

            // マウス押下イベントのハンドラを設定します
            peacePictreBox.MouseDown += OnMouseDown;

            // 渡されたフォームのインスタンスを保持します
            this.form = form;

            // このコントロールをフォームに追加します
            Parent = form;

            // このコントロールを最前面に移動します
            BringToFront();
        }


        // マウスが押されたときに呼び出されるメソッド
        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            // 同じ駒をクリックした時
            if (form.SelectedPiece == this)
            {
                // 駒の選択状態を切り替えます
                IsSelected = !IsSelected;
                return;
            }
            // 選択された駒がある場合、選択を解除し、新しく選択された駒を選択中にします
            if (form.SelectedPiece != null)
            {
                form.SelectedPiece.IsSelected = false;
                IsSelected = true;
            }

            // この駒を選択された駒にします
            form.SelectedPiece = this;
        }

        // 駒がクリックされたときに呼び出される仮想メソッド
        public virtual void PieceClick(object sender, EventArgs e)
        {

        }

    }

    //class Kyou : Piece
    //{
    //    public override void PieceClick(object sender, EventArgs e)
    //    {
    //        base.PieceClick(sender, e);
    //    }
    //}
}

このコードは、将棋の駒を表すPieceクラスを定義しています。

具体的には、以下のような機能が含まれています。

  • UserControlクラスを継承しているため、Visual Studioのデザイナーで使えるようになっています。
  • Form1クラスのインスタンスを保持するためのフィールドがあります。
  • 駒が選択されているかどうかを示すisSelectedというフラグがあります。これは、Pieceクラスが選択されたときに駒の背景色を変更するために使用されます。
  • komaというプロパティがあり、駒の種類を表します。
  • ImageとPieceBackColorというプロパティがあり、それぞれ駒の画像と背景色を設定するために使用されます。
  • Pieceクラスのコンストラクタがあり、Form1クラスのインスタンスを受け取ります。コンポーネントの初期化を行い、マウス押下イベントのハンドラを設定します。
  • OnMouseDownというメソッドがあり、駒がマウスでクリックされたときに呼び出されます。このメソッドでは、選択された駒の管理、選択状態の切り替え、クリックされた駒の選択状態の設定などを行います。
  • PieceClickという仮想メソッドがあります。このメソッドは、駒がクリックされたときに呼び出され、派生クラスでオーバーライドすることができます。
namespace Shogi
{
    // Huクラスを定義する
    class Hu : Piece
    {
        // コンストラクタで親クラスのコンストラクタを呼び出し、イメージを設定する
        public Hu(Form1 form) : base(form)
        {
            Image = Properties.Resources.syougi14_fuhyou;
        }
    }

    //class Kyou : Piece
    //{
    //    public override void PieceClick(object sender, EventArgs e)
    //    {
    //        base.PieceClick(sender, e);
    //    }
    //}
}

このコードは、Shogiという名前空間内にある、Huというクラスを定義しています。

Huクラスは、Pieceというクラスを継承しています。Pieceクラスは、将棋の駒を表すための基底クラスであり、駒に関する共通の機能を提供するためのものです。

Huクラスには、親クラスのコンストラクタを呼び出すコンストラクタが定義されています。このコンストラクタは、Form1クラスのオブジェクトを受け取り、親クラスのコンストラクタに渡しています。親クラスのコンストラクタは、受け取ったForm1オブジェクトを保持し、Pieceクラスの機能を初期化します。また、HuクラスのImageプロパティに、Properties.Resources.syougi14_fuhyouという画像を設定しています。

また、コメントアウトされたKyouクラスが定義されています。このクラスは、Pieceクラスを継承しており、PieceClickというメソッドをオーバーライドしています。PieceClickは、駒がクリックされたときに呼び出されるメソッドであり、Kyouクラスでは、親クラスのPieceClickメソッドを呼び出すようにオーバーライドしています。