Volatile memory

物覚えの悪いわたしの、備忘録的な技術系ブログです。

ここで悔い改める2024。

ところでこのブログ、markdownで書けるんだって。知らんかった。 というわけで今回からmarkdownで書いていこうと思います。 技術系っぽくなってきた!

うまくいかなかったらもとに戻るんですけどね。

技術系っぽいついでに、きのう書いたコード、リファクタリングしてみましょう。 たぶん、リファクタリングのとこに下線がついて勝手に説明とかいけるようになるんですよね。 ブログって便利ですね。

きのう書いたヨットですが、たったあれだけで一応必要なことはできるような気がして、あー単純なのに楽しいゲームだな―ということで安心してほっとくのが世の慣わしという気もします。

でもでもでも、そこは新年。悔い改めるとかにちょうどいいじゃないですか。ここはリファクタリングして、美しいコードを目指しましょう。そうしましょう。今年からはちゃんとした技術系ブログです。縞パンがどうとか過去の話です。

問題点を上げてみましょう。

  • モデルとビューが分離されてない。
  • コピペくさい繰り返しが多い。
  • いらんとこまでプラットフォームに依存し過ぎ。

まずはモデルというかビジネスじゃないけどビジネスロジックを分離します。

    public class Dice
    {
        public int Value;
        public bool Keep;
        Random Random = new Random();

        public void Reset()
        {
            Value = 0;
            Keep = false;
        }

        public void Roll()
        {
            if (!Keep)
            {
                Value = Random.Next(1, 7);
            }
        }
    }

    public class Yacht
    {
        public int Rest;
        public Dice[] Dice = new Dice[5];

        public Yacht()
        {
            for (int i = 0; i < 5; i++)
            {
                Dice[i] = new Dice();
            }
            Reset();
        }

        public void Reset()
        {
            Rest = 3;
            foreach(var die in Dice)
            {
                die.Reset();
            }
        }

        public void Roll()
        {
            foreach(var die in Dice)
            {
                die.Roll();
            }

            -- Rest;
        }
    }

サイコロクラスとヨットクラスです。 サイコロとは、値を持ち、キープすることができて、転がすと1から6のランダムな整数値を取る。キープしてると値は更新されないと、わりと宣言的に書いてあるつもりです。 ヨットとは、残り回数とサイコロ5個を持ち、リセットすると初期状態に、転がすと5個のサイコロを振り、残り回数を減らすもの。と定義します。 先頭にusingがありません。つまりプラットフォーム依存もほぼないということです。

あとはこれの中身を表示するビューを、Formをいじって定義すればいいですね。MVC的にいうとVとCのとこになるのかと思います。

    public partial class YachtForm : Form
    {
        public YachtForm()
        {
            InitializeComponent();
        }

        private Yacht Yacht = new Yacht();
        private Label[] DiceLabels;
        private CheckBox[] KeepCheckBoxes; 

        private string ToDiceString(int i)
        {
            return i == 0 ? "-" : i.ToString();
        }

        private void UpdateView()
        {
            for (int i = 0; i < Yacht.Dice.Length; ++i)
            {
                DiceLabels[i].Text = ToDiceString(Yacht.Dice[i].Value);
            }
            RestLabel.Text = Yacht.Rest.ToString();
        }

        private void RollButton_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < KeepCheckBoxes.Length; ++i)
            {
                Yacht.Dice[i].Keep = KeepCheckBoxes[i].Checked;
            }
            Yacht.Roll();
            UpdateView();
            if (Yacht.Rest == 0)
            {
                RollButton.Enabled = false;
            }
        }

        private void ResetButton_Click(object sender, EventArgs e)
        {
            Yacht.Reset();
            UpdateView();
            foreach (var box in KeepCheckBoxes)
            {
                box.Checked = false;
            }
            RollButton.Enabled = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DiceLabels = new Label[]
            {
                DiceLabel0,
                DiceLabel1,
                DiceLabel2,
                DiceLabel3,
                DiceLabel4,
            };
            KeepCheckBoxes = new CheckBox[]
            {
                KeepCheckBox0,
                KeepCheckBox1,
                KeepCheckBox2,
                KeepCheckBox3,
                KeepCheckBox4,
            };
            UpdateView();
        }
    }

基本的にはビューの状態管理とヨットの呼び出ししかしてません。 えらく長くなってしまうのでなんかきれいになったのかどうなのかいまいち疑問ですね。

はい、今年もこんなもんですが、よろしければお付き合いのほどを…( )

なんかこれ貼り付けるとランキングに参加できるらしいので貼ってみます↓