五子棋作为经典策略游戏,结合Blazor框架开发成Web应用是个绝佳的技术实践。本文将完整呈现从零开始构建一个功能完善的Blazor五子棋应用的全过程,包含AI对战、难度调节等进阶功能实现。
首先需要安装.NET SDK和Visual Studio开发环境。推荐使用.NET 8.0及以上版本,它提供了最新的Blazor功能支持。创建项目时选择"Blazor Web App"模板,在高级配置中勾选"Interactive render mode"选项,这将为我们提供客户端交互能力。
提示:开发过程中建议将渲染模式设为InteractiveServer,这样可以利用服务端调试优势,避免初期开发时频繁的客户端刷新。
五子棋的核心是15×15的棋盘,我们用二维数组表示棋盘状态:
csharp复制const int BoardSize = 15;
int[,] board = new int[BoardSize, BoardSize]; // 0:空 1:黑子 2:白子
int currentPlayer = 1; // 当前玩家
在Razor组件中,我们使用双层循环渲染棋盘格子:
html复制@for (int y = 0; y < BoardSize; y++) {
@for (int x = 0; x < BoardSize; x++) {
<div @onclick="() => PlacePiece(x,y)"
style="background:@GetCellBg(x,y)">
@if (board[x,y] == 1) { ● }
else if (board[x,y] == 2) { ○ }
</div>
}
}
这里有个关键细节:Blazor的事件处理会捕获循环变量,必须创建局部变量副本:
csharp复制int _x = x; // 创建局部副本
int _y = y;
@onclick="@(() => PlacePiece(_x, _y))"
PlacePiece方法处理玩家落子:
csharp复制void PlacePiece(int x, int y) {
if (board[x,y] != 0) return; // 已有棋子
board[x,y] = currentPlayer;
if (CheckWin(x,y)) {
// 获胜处理
} else {
currentPlayer = 3 - currentPlayer; // 切换玩家
}
}
胜负判断通过CheckWin方法实现,检查四个方向是否连成五子:
csharp复制bool CheckWin(int x, int y) {
int[][] directions = { new[]{1,0}, new[]{0,1}, new[]{1,1}, new[]{1,-1} };
foreach (var dir in directions) {
int count = 1;
count += CountDirection(x,y, dir[0], dir[1]);
count += CountDirection(x,y, -dir[0], -dir[1]);
if (count >= 5) return true;
}
return false;
}
为增加游戏性,我们添加得分统计功能:
csharp复制int blackScore = 0;
int whiteScore = 0;
// 在获胜时更新分数
if (winner == 1) blackScore++;
else if (winner == 2) whiteScore++;
同时添加重置分数功能:
html复制<button @onclick="ResetScore">重置得分</button>
@code {
void ResetScore() {
blackScore = 0;
whiteScore = 0;
}
}
首先实现随机落子的简单AI:
csharp复制async Task AITurnAsync() {
await Task.Delay(500); // 模拟思考时间
var empty = GetAllEmptyPositions();
var (x,y) = empty[rand.Next(empty.Count)];
board[x,y] = 2; // 白子落子
if (CheckWin(x,y)) {
whiteScore++;
} else {
currentPlayer = 1; // 切换回玩家
}
}
随机AI过于简单,我们实现基于评分的智能AI:
csharp复制(int, int) FindBestMove() {
var bestMoves = new List<(int x, int y)>();
int maxScore = int.MinValue;
foreach (var (x,y) in GetAllEmptyPositions()) {
int score = EvaluatePosition(x, y, 2); // AI进攻评分
score = Math.Max(score, EvaluatePosition(x, y, 1)); // 防守评分
if (score > maxScore) {
maxScore = score;
bestMoves.Clear();
bestMoves.Add((x,y));
} else if (score == maxScore) {
bestMoves.Add((x,y));
}
}
return bestMoves[rand.Next(bestMoves.Count)];
}
评分函数考虑多种棋型:
csharp复制int EvaluatePosition(int x, int y, int player) {
int score = 0;
int opponent = 3 - player;
foreach (var dir in directions) {
// 进攻评分
int count = CountLine(x,y,dir,player);
if (count >= 5) score += 10000;
else if (count == 4) score += 1000;
// 更多评分规则...
// 防守评分
int oppCount = CountLine(x,y,dir,opponent);
if (oppCount >= 5) score += 9000;
// 更多防守评分...
}
return score;
}
通过调整评分权重实现不同难度:
csharp复制int aiLevel = 1; // 0:简单 1:中等 2:困难
int EvaluatePosition(int x, int y, int player) {
int[] winWeights = [100, 10000, 100000]; // 不同难度获胜权重
// 使用aiLevel索引权重数组
if (count >= 5) score += winWeights[aiLevel];
// ...
}
添加模式切换功能:
csharp复制bool isHumanVsAI = true;
void PlacePiece(int x, int y) {
// 人机模式下阻止AI方手动落子
if (isHumanVsAI && currentPlayer == 2) return;
// ...正常落子逻辑
}
void ToggleMode() {
isHumanVsAI = !isHumanVsAI;
RestartGame();
}
完善游戏界面显示:
html复制<div class="game-info">
<div>当前玩家: <strong>@GetPlayerName()</strong></div>
<div>黑方得分: @blackScore | 白方得分: @whiteScore</div>
<div class="controls">
<button @onclick="RestartGame">重新开始</button>
<button @onclick="ResetScore">重置得分</button>
</div>
</div>
@code {
string GetPlayerName() {
return currentPlayer == 1 ? "黑方" :
(isHumanVsAI ? "白方(电脑)" : "白方");
}
}
html复制<Virtualize Items="@board">
<ItemContent Context="cell">
<!-- 只渲染可视区域的格子 -->
</ItemContent>
</Virtualize>
csharp复制Parallel.ForEach(emptyPositions, pos => {
var score = EvaluatePosition(pos.x, pos.y, 2);
// ...
});
csharp复制// 错误写法:会捕获循环变量
@onclick="@(() => PlacePiece(x,y))"
// 正确写法:创建局部副本
@{
int _x = x;
int _y = y;
@onclick="@(() => PlacePiece(_x,_y))"
}
csharp复制// 需要手动刷新UI时调用
StateHasChanged();
最终项目的核心文件结构如下:
code复制Gomoku/
├── Pages/
│ ├── Index.razor # 主游戏界面
│ └── Index.razor.cs # 游戏逻辑代码
├── Shared/
│ ├── MainLayout.razor # 布局文件
│ └── NavMenu.razor # 导航菜单
└── wwwroot/
├── css/ # 样式文件
└── js/ # 可选JavaScript代码
关键代码模块:
这个项目展示了如何利用Blazor构建交互式Web游戏,涵盖了状态管理、算法实现、UI交互等核心开发技能。通过逐步迭代开发,我们从基础功能开始,最终实现了一个功能完善的五子棋游戏。