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实现能显著提升视觉体验。