开源地址
源码g01Gobang
demo
https://game.app1.es 用blazor auto发布的
1. 创建 Blazor web工程,选Auto
2. 打开 GitHub Copilot 窗口,输入提示词
使用 Blazor 编一个五子棋游戏
3.复制代码测试
为了方便调试, 我们先把运行模式由 InteractiveAuto 改为 InteractiveServer
打开 App.razor 编辑 两行 @rendermode="InteractiveAuto" 改为 @rendermode="InteractiveServer"
4.不出意外, 代码出现了意外
无脑使用AI修复一下
结果发现不是这个问题. 是逻辑代码 @ 问题. 原因是PlacePiece闭包捕获的 x、y 是当前循环的值
既然人工发现了问题, 我们继续提醒一下AI, 尝试修复
最后还是没修复成功, 手动处理一下- @page "/"
- <PageTitle>五子棋</PageTitle>
- <h1>五子棋游戏</h1>
- 当前玩家: <b>@(currentPlayer == 1 ? "黑子" : "白子")</b>
- @if (winner != 0)
- {
- 胜者: @(winner == 1 ? "黑子" : "白子")
- <button @onclick="Restart">重新开始</button>
- }
- <table >
- @for (int y = 0; y < BoardSize; y++)
- {
- <tr>
- @for (int x = 0; x < BoardSize; x++)
- {
- int _x = x;
- int _y = y;
- <td
- @onclick="@(() => PlacePiece(_x, _y))">
- @if (board[x, y] == 1)
- {
- ●
- }
- else if (board[x, y] == 2)
- {
- ●
- }
- </td>
- }
- </tr>
- }
- </table>
- @code {
- const int BoardSize = 15;
- int[,] board = new int[BoardSize, BoardSize];
- int currentPlayer = 1; // 1: 黑子, 2: 白子
- int winner = 0;
- void PlacePiece(int x, int y)
- {
- // 修复:增加边界检查,防止越界
- if (x < 0 || x >= BoardSize || y < 0 || y >= BoardSize)
- return;
- if (winner != 0 || board[x, y] != 0)
- return;
- board[x, y] = currentPlayer;
- if (CheckWin(x, y, currentPlayer))
- {
- winner = currentPlayer;
- }
- else
- {
- currentPlayer = 3 - currentPlayer; // 切换玩家
- }
- }
- bool CheckWin(int x, int y, int player)
- {
- int[][] directions = new int[][]
- {
- new int[]{1,0}, // 横
- new int[]{0,1}, // 竖
- new int[]{1,1}, // 斜
- new int[]{1,-1} // 反斜
- };
- foreach (var dir in directions)
- {
- int count = 1;
- count += CountDirection(x, y, dir[0], dir[1], player);
- count += CountDirection(x, y, -dir[0], -dir[1], player);
- if (count >= 5)
- return true;
- }
- return false;
- }
- int CountDirection(int x, int y, int dx, int dy, int player)
- {
- int count = 0;
- for (int step = 1; step < 5; step++)
- {
- int nx = x + dx * step;
- int ny = y + dy * step;
- if (nx < 0 || nx >= BoardSize || ny < 0 || ny >= BoardSize)
- break;
- if (board[nx, ny] == player)
- count++;
- else
- break;
- }
- return count;
- }
- void Restart()
- {
- board = new int[BoardSize, BoardSize];
- currentPlayer = 1;
- winner = 0;
- }
- string GetCellBg(int x, int y)
- {
- return (x + y) % 2 == 0 ? "#f9d77e" : "#eac066";
- }
- }
复制代码 说明:
- 添加 int _x = x; int _y = y; 确保闭包捕获的 _x、_y 是当前循环的值,避免 Blazor 渲染时闭包变量引用错误。
- 在 PlacePiece 方法开头增加边界检查,防止非法坐标导致数组越界异常。
这样可以彻底修复 PlacePiece 拿到的变量不正确和越界的问题。
5. 运行效果
6. 加入显示当前玩家的得分功能
你可以为每个玩家增加一个分数变量,每次有玩家获胜时将其分数加一,并在界面上显示。下面是具体实现方法:
- int blackScore = 0;
- int whiteScore = 0;
复制代码- void PlacePiece(int x, int y)
- {
- if (x < 0 || x >= BoardSize || y < 0 || y >= BoardSize)
- return;
- if (winner != 0 || board[x, y] != 0)
- return;
- board[x, y] = currentPlayer;
- if (CheckWin(x, y, currentPlayer))
- {
- winner = currentPlayer;
- if (winner == 1)
- blackScore++;
- else if (winner == 2)
- whiteScore++;
- }
- else
- {
- currentPlayer = 3 - currentPlayer; // 切换玩家
- }
- }
复制代码- 当前玩家: <b>@(currentPlayer == 1 ? "黑子" : "白子")</b>
- 黑子得分: <b>@blackScore</b>
- 白子得分: <b>@whiteScore</b>
- @if (winner != 0)
- {
- 胜者: @(winner == 1 ? "黑子" : "白子")
- <button @onclick="Restart">重新开始</button>
- }
复制代码 这样每次有玩家获胜时,分数都会自动更新并显示在页面上。
7. 加入<button @onclick="ResetScore">重置得分</button>功能
你可以在 Restart 方法中增加对分数的重置,或者单独添加一个“<button @onclick="ResetScore">重置得分</button>”按钮和方法。推荐做法如下:
- 添加<button @onclick="ResetScore">重置得分</button>方法:
- void ResetScore()
- {
- blackScore = 0;
- whiteScore = 0;
- }
复制代码- <button @onclick="ResetScore">重置得分</button>
复制代码 建议将此按钮放在分数显示附近,例如:- 当前玩家: [b]@(currentPlayer == 1 ? "黑子" : "白子")[/b] 黑子得分: [b]@blackScore[/b] 白子得分: [b]@whiteScore[/b] <button @onclick="ResetScore">重置得分</button> @if (winner != 0) { 胜者: @(winner == 1 ? "黑子" : "白子") 重新开始 }
复制代码 这样点击“<button @onclick="ResetScore">重置得分</button>”按钮即可将分数清零。
8. 在这个五子棋游戏中添加 AI 对手功能
在你的 Blazor 五子棋游戏中添加 AI 对手功能,常见做法是让一方(如白子)由 AI 自动落子。实现思路如下:
- 判断当前玩家是否为 AI:如 currentPlayer == 2 时,自动调用 AI 落子逻辑。
- 实现 AI 落子算法:可以先用简单的随机落子,后续可扩展为更智能的算法。
- 在玩家落子后自动触发 AI 落子:用 StateHasChanged() 刷新界面,必要时用 await Task.Delay() 增加落子延迟。
下面是具体实现方法(以白子为 AI):- @page "/"五子棋[size=6]五子棋游戏[/size]
- 当前玩家: [b]@(currentPlayer == 1 ? "黑子" : "白子(电脑)")[/b] 黑子得分: [b]@blackScore[/b] 白子得分: [b]@whiteScore[/b] <button @onclick="ResetScore">重置得分</button> @if (winner != 0) { 胜者: @(winner == 1 ? "黑子" : "白子(电脑)") 重新开始 }[table] @for (int y = 0; y < BoardSize; y++) { [tr] @for (int x = 0; x < BoardSize; x++) { int _x = x; int _y = y; [td] @if (board[x, y] == 1) { ● } else if (board[x, y] == 2) { ● } [/td] } [/tr] }[/table]@code { const int BoardSize = 15; int[,] board = new int[BoardSize, BoardSize]; int currentPlayer = 1; // 1: 黑子, 2: 白子(电脑) int winner = 0; int blackScore = 0; int whiteScore = 0; Random rand = new(); void PlacePiece(int x, int y) { if (winner != 0 || board[x, y] != 0 || currentPlayer == 2) return; board[x, y] = currentPlayer; if (CheckWin(x, y, currentPlayer)) { winner = currentPlayer; if (winner == 1) blackScore++; else if (winner == 2) whiteScore++; } else { currentPlayer = 2; StateHasChanged(); _ = AITurnAsync(); } } async Task AITurnAsync() { await Task.Delay(500); // AI 落子延迟 if (winner != 0) return; // 简单随机落子 var empty = new List(); for (int i = 0; i < BoardSize; i++) for (int j = 0; j < BoardSize; j++) if (board[i, j] == 0) empty.Add((i, j)); if (empty.Count == 0) return; var (aiX, aiY) = empty[rand.Next(empty.Count)]; board[aiX, aiY] = 2; if (CheckWin(aiX, aiY, 2)) { winner = 2; whiteScore++; } else { currentPlayer = 1; } StateHasChanged(); } // 其余代码不变... bool CheckWin(int x, int y, int player) { int[][] directions = new int[][] { new int[]{1,0}, new int[]{0,1}, new int[]{1,1}, new int[]{1,-1} }; foreach (var dir in directions) { int count = 1; count += CountDirection(x, y, dir[0], dir[1], player); count += CountDirection(x, y, -dir[0], -dir[1], player); if (count >= 5) return true; } return false; } int CountDirection(int x, int y, int dx, int dy, int player) { int count = 0; for (int step = 1; step < 5; step++) { int nx = x + dx * step; int ny = y + dy * step; if (nx < 0 || nx >= BoardSize || ny < 0 || ny >= BoardSize) break; if (board[nx, ny] == player) count++; else break; } return count; } void Restart() { board = new int[BoardSize, BoardSize]; currentPlayer = 1; winner = 0; } void ResetScore() { blackScore = 0; whiteScore = 0; } string GetCellBg(int x, int y) { return (x + y) % 2 == 0 ? "#f9d77e" : "#eac066"; }}
复制代码 要点说明:
- 玩家(黑子)落子后自动触发 AI(白子)落子。
- AI 采用随机空位落子,简单易懂,后续可扩展为更智能算法。
- 若要让 AI 先手,只需将 currentPlayer = 2 并在 OnInitialized 或 Restart 时调用 AITurnAsync()。
用是能用了, 就是这个AI太傻了,继续优化一下
要优化五子棋 AI 的落子策略,可以采用“优先级评分法”来提升难度。基本思路如下:
- 优先考虑能直接获胜的位置(如 AI 连成五子)。
- 阻止玩家获胜(如玩家有四连,AI 必须堵住)。
- 优先进攻(如自己有三连、二连)。
- 其次防守(如玩家有三连、二连)。
- 否则随机或选择评分最高的位置。
下面是一个简单的评分法实现,AI 会优先选择能赢、能防守、能进攻的位置:- async Task AITurnAsync()
- {
- await Task.Delay(500);
- if (winner != 0) return;
- var (aiX, aiY) = FindBestMove();
- board[aiX, aiY] = 2;
- if (CheckWin(aiX, aiY, 2))
- {
- winner = 2;
- whiteScore++;
- }
- else
- {
- currentPlayer = 1;
- }
- StateHasChanged();
- }
- // 简单评分法:优先赢棋、阻挡对方、进攻
- (int, int) FindBestMove()
- {
- int maxScore = int.MinValue;
- var bestMoves = new List<(int x, int y)>();
- for (int x = 0; x < BoardSize; x++)
- {
- for (int y = 0; y < BoardSize; y++)
- {
- if (board[x, y] != 0) continue;
- int score = EvaluatePoint(x, y, 2); // AI进攻
- score = Math.Max(score, EvaluatePoint(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)];
- }
- // 评分函数:可根据实际需要调整权重
- int EvaluatePoint(int x, int y, int player)
- {
- int score = 0;
- int opponent = player == 1 ? 2 : 1;
- // 检查4连、3连、2连等
- foreach (var dir in new[] { (1, 0), (0, 1), (1, 1), (1, -1) })
- {
- int count = 1 + CountDirection(x, y, dir.Item1, dir.Item2, player)
- + CountDirection(x, y, -dir.Item1, -dir.Item2, player);
- if (count >= 5) score += 10000; // 直接获胜
- else if (count == 4) score += 1000;
- else if (count == 3) score += 100;
- else if (count == 2) score += 10;
- // 防守分数
- int oppCount = 1 + CountDirection(x, y, dir.Item1, dir.Item2, opponent)
- + CountDirection(x, y, -dir.Item1, -dir.Item2, opponent);
- if (oppCount >= 5) score += 9000; // 必须防守
- else if (oppCount == 4) score += 900;
- else if (oppCount == 3) score += 90;
- else if (oppCount == 2) score += 9;
- }
- return score;
- }
复制代码 集成方法:
- 替换你的 AITurnAsync 方法为上述实现。
- 在 @code 区域添加 FindBestMove 和 EvaluatePoint 方法。
- 可根据实际效果调整评分权重。
效果说明:
- AI 会优先选择能赢的位置,其次堵住玩家的四连,再考虑进攻和防守三连、二连。
- 这种评分法简单高效,能显著提升 AI 难度。
- 若需更高难度,可进一步实现“活三”、“活四”识别、双向评分、甚至 Minimax 算法。
9. 添加难度切换按钮
添加三个难度选择按钮以及切换人机按钮
下面是实现“三个难度选择按钮(简单、中等、困难)”和“人机/人人切换按钮”的完整方法。
难度通过调整 AI 的评分权重实现,人机切换通过 isHumanVsAI 控制。请直接替换你的 Home.razor 文件内容:- @page "/"五子棋[size=6]五子棋游戏[/size]
- [b]难度:[/b] 简单 中等 困难 [b]模式:[/b] @(isHumanVsAI ? "人机对战" : "人人对战") 当前玩家: [b]@(currentPlayer == 1 ? "黑子" : (isHumanVsAI ? "白子(电脑)" : "白子"))[/b] 黑子得分: [b]@blackScore[/b] 白子得分: [b]@whiteScore[/b] <button @onclick="ResetScore">重置得分</button> @if (winner != 0) { 胜者: @(winner == 1 ? "黑子" : (isHumanVsAI ? "白子(电脑)" : "白子")) 重新开始 }[table] @for (int y = 0; y < BoardSize; y++) { [tr] @for (int x = 0; x < BoardSize; x++) { int _x = x; int _y = y; [td] @if (board[x, y] == 1) { ● } else if (board[x, y] == 2) { ● } [/td] } [/tr] }[/table]@code { const int BoardSize = 15; int[,] board = new int[BoardSize, BoardSize]; int currentPlayer = 1; // 1: 黑子, 2: 白子(电脑/玩家) int winner = 0; int blackScore = 0; int whiteScore = 0; Random rand = new(); bool isHumanVsAI = true; int aiLevel = 1; // 0:简单 1:中等 2:困难 void PlacePiece(int x, int y) { if (winner != 0 || board[x, y] != 0) return; // 人机模式下,只有当前为玩家时可落子 if (isHumanVsAI && currentPlayer == 2) return; board[x, y] = currentPlayer; if (CheckWin(x, y, currentPlayer)) { winner = currentPlayer; if (winner == 1) blackScore++; else if (winner == 2) whiteScore++; } else { currentPlayer = 3 - currentPlayer; if (isHumanVsAI && currentPlayer == 2 && winner == 0) { StateHasChanged(); _ = AITurnAsync(); } } } async Task AITurnAsync() { await Task.Delay(500); if (winner != 0) return; var (aiX, aiY) = FindBestMove(); board[aiX, aiY] = 2; if (CheckWin(aiX, aiY, 2)) { winner = 2; whiteScore++; } else { currentPlayer = 1; } StateHasChanged(); } (int, int) FindBestMove() { if (aiLevel == 0) { // 简单:随机落子 var empty = new List(); for (int i = 0; i < BoardSize; i++) for (int j = 0; j < BoardSize; j++) if (board[i, j] == 0) empty.Add((i, j)); return empty[rand.Next(empty.Count)]; } else { // 中等/困难:评分法 int maxScore = int.MinValue; var bestMoves = new List(); for (int x = 0; x < BoardSize; x++) { for (int y = 0; y < BoardSize; y++) { if (board[x, y] != 0) continue; int score = EvaluatePoint(x, y, 2); score = Math.Max(score, EvaluatePoint(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)]; } } int EvaluatePoint(int x, int y, int player) { int score = 0; int opponent = player == 1 ? 2 : 1; // 不同难度权重 int[] winWeight = { 100, 10000, 10000 }; int[] fourWeight = { 10, 1000, 3000 }; int[] threeWeight = { 5, 100, 500 }; int[] twoWeight = { 2, 10, 50 }; int[] blockWinWeight = { 90, 9000, 9000 }; int[] blockFourWeight = { 9, 900, 2500 }; int[] blockThreeWeight = { 4, 90, 400 }; int[] blockTwoWeight = { 1, 9, 40 }; foreach (var dir in new[] { (1, 0), (0, 1), (1, 1), (1, -1) }) { int count = 1 + CountDirection(x, y, dir.Item1, dir.Item2, player) + CountDirection(x, y, -dir.Item1, -dir.Item2, player); if (count >= 5) score += winWeight[aiLevel]; else if (count == 4) score += fourWeight[aiLevel]; else if (count == 3) score += threeWeight[aiLevel]; else if (count == 2) score += twoWeight[aiLevel]; int oppCount = 1 + CountDirection(x, y, dir.Item1, dir.Item2, opponent) + CountDirection(x, y, -dir.Item1, -dir.Item2, opponent); if (oppCount >= 5) score += blockWinWeight[aiLevel]; else if (oppCount == 4) score += blockFourWeight[aiLevel]; else if (oppCount == 3) score += blockThreeWeight[aiLevel]; else if (oppCount == 2) score += blockTwoWeight[aiLevel]; } return score; } bool CheckWin(int x, int y, int player) { int[][] directions = new int[][] { new int[]{1,0}, new int[]{0,1}, new int[]{1,1}, new int[]{1,-1} }; foreach (var dir in directions) { int count = 1; count += CountDirection(x, y, dir[0], dir[1], player); count += CountDirection(x, y, -dir[0], -dir[1], player); if (count >= 5) return true; } return false; } int CountDirection(int x, int y, int dx, int dy, int player) { int count = 0; for (int step = 1; step < 5; step++) { int nx = x + dx * step; int ny = y + dy * step; if (nx < 0 || nx >= BoardSize || ny < 0 || ny >= BoardSize) break; if (board[nx, ny] == player) count++; else break; } return count; } void Restart() { board = new int[BoardSize, BoardSize]; currentPlayer = 1; winner = 0; if (isHumanVsAI && currentPlayer == 2) { _ = AITurnAsync(); } } void ResetScore() { blackScore = 0; whiteScore = 0; } void SetAILevel(int level) { aiLevel = level; Restart(); } void ToggleMode() { isHumanVsAI = !isHumanVsAI; Restart(); } string GetCellBg(int x, int y) { return (x + y) % 2 == 0 ? "#f9d77e" : "#eac066"; }}
复制代码 说明:
- “简单”AI为随机落子,“中等/困难”AI为评分法,困难权重更高更难。
- “人机对战”时白子为AI,“人人对战”时双方均为玩家。
- 切换难度或模式会自动重开棋局。
- 你可以根据需要调整权重数组以微调难度。
10. 最后贴上完整代码
- @page "/"五子棋[size=6]五子棋游戏[/size]
- [b]难度:[/b] 简单 中等 困难 [b]模式:[/b] @(isHumanVsAI ? "人机对战" : "人人对战") 当前玩家: [b]@(currentPlayer == 1 ? "黑子" : (isHumanVsAI ? "白子(电脑)" : "白子"))[/b] 黑子得分: [b]@blackScore[/b] 白子得分: [b]@whiteScore[/b] <button @onclick="ResetScore">重置得分</button> @if (winner != 0) { 胜者: @(winner == 1 ? "黑子" : (isHumanVsAI ? "白子(电脑)" : "白子")) 重新开始 }[table] @for (int y = 0; y < BoardSize; y++) { [tr] @for (int x = 0; x < BoardSize; x++) { int _x = x; int _y = y; [td] @if (board[x, y] == 1) { ● } else if (board[x, y] == 2) { ● } [/td] } [/tr] }[/table]@code { const int BoardSize = 15; int[,] board = new int[BoardSize, BoardSize]; int currentPlayer = 1; // 1: 黑子, 2: 白子(电脑/玩家) int winner = 0; int blackScore = 0; int whiteScore = 0; Random rand = new(); bool isHumanVsAI = true; int aiLevel = 1; // 0:简单 1:中等 2:困难 void PlacePiece(int x, int y) { if (winner != 0 || board[x, y] != 0) return; // 人机模式下,只有当前为玩家时可落子 if (isHumanVsAI && currentPlayer == 2) return; board[x, y] = currentPlayer; if (CheckWin(x, y, currentPlayer)) { winner = currentPlayer; if (winner == 1) blackScore++; else if (winner == 2) whiteScore++; } else { currentPlayer = 3 - currentPlayer; if (isHumanVsAI && currentPlayer == 2 && winner == 0) { StateHasChanged(); _ = AITurnAsync(); } } } async Task AITurnAsync() { await Task.Delay(500); if (winner != 0) return; var (aiX, aiY) = FindBestMove(); board[aiX, aiY] = 2; if (CheckWin(aiX, aiY, 2)) { winner = 2; whiteScore++; } else { currentPlayer = 1; } StateHasChanged(); } (int, int) FindBestMove() { if (aiLevel == 0) { // 简单:随机落子 var empty = new List(); for (int i = 0; i < BoardSize; i++) for (int j = 0; j < BoardSize; j++) if (board[i, j] == 0) empty.Add((i, j)); return empty[rand.Next(empty.Count)]; } else { // 中等/困难:评分法 int maxScore = int.MinValue; var bestMoves = new List(); for (int x = 0; x < BoardSize; x++) { for (int y = 0; y < BoardSize; y++) { if (board[x, y] != 0) continue; int score = EvaluatePoint(x, y, 2); score = Math.Max(score, EvaluatePoint(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)]; } } int EvaluatePoint(int x, int y, int player) { int score = 0; int opponent = player == 1 ? 2 : 1; // 不同难度权重 int[] winWeight = { 100, 10000, 10000 }; int[] fourWeight = { 10, 1000, 3000 }; int[] threeWeight = { 5, 100, 500 }; int[] twoWeight = { 2, 10, 50 }; int[] blockWinWeight = { 90, 9000, 9000 }; int[] blockFourWeight = { 9, 900, 2500 }; int[] blockThreeWeight = { 4, 90, 400 }; int[] blockTwoWeight = { 1, 9, 40 }; foreach (var dir in new[] { (1, 0), (0, 1), (1, 1), (1, -1) }) { int count = 1 + CountDirection(x, y, dir.Item1, dir.Item2, player) + CountDirection(x, y, -dir.Item1, -dir.Item2, player); if (count >= 5) score += winWeight[aiLevel]; else if (count == 4) score += fourWeight[aiLevel]; else if (count == 3) score += threeWeight[aiLevel]; else if (count == 2) score += twoWeight[aiLevel]; int oppCount = 1 + CountDirection(x, y, dir.Item1, dir.Item2, opponent) + CountDirection(x, y, -dir.Item1, -dir.Item2, opponent); if (oppCount >= 5) score += blockWinWeight[aiLevel]; else if (oppCount == 4) score += blockFourWeight[aiLevel]; else if (oppCount == 3) score += blockThreeWeight[aiLevel]; else if (oppCount == 2) score += blockTwoWeight[aiLevel]; } return score; } bool CheckWin(int x, int y, int player) { int[][] directions = new int[][] { new int[]{1,0}, new int[]{0,1}, new int[]{1,1}, new int[]{1,-1} }; foreach (var dir in directions) { int count = 1; count += CountDirection(x, y, dir[0], dir[1], player); count += CountDirection(x, y, -dir[0], -dir[1], player); if (count >= 5) return true; } return false; } int CountDirection(int x, int y, int dx, int dy, int player) { int count = 0; for (int step = 1; step < 5; step++) { int nx = x + dx * step; int ny = y + dy * step; if (nx < 0 || nx >= BoardSize || ny < 0 || ny >= BoardSize) break; if (board[nx, ny] == player) count++; else break; } return count; } void Restart() { board = new int[BoardSize, BoardSize]; currentPlayer = 1; winner = 0; if (isHumanVsAI && currentPlayer == 2) { _ = AITurnAsync(); } } void ResetScore() { blackScore = 0; whiteScore = 0; } void SetAILevel(int level) { aiLevel = level; Restart(); } void ToggleMode() { isHumanVsAI = !isHumanVsAI; Restart(); } string GetCellBg(int x, int y) { return (x + y) % 2 == 0 ? "#f9d77e" : "#eac066"; }}
复制代码
把运行模式改回来,Auto模式不占用服务器计算资源
打开 App.razor 编辑 两行 @rendermode="InteractiveServer" 改为 @rendermode="InteractiveAuto"
网友反馈
后续添加了美化UI, 添加动画, 悔棋
开源地址
源码g01Gobang
demo
https://game.app1.es 用blazor auto发布的
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |