效果
源码
新建一个winform项目命名为Matching Game,选用.net core 6框架
并把Form1.cs代码修改为
using Timer = System.Windows.Forms.Timer;namespace Matching_Game
{public partial class Form1 : Form{private const int row = 4;private const int col = 4;private TableLayoutPanel panel = new(){RowCount = row,ColumnCount = col,};private Label[,] labels = new Label[row, col];private readonly Random random = new();private readonly List<string> icons = new(){"!", "!", "N", "N", ",", ",", "k", "k","b", "b", "v", "v", "w", "w", "z", "z"};private readonly Timer timer = new(){Interval = 750,};private Label? firstClicked = null;private Label? secondClicked = null;public Form1(){InitializeComponent();InitializeControls();timer.Tick += Timer_Tick;AssignIconsToSquares();}/// <summary>/// 窗体和它的子窗体都开启双缓冲,防止重新开始游戏时重新绘制控件闪屏/// </summary>protected override CreateParams CreateParams{get{CreateParams cp = base.CreateParams;cp.ExStyle |= 0x02000000;return cp;}}/// <summary>/// 初始化控件/// </summary>public void InitializeControls(){#region initialize formText = "Matching Game";Size = new Size(550, 550);StartPosition = FormStartPosition.CenterScreen;Controls.Clear();#endregion#region initialize panelpanel.BackColor = Color.CornflowerBlue;for (int i = 0; i < row; i++){panel.RowStyles.Add(new RowStyle(SizeType.Percent, 25));}for (int j = 0; j < col; j++){panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25));}panel.Dock = DockStyle.Fill;panel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Inset;panel.Padding = new Padding(0, 0, 0, 0);Controls.Add(panel);#endregion#region initialize labelsfor (int i = 0; i < row; i++){for (int j = 0; j < col; j++){Label label = new(){BackColor = Color.CornflowerBlue,ForeColor = Color.CornflowerBlue,AutoSize = false,Dock = DockStyle.Fill,TextAlign = ContentAlignment.MiddleCenter,Font = new Font("Webdings", 64, FontStyle.Regular),//Font = new Font("Times New Roman", 48, FontStyle.Bold),Margin = new Padding(0, 0, 0, 0)};labels[i, j] = label;label.Click += Label_Click;panel.Controls.Add(label);panel.SetCellPosition(label, new TableLayoutPanelCellPosition(j, i));}}#endregion}/// <summary>/// 定时器任务/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Timer_Tick(object? sender, EventArgs e){timer.Stop();CheckForWinner();if (firstClicked != null){firstClicked.ForeColor = firstClicked.BackColor;}if (secondClicked != null){secondClicked.ForeColor = secondClicked.BackColor;}firstClicked = null;secondClicked = null;}/// <summary>/// 标签被点击时触发/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Label_Click(object? sender, EventArgs e){// The timer is only on after two non-matching // icons have been shown to the player, // so ignore any clicks if the timer is runningif (timer.Enabled == true)return;if (sender is Label clickedLabel){// If the clicked label is black, the player clicked// an icon that's already been revealed --// ignore the clickif (clickedLabel.ForeColor == Color.Black)return;// If firstClicked is null, this is the first icon// in the pair that the player clicked, // so set firstClicked to the label that the player // clicked, change its color to black, and returnif (firstClicked == null){firstClicked = clickedLabel;firstClicked.ForeColor = Color.Black;return;}// If the player gets this far, the timer isn't// running and firstClicked isn't null,// so this must be the second icon the player clicked// Set its color to blacksecondClicked = clickedLabel;secondClicked.ForeColor = Color.Black;if (firstClicked.Text == secondClicked.Text){firstClicked = null;secondClicked = null;}// If the player gets this far, the player // clicked two different icons, so start the // timer (which will wait three quarters of // a second, and then hide the icons)timer.Start();}}/// <summary>/// Assign each icon from the list of icons to a random square/// </summary>private void AssignIconsToSquares(){List<string> iList = icons.ToList();// The TableLayoutPanel has 16 labels,// and the icon list has 16 icons,// so an icon is pulled at random from the list// and added to each labelforeach (Control control in panel.Controls){if (control is Label iconLabel){int randomNumber = random.Next(iList.Count);iconLabel.Text = iList[randomNumber];// iconLabel.ForeColor = iconLabel.BackColor;iList.RemoveAt(randomNumber);}}}/// <summary>/// Check every icon to see if it is matched, by /// comparing its foreground color to its background color. /// If all of the icons are matched, the player wins/// </summary>private void CheckForWinner(){// Go through all of the labels in the TableLayoutPanel, // checking each one to see if its icon is matchedforeach (Control control in panel.Controls){if (control is Label iconLabel){if (iconLabel.ForeColor == iconLabel.BackColor)return;}}// If the loop didn’t return, it didn't find// any unmatched icons// That means the user won. Show a message and close the formDialogResult result = MessageBox.Show("You matched all the icons! Restart?", "Congratulations", MessageBoxButtons.YesNo, MessageBoxIcon.Question);if (result != DialogResult.Yes){Close();}else{panel = new TableLayoutPanel() { RowCount = row, ColumnCount = col };labels = new Label[row, col];InitializeControls();AssignIconsToSquares();}}}
}
修改完代码后直接启动即可。
有兴趣可以到微软官网查看相关细节教程:创建匹配游戏 - Visual Studio (Windows) | Microsoft Learn