C# Winform翻牌子记忆小游戏

news2025/2/27 9:08:50

效果

源码

新建一个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 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1382793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#中的反射(Reflection)使用经典案例

文章目录 1. 动态加载和调用类的方法2. 记录用户修改行为3. 调用私有构造函数4. 泛型类型的动态创建和使用5. 动态类型转换与检查6. 获取和设置私有、受保护成员7. 枚举程序集、模块、类型等信息8. 处理泛型类型参数9. 动态生成代码或动态编译10. 配置驱动的应用程序扩展注意事…

粒子群算法优化RBF神经网络回归分析

目录 完整代码和数据下载链接:粒子群算法优化RBF神经网络回归分析(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88738570 RBF的详细原理 RBF的定义 RBF理论 易错及常见问题 RBF应用实例,基于rbf的空调功率预测 代码 结果分析 展望…

动态规划篇-03:打家劫舍

198、打家劫舍 状态转移方程 base case 边界问题就是&#xff1a;走到最后一间房子门口也没抢&#xff0c;那么最终抢到的金额为0 明确状态 “原问题和子问题中会变化的变量” 抢到的金额数就是状态&#xff0c;因为随着在每一件房子门口做选择&#xff0c;抢到的金额数会随…

Springboot3新特性:开发第一个 GraalVM 本机应用程序(完整教程)

在讲述之前&#xff0c;各位先自行在网上下载并安装Visual Studio 2022&#xff0c;安装的时候别忘了勾选msvc 概述&#xff1a;GraalVM 本机应用程序&#xff08;Native Image&#xff09;是使用 GraalVM 的一个特性&#xff0c;允许将 Java 应用程序编译成本机二进制文件&am…

VS2019中解决一些配置问题

一、取消一堆冗余的C语法告警 1.点击项目最下面的属性栏 2.选择代码分析&#xff0c;点击常规&#xff0c;将其中的设置全部改为否&#xff0c;确定即可

GRE隧道(初级VPN)配置步骤

一、拓朴图&#xff1a; 二、配置步骤&#xff1a; 1、配置IP 2、R1、R2 配置nat&#xff0c;代理内网地址通过G0/0/0口上外网 acl 2000rule permit source anyquit # int G0/0/0ip addr 100.1.1.1 24nat outbound 2000 # 3、R1、R2 配置默认出口路由G0/0/0&#xff0c;这一…

【开源】基于JAVA+Vue+SpringBoot的桃花峪滑雪场租赁系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设计3.1 教练表3.2 教练聘请表3.3 押金规则表3.4 器材表3.5 滑雪场表3.7 售票表3.8 器材损坏表 四、系统展示五、核心代码5.1 查询教练5.2 教练聘请5.3 查询滑雪场5.4 滑雪场预定5.5 新…

高斯Hack算法

背景 刷leetcode时&#xff0c;碰到一题需要求解n个bit中选择m个bit的所有组合集&#xff0c;我只想到了递归求解&#xff0c;没啥问题&#xff0c;但是在官方题解中看到了牛逼的方法(Gospers Hack)&#xff0c;故记录一下。 4bit中2个1的情况 0011b0101b0110b1001b1010b1100b…

第 380 场周赛 解题报告 | 珂学家 | 数位DP 二分 + 字符串Hash

前言 整体评价 感觉T3更难些&#xff0c;T4太直接了&#xff0c;一般的KMP/StringHash基本就够用了。 上周T4出数位DP&#xff0c;估计是为T3打了一个铺垫。 A. 最大频率元素计数 思路: 模拟即可 class Solution {public int maxFrequencyElements(int[] nums) {Map<Int…

Day29 131分割回文串 93复原ip地址

131分割回文串 给定一个字符串 s&#xff0c;将 s 分割成一些子串&#xff0c;使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ] class Solution …

大数据深度学习卷积神经网络CNN:CNN结构、训练与优化一文全解

文章目录 大数据深度学习卷积神经网络CNN&#xff1a;CNN结构、训练与优化一文全解一、引言1.1 背景和重要性1.2 卷积神经网络概述 二、卷积神经网络层介绍2.1 卷积操作卷积核与特征映射卷积核大小多通道卷积 步长与填充步长填充 空洞卷积&#xff08;Dilated Convolution&…

ST工具Flash Loader烧写STM32

简介 使用ST公司自家的Flash Loader烧写程序&#xff0c; 如下图, F103直接接USART1到PC端就好, 使用普通的USB转TTL线&#xff0c; 就是你之前使用串口打印的方式连接到电脑就好。 软件下载 ST Flash Loader 我放到CSDN里面了Flash_Loader_demo_v2.8.0 开发板设置 Boot0-&g…

泊松流生成模型简介

一、说明 泊松流生成模型 (PFGM) 是一种新型的生成深度学习模型&#xff0c;与扩散模型类似&#xff0c;其灵感来自物理学。在这本简单易懂的指南中了解 PFGM 背后的理论以及如何使用它们生成图像。 生成式人工智能模型在过去几年中取得了长足的进步。受物理启发的扩散…

别再用老掉牙的技术了!试试微服务架构!从零教你认识、开发、部署微服务

从0带你认识、开发、部署微服务&#xff08;一&#xff09; 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.目标 微服务架构的优缺点…

Spring Boot 3 + Vue 3实战:实现用户登录功能

文章目录 一、实战概述二、实战步骤​&#xff08;一&#xff09;创建后端项目1、创建Spring Boot项目2、启动应用&#xff0c;访问首页 &#xff08;二&#xff09;创建前端项目1、创建Vue项目2、安装axios模块3、安装vue-router模块4、安装less和less-loader模块5、运行Vue项…

远程开发之端口转发

远程开发之端口转发 涉及的软件forwarded port 通过端口转发&#xff0c;实现在本地电脑上访问远程服务器上的内网的服务。 涉及的软件 vscode、ssh forwarded port 在ports界面中的port字段&#xff0c;填需要转发的IP:PORT&#xff0c;即可转发远程服务器中的内网端口到本…

LeetCode刷题(ACM模式)-05栈与队列

参考引用&#xff1a;代码随想录 注&#xff1a;每道 LeetCode 题目都使用 ACM 代码模式&#xff0c;可直接在本地运行&#xff0c;蓝色字体为题目超链接 0. 栈与队列理论基础 21天学通C读书笔记&#xff08;二十三&#xff1a;自适应容器&#xff1a;栈和队列&#xff09; 堆…

Bean作用域及生命周期

关于Bean对象&#xff0c;在将其存储到spring中以后&#xff0c;在使用或读取该Bean对象时&#xff0c;如果该对象是公有的&#xff0c;难免就会出现被一方修改&#xff0c;从而影响另外一方读取到的对象准确性的情况。因此了解Bean的作用域和生命周期就是十分必要的了。 首先…

一、MySQL 卸载

目录 1、软件的卸载准备 2、软件的卸载 方式一&#xff1a;通过控制面板卸载 方式二&#xff1a;通过mysql8的安装向导卸载 1、双击mysql8的安装向导 2、取消更新 3、选择要卸载的mysql服务器软件的具体版本 4、确认删除数据目录 5、执行删除 6、完成删除 3、清理残…

Springboot中使用Filter过滤器

1、概述 springboot工程中使用Filter过滤器与其他地方使用基本相同&#xff0c;只是注入的方式不同。 2、创建Filter过滤器 实现Filter接口&#xff0c;重写doFilter方法 filterChain.doFilter(servletRequest,servletResponse);表示放行 public class MyFilter implement…