WPF五子棋开发:棋盘绘制与游戏逻辑实现
1. 项目背景与核心思路五子棋作为一款经典的双人对战棋类游戏其规则简单却蕴含丰富的策略性。使用WPFWindows Presentation Foundation框架开发桌面版五子棋既能锻炼WPF的核心技能又能深入理解游戏逻辑的实现原理。这个系列的第一部分我们将重点解决棋盘绘制、落子逻辑和基础胜负判断这三个核心模块。选择WPF主要基于三点考量首先其矢量图形系统能完美适配不同分辨率的棋盘显示其次数据绑定机制可以优雅地处理游戏状态更新最后MVVM模式能让代码保持良好结构。我在实际开发中发现相比WinFormsWPF在实现这类需要频繁界面更新的应用时性能表现更为稳定。2. 开发环境准备2.1 基础环境配置推荐使用Visual Studio 2022社区版安装时需勾选.NET桌面开发工作负载。新建项目选择WPF应用程序(.NET Core 3.1或更高版本)项目命名建议采用GomokuWPF这样的语义化名称。注意若使用.NET 6/7需特别注意WPF的兼容性包。我在实际项目中遇到过System.Windows.Interactivity引用问题解决方案是手动安装Microsoft.Xaml.Behaviors.Wpf NuGet包。2.2 核心依赖项通过NuGet包管理器安装以下关键库Microsoft.Xaml.Behaviors.Wpf处理UI交互行为PropertyChanged.Fody简化属性通知实现可选MaterialDesignThemes如需现代化UI风格3. 棋盘系统实现3.1 棋盘绘制方案采用Canvas作为棋盘容器通过动态计算实现自适应布局。核心代码示例Canvas x:NameBoardCanvas Background#FFE4C4 SizeChangedBoardCanvas_SizeChanged !-- 网格线将通过代码动态生成 -- /Canvas在代码后台实现网格绘制逻辑private void DrawBoardLines() { double cellSize Math.Min(BoardCanvas.ActualWidth, BoardCanvas.ActualHeight) / 15; // 绘制横线 for (int i 0; i 15; i) { Line line new Line { X1 0, Y1 i * cellSize, X2 BoardCanvas.ActualWidth, Y2 i * cellSize, Stroke Brushes.Black, StrokeThickness i 0 || i 14 ? 2 : 1 }; BoardCanvas.Children.Add(line); } // 绘制竖线类似逻辑 }3.2 棋盘状态建模使用二维数组存储棋盘状态是最直观的方案public enum PieceType { Empty, Black, White } private PieceType[,] _boardState new PieceType[15, 15];但更推荐采用面向对象的方式public class BoardCell : INotifyPropertyChanged { private PieceType _piece; public PieceType Piece { get _piece; set { _piece value; OnPropertyChanged(); } } public int X { get; set; } public int Y { get; set; } // 实现INotifyPropertyChanged... }4. 游戏逻辑实现4.1 落子交互处理通过MouseLeftButtonDown事件捕获点击位置转换为棋盘坐标private void BoardCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Point clickPos e.GetPosition(BoardCanvas); int x (int)(clickPos.X / _cellSize); int y (int)(clickPos.Y / _cellSize); if (x 0 x 15 y 0 y 15 _boardState[x,y] PieceType.Empty) { PlacePiece(x, y, _currentPlayer); if (CheckWin(x, y)) { MessageBox.Show(${_currentPlayer} wins!); ResetGame(); } _currentPlayer _currentPlayer PieceType.Black ? PieceType.White : PieceType.Black; } }4.2 胜负判定算法采用方向向量法实现五连检测private bool CheckWin(int x, int y) { PieceType current _boardState[x,y]; int[,] directions { {1,0}, {0,1}, {1,1}, {1,-1} }; foreach (var dir in directions) { int count 1; for (int i 1; i 5; i) { int nx x i * dir[0], ny y i * dir[1]; if (nx 0 || nx 15 || ny 0 || ny 15 || _boardState[nx,ny] ! current) break; count; } for (int i 1; i 5; i) { int nx x - i * dir[0], ny y - i * dir[1]; if (nx 0 || nx 15 || ny 0 || ny 15 || _boardState[nx,ny] ! current) break; count; } if (count 5) return true; } return false; }5. 性能优化与调试技巧5.1 渲染优化方案使用DrawingVisual替代Shape对象绘制棋子实现棋子的缓存渲染private DrawingVisual CreatePieceVisual(PieceType type) { DrawingVisual visual new DrawingVisual(); using (DrawingContext dc visual.RenderOpen()) { dc.DrawEllipse( type PieceType.Black ? Brushes.Black : Brushes.White, new Pen(Brushes.Black, 1), new Point(_cellSize/2, _cellSize/2), _cellSize*0.4, _cellSize*0.4); } return visual; }5.2 常见问题排查棋子显示位置偏移检查棋盘坐标转换逻辑确认Canvas的RenderTransformOrigin是否设置为(0,0)胜负判断异常边界条件检查数组越界方向向量定义是否正确调试时输出中间计数结果内存泄漏避免频繁创建Visual对象使用WeakEventManager处理事件订阅6. 项目扩展方向虽然当前实现了基础功能但还有多个可优化点实现悔棋功能通过栈结构记录历史步骤添加AI对战采用极小化极大算法实现简单AI网络对战支持通过WCF或SignalR实现联机游戏回放系统记录棋谱并支持复盘我在实际开发中发现当棋盘尺寸超过19x19时原始的二维数组存储方案会明显影响性能。这时可以考虑改用稀疏矩阵或位图压缩等优化方案。另一个实用技巧是在绘制棋子时添加轻微的渐变效果这可以通过LinearGradientBrush实现能显著提升视觉体验。

