C#で2048ゲームのクローンを作る[その1]

これから勉強をかねて、2048というゲームのクローンをWinFormで作ってみようと思います。

2048って何?


一時期ブームになったスマホのゲームアプリで、パネルをスライドさせながら大きな数字を作っていくゲームです。ルールは説明するより、動画を見てもらったほうが早いです。


個人的にはこのゲーム、結構プレイしていて最高で8192まで行った事があります。



作成ルール

本当は一気に作ってしまいのですが、時間が無いので下記のルールで少しづつ進めていきます。

毎週何か作る。本当な毎日少しづつ進めたいけど仕事があるので、週に3回以上は最低目標とする。

作成中のプログラムをBlogにさらす。本当ならいったん全部作ってしまってから、キレイに順序だてて説明すべきなのだけど、それだとモチベーションが続かなさそう。なので、試作目的で後で消す予定のコードだとしても一旦アップしてしまう。

ネットで2048cloneの作り方は検索できるけど、勉強の為にあえて見ずに作ってみる。


今日のコード

と、言うわけでさっそく今日の成果です。
とりあえず今回はイメージをつかむために、下記の試作をして見ました。

・最初の盤面は決まっている。
・カーソルキーの上を押したら、上方向にスライドさせる。
・スライドさせても新しいパネルは出現しない。
・画面表示はまだ作らない。(TextBoxに盤面データをダンプするだけ)

なので、プログラムが起動したらカーソルの上キーを押すだけの動作確認状態です。
現状のロジックだと、2回上を押すと2のパネルが消えてしまうバグがあるとう中途半端な状態ですが、続きはまた次回にします。

パネルのスライド処理が地味に面倒です…

using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
 
namespace Mock2048 {
    public partial class Form1 : Form {
        // 盤面の情報
        private int[,] board = new int[4,4];        
 
        public Form1() {
            InitializeComponent();
        }
 
        //*********************************************************************
        /// <summary> 画面表示時のハンドラ
        /// </summary>
        //*********************************************************************
        private void Form1_Load( object sender, EventArgs e ) {
            // Formコントロール自身がキー入力を取得可能とする
            this.KeyPreview = true;
 
            //盤面の初期化
            initBoard();
 
            // 盤面を表示する
            displayBoard(); 
        }
 
 
        //*********************************************************************
        /// <summary> キー入力時のハンドラ
        /// </summary>
        //*********************************************************************
        private void Form1_KeyDown( object sender, KeyEventArgs e ) {
            moveCell( e.KeyCode );
 
            // 盤面を表示する
            displayBoard();
        }
 
        //*********************************************************************
        /// <summary> 盤面の初期化(テストデータのセット)
        /// </summary>
        //*********************************************************************
        private void initBoard() {
            board[2,0] = 4;
            board[3,0] = 2;
            board[3,1] = 2;
 
            board[2,2] = 4;
            board[3,3] = 2;
 
        }
 
        //*********************************************************************
        /// <summary> 盤面を画面に表示させる
        /// </summary>
        //*********************************************************************
        private void displayBoard() {
            string boardData = "";
 
            // すべての行のデータを出すまで繰り返し
            for (int y = 0; y < 4; y++) {
                // 1行分のデータを出力
                for (int x = 0; x < 4; x++) {
                    boardData += board[x,y];
                }
                boardData += Environment.NewLine;
            }
 
            txtLog.Text = boardData;
        }
 
        //*********************************************************************
        /// <summary> 指定された方向に移動させる
        /// </summary>
        /// <param name="keyCode"></param>
        //*********************************************************************
        private void moveCell( Keys keyCode ) {
 
            // 入力されたキーを判定する
            switch ( keyCode ) {
                case Keys.Up:
                    // 2~4列目に対して上方向のスライドを試みる
                    for (int y = 1; y < 4; y++) {
                        for (int x = 0; x < 4; x++) {
                            int targetCellVal = board[x,y];
                            if ( targetCellVal == 0 ) {
                                continue; // 空セルは何もしない
                            }
 
 
                            // 上方向に移動させる
                            bool isMoved = false;
                            for ( int endY = y-1; endY >= 0; endY-- ) {
                                if ( board[x,endY] == 0 ) {
                                    continue; // 空セルなら、さらに移動先を探索
                                }
 
                                // 空セルで無ければ、合体or衝突させる
                                if ( targetCellVal == board[x,endY] ) {
                                    // 同じ値なら合体
                                    board[x,endY] = targetCellVal*2;
                                    board[x,y] = 0;
                                    isMoved = true;
                                    break;
                                } else {
                                    // 異なる値なら1つ手前のところまで移動
                                    board[x,endY+1] = targetCellVal;
                                    board[x,y] = 0;
                                    isMoved = true;
                                    break;
                                }                                                           
                            }
                            if ( isMoved == false ) {
                                // 壁まできたら、壁まで移動
                                board[x,0] = targetCellVal;
                                board[x,y] = 0;
                                break;
                            }
 
                        }
                    }
 
                    //txtLog.Text = "[UP]";
                    break;
                case Keys.Down:
                    //txtLog.Text = "[DOWN]";
                    break;
                case Keys.Left:
                    //txtLog.Text = "[LEFT]";
                    break;
                case Keys.Right:
                    //txtLog.Text = "[RIGHT]";
                    break;
                default:
                    //txtLog.Text = "";
                    break;
            }
        }
 
    }
}

関連記事

コメントを残す

メールアドレスが公開されることはありません。