はじめに
今回は「検証ボタン」と「新規入力ボタン」を実装します。「検証ボタン」は入力された問題が適切がどうか検証するためのものです。問題を解く前に実行するようにします。C#コード
まずはGUIのためのファイル(settings.cs)に以下を追加しました。newBtn.Click += New_Click;
kensyoBtn.Click += Kensyo_Click;
solveBtn.Enabled = false;
最終的にはsettings.csはこのようになっています。
using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { FlowLayoutPanel flp1 = new FlowLayoutPanel(); TableLayoutPanel tlp1 = new TableLayoutPanel(); Button[] numberBtn = new Button[81]; Button dummyBtn = new Button(); Button newBtn = new Button(); Button kensyoBtn = new Button(); Button solveBtn = new Button(); private void Form1_load(object sender, EventArgs e) { int[] btn_position = { 0, 1, 2, 4, 5, 6, 8, 9, 10 }; Text = "solver"; for (int i = 0; i < 3; i++) { tlp1.RowStyles.Add(new RowStyle(SizeType.Percent, 11f)); tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11f)); } tlp1.RowStyles.Add(new RowStyle(SizeType.Percent, .5f)); tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, .5f)); for (int i = 0; i < 3; i++) { tlp1.RowStyles.Add(new RowStyle(SizeType.Percent, 11f)); tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11f)); } tlp1.RowStyles.Add(new RowStyle(SizeType.Percent, .5f)); tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, .5f)); for (int i = 0; i < 3; i++) { tlp1.RowStyles.Add(new RowStyle(SizeType.Percent, 11f)); tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11f)); } tlp1.Size = new Size(TLPSize, TLPSize); for (int i = 0; i < 81; i++) { numberBtn[i] = new Button(); numberBtn[i].Text = ""; numberBtn[i].Dock = DockStyle.Fill; numberBtn[i].Margin = new Padding(0); numberBtn[i].Font = buttonFont; numberBtn[i].Click += ClicknumberBtn; tlp1.Controls.Add(numberBtn[i], btn_position[i % 9], btn_position[i / 9]); } SetClientSizeCore(TLPSize + FLPWidth, TLPSize); Controls.Add(tlp1); flp1.Width = FLPWidth; flp1.Dock = DockStyle.Right; flp1.FlowDirection = FlowDirection.BottomUp; Controls.Add(flp1); dummyBtn.Size = new Size(flp1.Width, 0); newBtn.AutoSize = true; newBtn.Font = buttonFont; newBtn.Text = "新規入力"; newBtn.Width = (int)(flp1.Width * 0.9); newBtn.Anchor = AnchorStyles.None; newBtn.Click += New_Click; kensyoBtn.AutoSize = true; kensyoBtn.Font = buttonFont; kensyoBtn.Text = "検証"; kensyoBtn.Width = newBtn.Width; kensyoBtn.Anchor = AnchorStyles.None; kensyoBtn.Click += Kensyo_Click; solveBtn.AutoSize = true; solveBtn.Font = buttonFont; solveBtn.Text = "実行"; solveBtn.Width = newBtn.Width; solveBtn.Anchor = AnchorStyles.None; solveBtn.Enabled = false; flp1.Controls.Add(dummyBtn); flp1.Controls.Add(newBtn); flp1.Controls.Add(solveBtn); flp1.Controls.Add(kensyoBtn); } } }
いよいよクリックイベントの中身を実装していきます。
コードはメインファイル(Form1.cs)に書きました。
まずは以下を追加しました。
using System.Linq;
private readonly int[] box_start = { 0, 3, 6, 27, 30, 33, 54, 57, 60 }; private readonly int[] box_offset = { 0, 1, 2, 9, 10, 11, 18, 19, 20 };
int[] kazu = new int[81];
検証ボタンの実装
private void Kensyo_Click(object sender, EventArgs e) { int d; for (int i = 0; i < 81; i++) { int.TryParse(numberBtn[i].Text, out d); kazu[i] = d; } if (Kensyo_do()) { solveBtn.Enabled = true; kensyoBtn.Enabled = false; foreach (Button btn in numberBtn) { btn.Enabled = false; } } else { MessageBox.Show("入力が不適です", "結果" , MessageBoxButtons.OK, MessageBoxIcon.Information); } } private bool Kensyo_do() { int[] box_test = new int[9]; int[] row_test = new int[9]; int[] col_test = new int[9]; for (int i = 0; i < 9; i++) { for (int ii = 0; ii < 9; ii++) { box_test[ii] = kazu[box_start[i] + box_offset[ii]]; row_test[ii] = kazu[i * 9 + ii]; col_test[ii] = kazu[i + ii * 9]; } if (box_test.Where(c => c > 0).Count() != box_test.Where(c => c > 0).Distinct().Count()) { return false; } if (row_test.Where(c => c > 0).Count() != row_test.Where(c => c > 0).Distinct().Count()) { return false; } if (col_test.Where(c => c > 0).Count() != col_test.Where(c => c > 0).Distinct().Count()) { return false; } } return true; }
新規入力ボタンの実装
private void New_Click(object sender, EventArgs e) { foreach (Button btn in numberBtn) { btn.Enabled = true; btn.Text = ""; } kensyoBtn.Enabled = true; solveBtn.Enabled = false; }
最終的にはForm1.csはこのようになっています。
using System; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { private const int TLPSize = 400; private const int FLPWidth = 150; public static Font buttonFont = new Font("游ゴシック", 12); private readonly int[] box_start = { 0, 3, 6, 27, 30, 33, 54, 57, 60 }; private readonly int[] box_offset = { 0, 1, 2, 9, 10, 11, 18, 19, 20 }; int[] kazu = new int[81]; public Form1() { Load += Form1_load; } private void ClicknumberBtn(object sender, EventArgs e) { if (((Button)sender).Text == "") { InputForm input = new InputForm(); int Form1_x = Left; int Form1_y = Top; int x_min = ((Button)sender).Left; int y_min = ((Button)sender).Top; int width_half = ((Button)sender).Width / 2; input.Left = Form1_x + x_min + width_half; input.Top = Form1_y + y_min + width_half; input.StartPosition = FormStartPosition.Manual; input.ShowDialog(); ((Button)sender).Text = input.result; input.Dispose(); } else { ((Button)sender).Text = ""; } } private void Kensyo_Click(object sender, EventArgs e) { int d; for (int i = 0; i < 81; i++) { int.TryParse(numberBtn[i].Text, out d); kazu[i] = d; } if (Kensyo_do()) { solveBtn.Enabled = true; kensyoBtn.Enabled = false; foreach (Button btn in numberBtn) { btn.Enabled = false; } } else { MessageBox.Show("入力が不適です", "結果" , MessageBoxButtons.OK, MessageBoxIcon.Information); } } private bool Kensyo_do() { int[] box_test = new int[9]; int[] row_test = new int[9]; int[] col_test = new int[9]; for (int i = 0; i < 9; i++) { for (int ii = 0; ii < 9; ii++) { box_test[ii] = kazu[box_start[i] + box_offset[ii]]; row_test[ii] = kazu[i * 9 + ii]; col_test[ii] = kazu[i + ii * 9]; } if (box_test.Where(c => c > 0).Count() != box_test.Where(c => c > 0).Distinct().Count()) { return false; } if (row_test.Where(c => c > 0).Count() != row_test.Where(c => c > 0).Distinct().Count()) { return false; } if (col_test.Where(c => c > 0).Count() != col_test.Where(c => c > 0).Distinct().Count()) { return false; } } return true; } private void New_Click(object sender, EventArgs e) { foreach (Button btn in numberBtn) { btn.Enabled = true; btn.Text = ""; } kensyoBtn.Enabled = true; solveBtn.Enabled = false; } } }
これで後は問題を解くためのコードを書くのみとなりました。
前回までの記事
【C#】【Windowsフォームアプリケーション】5年ぶりに数独を解く Part 1【C#】【Windowsフォームアプリケーション】5年ぶりに数独を解く Part 2