相关新闻

空间域图像增强实战指南:灰度变换与直方图处理核心原理与调参技巧

空间域图像增强实战指南:灰度变换与直方图处理核心原理与调参技巧

拿到《数字图像处理》第三章“空间域图像增强(灰度变换和直方图处理)”这个标题,很多人的第一反应是翻课本对着公式背,但真正拿到一张模糊、偏暗、对比度极低的图,往往又不知道怎么下手。我当年在某个图像处理Demo项目…

2026/10/15 12:21:56 阅读更多 →
Spring AI实战:构建智能IDE插件的架构与优化

Spring AI实战:构建智能IDE插件的架构与优化

1. 项目背景与核心价值最近在团队内部做代码评审时,发现一个很有意思的现象:即使是经验丰富的Java开发者,在编写某些特定场景的代码时(比如复杂的Stream操作或者Spring事务嵌套),也常常需要反复查阅文档或搜…

2026/10/15 12:21:56 阅读更多 →
解决报错CC Switch local proxy failed while handling Codex endpoint /responses:把 endpoint 改到 TaoToken 的排查

解决报错CC Switch local proxy failed while handling Codex endpoint /responses:把 endpoint 改到 TaoToken 的排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 12:21:56 阅读更多 →

最新新闻

Qt跨数据库获取SQL表字段元数据的工程实践

Qt跨数据库获取SQL表字段元数据的工程实践

1. 项目概述:为什么“获取SQL数据表所有字段”是Qt开发中绕不开的硬需求在用Qt做数据库应用开发时,我几乎每天都会遇到这个场景:界面刚打开,需要动态加载某张表的全部字段名来构建查询条件面板;或者用户点开一个数据编…

2026/10/15 13:01:26 阅读更多 →
页面没有报截断,短屏上确认按钮却消失了:HarmonyOS 7 怎么验关键任务始终可达

页面没有报截断,短屏上确认按钮却消失了:HarmonyOS 7 怎么验关键任务始终可达

页面没有报截断,短屏上确认按钮却消失了:HarmonyOS 7 怎么验关键任务始终可达 DevEco Studio 26.0 场景化体检把“截断”纳入多设备检测,官方多设备指南也明确提醒短屏高度受限时要保证关键区可见并支持滚动。但最难发现的不是文字少一行&am…

2026/10/15 13:01:26 阅读更多 →
AI 卖课博主年入 120 万?程序员用 Cursor 算完这笔账,我沉默了

AI 卖课博主年入 120 万?程序员用 Cursor 算完这笔账,我沉默了

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 13:01:26 阅读更多 →
RetroArch BIOS 资源包:一键补齐多平台模拟器 BIOS 文件

RetroArch BIOS 资源包:一键补齐多平台模拟器 BIOS 文件

简介:这份资源面向复古游戏模拟器玩家与 Retropie、Recalbox、Lakka、Retrobat、EmuVR 等前端使用者,集中提供 libretro 体系所需的系统固件与 BIOS 文件,解决模拟器因缺少底层固件而无法启动或运行异常的问题。压缩包共 262 个文件&#xff…

2026/10/15 13:01:26 阅读更多 →
深入理解context-mode:给AI划边界,让编程更稳定、更省token

深入理解context-mode:给AI划边界,让编程更稳定、更省token

其实最开始我对context-mode这词挺不以为然,觉得不就是“多给AI塞点资料”吗?直到在项目里被坑了好几次,才意识到这观念错得离谱。有一阵子我习惯把项目里相关的文件全部丢给AI代码助手,结果它给的修改建议经常自相矛盾&#xff0…

2026/10/15 13:01:26 阅读更多 →
人脸特征提取三路线:HoG、Dlib与CNN原理及选型指南

人脸特征提取三路线:HoG、Dlib与CNN原理及选型指南

人脸识别这几年从实验室走向了门禁、考勤、相册聚类、甚至手机解锁,几乎成了计算机视觉里最"接地气"的方向之一。但真到动手做项目的时候,很多人会卡在同一个地方:特征到底怎么提?我见过不少朋友一上来就堆深度学习模型…

2026/10/15 13:00:25 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →