Layout

メニューを設定してゲーム画面を描画します。

前田稔の超初心者のプログラム入門

プログラムの説明

  1. MenuStrip を設定すると、ウインドウのレイアウトがずれるので、メニューを設定してからゲーム画面を作成します。
    メニューの実装(メニューを使えるようにする)は、後にまわします。
    親メニュー 子メニュー メソッド 説明
    File(&F)
    Save(&S) SaveFile 現在のゲームを保存します
    Load(&L) LoadFile ゲームファイルをロードします
    Exit(&X) Exit プログラムを終了します
    NewGame(&G)
    Level-1(&A) Level_1 初心者レベルで出題します
    Level-2(&B) Level_2 中級者レベルで出題します
    Level-3(&C) Level_3 上級者レベルで出題します
    Reset(&R) Reset 出題の状態に戻します
    Complete(&Q)Complete 完成のチェックをします
    Tool(&T)
    Check(&C) Check 現在の盤面でエラーを調べます
    Hint(&H) Hint マスに入る数字の候補を表示します
    AllPlay(&P) Play 正解を表示します
    Help(&H)
    Version(&V) Version バージョン情報を表示します
  2. CSForm.cs のデザイン画面を表示して、上の表に従ってメニューを設定して下さい。
    イベントハンドラーの登録とメニューの実装は、後にまわします。
    ToolBox からメニューを貼り付ける を参考にデザイン画面から設定します。
  3. メニューの設定が終わったらゲーム画面を描画します。
    CSForm.cs のソースコードです。
    /*★ Numberplace の画面を描画する    前田 稔 ★*/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    
    public class MyForm : Form
    {
        IMAGE       m_back;     //盤全体
        IMAGE       m_number;   //選択画像
        Card        m_num;      //0~9の数字
        Card        m_mini;     //ヒントの数字
        Card        m_color;    //背景色
        int[,] m_b = new int[9, 9]      //Base テーブル(答え)
           {{ 8,1,9,4,6,7,2,3,5 },
            { 2,4,6,5,1,3,8,7,9 },
            { 5,7,3,8,9,2,4,6,1 },
            { 3,5,8,2,4,1,7,9,6 },
            { 4,6,7,9,3,5,1,2,8 },
            { 9,2,1,6,7,8,5,4,3 },
            { 1,3,5,7,2,6,9,8,4 },
            { 7,8,4,3,5,9,6,1,2 },
            { 6,9,2,1,8,4,3,5,7 }};
        int[,] m_t = new int[9, 9];     //数字(問題)テーブル
        int[,] m_ct = new int[9, 9];    //色テーブル
        int    m_no = 0;                //選択数字
        Random rand = new Random();
    
        private MenuStrip menuStrip1;
        private ToolStripMenuItem fileFToolStripMenuItem;
        private ToolStripMenuItem saveSToolStripMenuItem;
        private ToolStripMenuItem loadLToolStripMenuItem;
        private ToolStripMenuItem exitXToolStripMenuItem;
        private ToolStripMenuItem newGameGToolStripMenuItem;
        private ToolStripMenuItem level1AToolStripMenuItem;
        private ToolStripMenuItem level2BToolStripMenuItem;
        private ToolStripMenuItem level3CToolStripMenuItem;
        private ToolStripMenuItem resetRToolStripMenuItem;
        private ToolStripMenuItem completeQToolStripMenuItem;
        private ToolStripMenuItem toolTToolStripMenuItem;
        private ToolStripMenuItem checkCToolStripMenuItem;
        private ToolStripMenuItem hintHToolStripMenuItem;
        private ToolStripMenuItem aToolStripMenuItem;
        private ToolStripMenuItem helpHToolStripMenuItem;
        private ToolStripMenuItem versionVToolStripMenuItem;
    
        public void Debug(string msg, int n)
        {
            Console.Write("\n" + msg + n);
        }
        public void Debug(int[,] t)
        {
            int x, y;
            for (y = 0; y < 9; y++)
            {
                for (x = 0; x < 9; x++)
                { Console.Write(t[y, x]); }
                Console.Write("\n");
            }
        }
    
        public MyForm()
        {
            InitializeComponent();  // 追加する
            Width = 600;
            Height = 700;
            m_back = new IMAGE(@"c:\data\test\back.gif");
            m_number = new IMAGE(@"c:\data\test\number.gif");
            m_num = new Card(@"c:\data\test\num.gif", 60, 60);
            m_mini = new Card(@"c:\data\test\minicor.gif", 30, 30);
            m_color = new Card(@"c:\data\test\color.gif", 60, 60);
            Paint += new PaintEventHandler(MyHandler);
            MouseDown += new MouseEventHandler(OnMyMouseDown);
            m_no = 0;
            Generate(35);
        }
    
        // 盤を描画
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (m_back.bmp == null) Application.Exit();
            for (int y = 0; y < 9; y++)
            {
                for (int x = 0; x < 9; x++)
                {
                    if (m_ct[y, x] > 0 && m_ct[y, x] < 10)
                        m_color.View(g, m_ct[y, x] - 1, x * 60 + 10, y * 60 + 30);
                    if (m_t[y, x] > 0 && m_ct[y, x] < 10)
                        m_num.View(g, m_t[y, x], x * 60 + 10, y * 60 + 30);
                }
            }
            m_back.View(g, 10, 30);
            m_number.View(g, 10, 580);
        }
    
        // マウスのクリックを検出
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {
            int xp, yp;
            xp = (e.X - 10) / 60;
            yp = (e.Y - 30) / 60;
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {
                if (e.Y > 580)
                {   m_no = xp;  }
                else
                {
                    if (xp > 8 || yp > 8) return;
                    if (m_ct[yp, xp] != 0)
                    {
                        if (m_t[yp, xp] == 0)   m_t[yp, xp] = m_no + 1;
                        else m_t[yp, xp] = 0;
                        m_ct[yp, xp] = 1;
                    }
                }
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {
                if (xp > 8 || yp > 8) return;
                if (m_ct[yp, xp] != 0)
                {
                    m_ct[yp, xp] = (m_ct[yp, xp] + 1) % 5;
                    if (m_ct[yp, xp] == 0) m_ct[yp, xp] = 1;
                }
            }
            Debug("m_no:", m_no);
            Invalidate();
        }
    
        private void InitializeComponent()
        {
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
            ・・・
              // メニューを登録すると作成される InitializeComponent() です
            ・・・
        }
    
        // m_b[9,9] を元に問題を作成する
        public void Generate(int rate)
        {
            for (int y = 0; y < 9; y++)
                for (int x = 0; x < 9; x++) m_t[y, x] = m_b[y, x];
            // m_t[y,x] ← 0, m_ct[y,x] ← 1 で穴抜きを設定
            for (int y = 0; y < 9; y++)
                for (int x = 0; x < 9; x++)
                {
                    m_ct[y, x] = 0;
                    if (rand.Next(100) < rate)
                    {
                        m_t[y, x] = 0;
                        m_ct[y, x] = 1;
                    }
                }
            Invalidate();
        }
    }
    
    class IMAGE
    {
        public  Bitmap  bmp;
        ・・・
          // 先に説明した Image Class です
        ・・・
    }
    
    //☆ Card Object Class
    class Card
    {
        public  Bitmap  bmp;
        ・・・
          // 先に説明した Card Class です
        ・・・
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  4. プログラムの要点を説明します。
    MyHandler() が画面を描画する関数で、タイル(マスの色)と数字と枠を重ねて描画します。
    m_t[y, x]==0 は穴抜きした箇所で、m_ct[y,x](マスの色) は 1 になっています。
    今回は使いませんが、m_ct[y, x]==6 はエラーが指摘されたマスです。
  5. 本来ならナンプレの問題はプログラムで作成するのですが、今回は定数(int[,] m_b)で定義します。
        int[,] m_b = new int[9, 9]      //Base テーブル(答え)
           {{ 8,1,9,4,6,7,2,3,5 },
              ・・・
            { 6,9,2,1,8,4,3,5,7 }};
    
  6. m_b から Generate() 関数を使って、乱数でマスを抜いて m_t に問題を作成します。
        int[,] m_t = new int[9, 9];     //数字テーブル
    
  7. 左クリックで数字画像を選択して、マスをクリックすると数字が置かれます。
    数字が置かれているマスをクリックすると削除されます。
    マスを右クリックすると背景色が1~4に切り替わります。

[Next Chapter ↓] Menu
[Previous Chapter ↑] Image

超初心者のプログラム入門(C# Frame Work)