除了问号基本实现了经典扫雷游戏(WPF)一(需求、思路和按钮代码)
2026/9/5 4:20:49 网站建设 项目流程

摘要:本文分享一个用 WPF 从零实现经典扫雷游戏的思路与代码。作者针对网上现成代码缺少右键排雷、首次点击不踩雷等核心体验的问题,自定义了一个继承自 Button 的 GameBtn 按钮类,通过 Opened 和 Signed 两个依赖属性封装打开与标记逻辑,简化游戏主类设计,并兼顾右键反悔等细节需求。

突然想练手WPF扫雷游戏,先上网查了下有不少,下了几个,没能找到能实现经典扫雷功能的代码,尤其是右键排雷功能,这可是这款游戏的灵魂!还有就是第一次点击应保证不是雷,问号不常用,手速快的不太用,省略也无妨。

一、基本需求

扫雷基本动作就是排雷和标记,比较频繁的动作是对按钮的左击、右击,判断胜利或失败,记录用时,它是一个坐标游戏。

二、基本思路

首先,使用原生Button有较高复杂度,打开判断、标记和周围雷数都需要数组记录,好多都是这样做的,所以,我做了个新类,继承自Button,添加两个属性Opened和Signed,把背景色变更和标记动作放在里面,简化了游戏类的设计。

其次,本游戏玩复杂度较低,但逻辑复杂度较高,需要考虑多种情况,比如,右键排雷,如果玩家右键按下后发现不对,有一个反悔的需求,怎么设计?布雷看着有难度,其实就几行代码,只是理解有难度而已。

三、基本代码

一是按钮类:

public class GameBtn : Button { public static readonly DependencyProperty OpenedProperty; public static readonly DependencyProperty SignedProperty; public bool Opened { get { return (bool)GetValue(OpenedProperty); } set { SetValue(OpenedProperty, BooleanBoxes.Box(value)); } } public bool Signed { get { return (bool)GetValue(SignedProperty); } set { SetValue(SignedProperty, BooleanBoxes.Box(value)); } } internal static class BooleanBoxes { internal static object TrueBox = true; internal static object FalseBox = false; internal static object Box(bool value) { if (value) return TrueBox; else return FalseBox; } } static GameBtn() { OpenedProperty = DependencyProperty.Register("Opened", typeof(bool), typeof(GameBtn), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, OnOpenedChanged)); SignedProperty = DependencyProperty.Register("Signed", typeof(bool), typeof(GameBtn), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, OnSignedChanged)); } private static void OnSignedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is GameBtn button) { if (button.Opened) { return;//已点开不操作 } else if (button.Signed) { button.Content = "🚩"; button.Foreground = Brushes.Red; } else { button.Content = null; button.Foreground = Brushes.LightGray; } } } private static void OnOpenedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is GameBtn button) { if (button.Opened) { button.Background = Brushes.LightYellow; } else { button.Background = Brushes.LightGray; } } } protected override AutomationPeer OnCreateAutomationPeer() { return new ButtonAutomationPeer(this); } protected override void OnClick() { if (AutomationPeer.ListenerExists(AutomationEvents.InvokePatternOnInvoked)) { UIElementAutomationPeer.CreatePeerForElement(this)?.RaiseAutomationEvent(AutomationEvents.InvokePatternOnInvoked); } if (!Opened)//已点开左击无效 { base.OnClick(); } } }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询