效果
源码
新建一个winform项目命名为Matching Game,选用.net core 6框架
并把Form1.cs代码修改为
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 form
Text = "Matching Game";
Size = new Size(550, 550);
StartPosition = FormStartPosition.CenterScreen;
Controls.Clear();
#endregion
#region initialize panel
panel.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 labels
for (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 running
if (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 click
if (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 return
if (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 black
secondClicked = 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 label
foreach (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 matched
foreach (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 form
DialogResult 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