<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Maui Blazor 中文社區(qū) QQ群:645660665

      Github Copilot 實(shí)戰(zhàn): 使用 Copilot AI + Blazor 編一個(gè)五子棋游戲

      開(kāi)源地址

      源碼g01Gobang

      demo
      https://game.app1.es 用blazor auto發(fā)布的

      1. 創(chuàng)建 Blazor web工程,選Auto

      image

      2. 打開(kāi) GitHub Copilot 窗口,輸入提示詞

      使用 Blazor 編一個(gè)五子棋游戲

      image

      3.復(fù)制代碼測(cè)試

      為了方便調(diào)試, 我們先把運(yùn)行模式由 InteractiveAuto 改為 InteractiveServer

      打開(kāi) App.razor 編輯 兩行 @rendermode="InteractiveAuto" 改為 @rendermode="InteractiveServer"

      image

      4.不出意外, 代碼出現(xiàn)了意外

      image

      無(wú)腦使用AI修復(fù)一下

      image

      結(jié)果發(fā)現(xiàn)不是這個(gè)問(wèn)題. 是邏輯代碼 @onclick="() => PlacePiece(x, y)" 問(wèn)題. 原因是PlacePiece閉包捕獲的 x、y 是當(dāng)前循環(huán)的值

      既然人工發(fā)現(xiàn)了問(wèn)題, 我們繼續(xù)提醒一下AI, 嘗試修復(fù)

      image

      最后還是沒(méi)修復(fù)成功, 手動(dòng)處理一下

      @page "/"
      
      <PageTitle>五子棋</PageTitle>
      
      <h1>五子棋游戲</h1>
      
      <div style="margin-bottom:10px;">
          當(dāng)前玩家: <b>@(currentPlayer == 1 ? "黑子" : "白子")</b>
          @if (winner != 0)
          {
              <span style="color:red;margin-left:20px;">勝者: @(winner == 1 ? "黑子" : "白子")</span>
              <button class="btn btn-primary" style="margin-left:20px;" @onclick="Restart">重新開(kāi)始</button>
          }
      </div>
      
      <table style="border-collapse:collapse;">
          @for (int y = 0; y < BoardSize; y++)
          {
              <tr>
                  @for (int x = 0; x < BoardSize; x++)
                  {
                      int _x = x;
                      int _y = y;
                      <td style="width:32px;height:32px;border:1px solid #888;text-align:center;vertical-align:middle;cursor:pointer;background:@GetCellBg(x, y);"
                          @onclick="@(() => PlacePiece(_x, _y))">
                          @if (board[x, y] == 1)
                          {
                              <span style="font-size:24px;color:black;">●</span>
                          }
                          else if (board[x, y] == 2)
                          {
                              <span style="font-size:24px;color:#eee;text-shadow:0 0 2px #888;">●</span>
                          }
                      </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)
          {
              // 修復(fù):增加邊界檢查,防止越界
              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";
          }
      }
      
      

      說(shuō)明:

      1. 添加 int _x = x; int _y = y; 確保閉包捕獲的 _x_y 是當(dāng)前循環(huán)的值,避免 Blazor 渲染時(shí)閉包變量引用錯(cuò)誤。
      2. PlacePiece 方法開(kāi)頭增加邊界檢查,防止非法坐標(biāo)導(dǎo)致數(shù)組越界異常。

      這樣可以徹底修復(fù) PlacePiece 拿到的變量不正確和越界的問(wèn)題。

      5. 運(yùn)行效果

      image

      6. 加入顯示當(dāng)前玩家的得分功能

      你可以為每個(gè)玩家增加一個(gè)分?jǐn)?shù)變量,每次有玩家獲勝時(shí)將其分?jǐn)?shù)加一,并在界面上顯示。下面是具體實(shí)現(xiàn)方法:

      1. @code 區(qū)域添加分?jǐn)?shù)字段:
      int blackScore = 0;
      int whiteScore = 0;
      
      1. 在玩家獲勝時(shí)更新分?jǐn)?shù):
      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; // 切換玩家
          }
      }
      
      1. 在頁(yè)面上顯示分?jǐn)?shù)(比如在標(biāo)題下方):
      <div style="margin-bottom:10px;">
          當(dāng)前玩家: <b>@(currentPlayer == 1 ? "黑子" : "白子")</b>
          <span style="margin-left:20px;">黑子得分: <b>@blackScore</b></span>
          <span style="margin-left:20px;">白子得分: <b>@whiteScore</b></span>
          @if (winner != 0)
          {
              <span style="color:red;margin-left:20px;">勝者: @(winner == 1 ? "黑子" : "白子")</span>
              <button class="btn btn-primary" style="margin-left:20px;" @onclick="Restart">重新開(kāi)始</button>
          }
      </div>
      

      這樣每次有玩家獲勝時(shí),分?jǐn)?shù)都會(huì)自動(dòng)更新并顯示在頁(yè)面上。

      image

      7. 加入重置得分功能

      你可以在 Restart 方法中增加對(duì)分?jǐn)?shù)的重置,或者單獨(dú)添加一個(gè)“重置得分”按鈕和方法。推薦做法如下:

      1. 添加重置得分方法:
      void ResetScore()
      {
          blackScore = 0;
          whiteScore = 0;
      }
      
      1. 在頁(yè)面上添加按鈕:
      <button class="btn btn-danger" style="margin-left:20px;" @onclick="ResetScore">重置得分</button>
      

      建議將此按鈕放在分?jǐn)?shù)顯示附近,例如:

      <div style="margin-bottom:10px;">
          當(dāng)前玩家: <b>@(currentPlayer == 1 ? "黑子" : "白子")</b>
          <span style="margin-left:20px;">黑子得分: <b>@blackScore</b></span>
          <span style="margin-left:20px;">白子得分: <b>@whiteScore</b></span>
          <button class="btn btn-danger" style="margin-left:20px;" @onclick="ResetScore">重置得分</button>
          @if (winner != 0)
          {
              <span style="color:red;margin-left:20px;">勝者: @(winner == 1 ? "黑子" : "白子")</span>
              <button class="btn btn-primary" style="margin-left:20px;" @onclick="Restart">重新開(kāi)始</button>
          }
      </div>
      

      這樣點(diǎn)擊“重置得分”按鈕即可將分?jǐn)?shù)清零。

      8. 在這個(gè)五子棋游戲中添加 AI 對(duì)手功能

      在你的 Blazor 五子棋游戲中添加 AI 對(duì)手功能,常見(jiàn)做法是讓一方(如白子)由 AI 自動(dòng)落子。實(shí)現(xiàn)思路如下:

      1. 判斷當(dāng)前玩家是否為 AI:如 currentPlayer == 2 時(shí),自動(dòng)調(diào)用 AI 落子邏輯。
      2. 實(shí)現(xiàn) AI 落子算法:可以先用簡(jiǎn)單的隨機(jī)落子,后續(xù)可擴(kuò)展為更智能的算法。
      3. 在玩家落子后自動(dòng)觸發(fā) AI 落子:用 StateHasChanged() 刷新界面,必要時(shí)用 await Task.Delay() 增加落子延遲。

      下面是具體實(shí)現(xiàn)方法(以白子為 AI):

      @page "/"
      
      <PageTitle>五子棋</PageTitle>
      
      <h1>五子棋游戲</h1>
      
      <div style="margin-bottom:10px;">
          當(dāng)前玩家: <b>@(currentPlayer == 1 ? "黑子" : "白子(電腦)")</b>
          <span style="margin-left:20px;">黑子得分: <b>@blackScore</b></span>
          <span style="margin-left:20px;">白子得分: <b>@whiteScore</b></span>
          <button class="btn btn-danger" style="margin-left:20px;" @onclick="ResetScore">重置得分</button>
          @if (winner != 0)
          {
              <span style="color:red;margin-left:20px;">勝者: @(winner == 1 ? "黑子" : "白子(電腦)")</span>
              <button class="btn btn-primary" style="margin-left:20px;" @onclick="Restart">重新開(kāi)始</button>
          }
      </div>
      
      <table style="border-collapse:collapse;">
          @for (int y = 0; y < BoardSize; y++)
          {
              <tr>
                  @for (int x = 0; x < BoardSize; x++)
                  {
                      int _x = x;
                      int _y = y;
                      <td style="width:32px;height:32px;border:1px solid #888;text-align:center;vertical-align:middle;cursor:pointer;background:@GetCellBg(x, y);"
                          @onclick="@(() => PlacePiece(_x, _y))">
                          @if (board[x, y] == 1)
                          {
                              <span style="font-size:24px;color:black;">●</span>
                          }
                          else if (board[x, y] == 2)
                          {
                              <span style="font-size:24px;color:#eee;text-shadow:0 0 2px #888;">●</span>
                          }
                      </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;
      
              // 簡(jiǎn)單隨機(jī)落子
              var empty = new List<(int x, int y)>();
              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";
          }
      }
      

      要點(diǎn)說(shuō)明:

      • 玩家(黑子)落子后自動(dòng)觸發(fā) AI(白子)落子。
      • AI 采用隨機(jī)空位落子,簡(jiǎn)單易懂,后續(xù)可擴(kuò)展為更智能算法。
      • 若要讓 AI 先手,只需將 currentPlayer = 2 并在 OnInitializedRestart 時(shí)調(diào)用 AITurnAsync()

      image

      用是能用了, 就是這個(gè)AI太傻了,繼續(xù)優(yōu)化一下

      要優(yōu)化五子棋 AI 的落子策略,可以采用“優(yōu)先級(jí)評(píng)分法”來(lái)提升難度。基本思路如下:

      1. 優(yōu)先考慮能直接獲勝的位置(如 AI 連成五子)。
      2. 阻止玩家獲勝(如玩家有四連,AI 必須堵住)。
      3. 優(yōu)先進(jìn)攻(如自己有三連、二連)。
      4. 其次防守(如玩家有三連、二連)。
      5. 否則隨機(jī)或選擇評(píng)分最高的位置

      下面是一個(gè)簡(jiǎn)單的評(píng)分法實(shí)現(xiàn),AI 會(huì)優(yōu)先選擇能贏、能防守、能進(jìn)攻的位置:

      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();
      }
      
      // 簡(jiǎn)單評(píng)分法:優(yōu)先贏棋、阻擋對(duì)方、進(jìn)攻
      (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進(jìn)攻
                  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));
                  }
              }
          }
          // 多個(gè)最佳點(diǎn)時(shí)隨機(jī)選一個(gè)
          return bestMoves[rand.Next(bestMoves.Count)];
      }
      
      // 評(píng)分函數(shù):可根據(jù)實(shí)際需要調(diào)整權(quán)重
      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;
      
              // 防守分?jǐn)?shù)
              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;
      }
      

      集成方法:

      1. 替換你的 AITurnAsync 方法為上述實(shí)現(xiàn)。
      2. @code 區(qū)域添加 FindBestMoveEvaluatePoint 方法。
      3. 可根據(jù)實(shí)際效果調(diào)整評(píng)分權(quán)重。

      效果說(shuō)明:

      • AI 會(huì)優(yōu)先選擇能贏的位置,其次堵住玩家的四連,再考慮進(jìn)攻和防守三連、二連。
      • 這種評(píng)分法簡(jiǎn)單高效,能顯著提升 AI 難度。
      • 若需更高難度,可進(jìn)一步實(shí)現(xiàn)“活三”、“活四”識(shí)別、雙向評(píng)分、甚至 Minimax 算法。

      image

      9. 添加難度切換按鈕

      添加三個(gè)難度選擇按鈕以及切換人機(jī)按鈕

      下面是實(shí)現(xiàn)“三個(gè)難度選擇按鈕(簡(jiǎn)單、中等、困難)”和“人機(jī)/人人切換按鈕”的完整方法。
      難度通過(guò)調(diào)整 AI 的評(píng)分權(quán)重實(shí)現(xiàn),人機(jī)切換通過(guò) isHumanVsAI 控制。請(qǐng)直接替換你的 Home.razor 文件內(nèi)容:

      @page "/"
      
      <PageTitle>五子棋</PageTitle>
      
      <h1>五子棋游戲</h1>
      
      <div style="margin-bottom:10px;">
          <b>難度:</b>
          <button class="btn btn-sm @(aiLevel==0?"btn-primary":"btn-outline-primary")" @onclick="() => SetAILevel(0)">簡(jiǎn)單</button>
          <button class="btn btn-sm @(aiLevel==1?"btn-primary":"btn-outline-primary")" @onclick="() => SetAILevel(1)">中等</button>
          <button class="btn btn-sm @(aiLevel==2?"btn-primary":"btn-outline-primary")" @onclick="() => SetAILevel(2)">困難</button>
          <span style="margin-left:20px;">
              <b>模式:</b>
              <button class="btn btn-sm @(isHumanVsAI?"btn-success":"btn-outline-success")" @onclick="ToggleMode">
                  @(isHumanVsAI ? "人機(jī)對(duì)戰(zhàn)" : "人人對(duì)戰(zhàn)")
              </button>
          </span>
      </div>
      
      <div style="margin-bottom:10px;">
          當(dāng)前玩家: <b>@(currentPlayer == 1 ? "黑子" : (isHumanVsAI ? "白子(電腦)" : "白子"))</b>
          <span style="margin-left:20px;">黑子得分: <b>@blackScore</b></span>
          <span style="margin-left:20px;">白子得分: <b>@whiteScore</b></span>
          <button class="btn btn-danger" style="margin-left:20px;" @onclick="ResetScore">重置得分</button>
          @if (winner != 0)
          {
              <span style="color:red;margin-left:20px;">勝者: @(winner == 1 ? "黑子" : (isHumanVsAI ? "白子(電腦)" : "白子"))</span>
              <button class="btn btn-primary" style="margin-left:20px;" @onclick="Restart">重新開(kāi)始</button>
          }
      </div>
      
      <table style="border-collapse:collapse;">
          @for (int y = 0; y < BoardSize; y++)
          {
              <tr>
                  @for (int x = 0; x < BoardSize; x++)
                  {
                      int _x = x;
                      int _y = y;
                      <td style="width:32px;height:32px;border:1px solid #888;text-align:center;vertical-align:middle;cursor:pointer;background:@GetCellBg(x, y);"
                          @onclick="@(() => PlacePiece(_x, _y))">
                          @if (board[x, y] == 1)
                          {
                              <span style="font-size:24px;color:black;">●</span>
                          }
                          else if (board[x, y] == 2)
                          {
                              <span style="font-size:24px;color:#eee;text-shadow:0 0 2px #888;">●</span>
                          }
                      </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:簡(jiǎn)單 1:中等 2:困難
      
          void PlacePiece(int x, int y)
          {
              if (winner != 0 || board[x, y] != 0)
                  return;
      
              // 人機(jī)模式下,只有當(dāng)前為玩家時(shí)可落子
              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)
              {
                  // 簡(jiǎn)單:隨機(jī)落子
                  var empty = new List<(int x, int y)>();
                  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
              {
                  // 中等/困難:評(píng)分法
                  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);
                          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;
              // 不同難度權(quán)重
              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";
          }
      }
      

      說(shuō)明:

      • “簡(jiǎn)單”AI為隨機(jī)落子,“中等/困難”AI為評(píng)分法,困難權(quán)重更高更難。
      • “人機(jī)對(duì)戰(zhàn)”時(shí)白子為AI,“人人對(duì)戰(zhàn)”時(shí)雙方均為玩家。
      • 切換難度或模式會(huì)自動(dòng)重開(kāi)棋局。
      • 你可以根據(jù)需要調(diào)整權(quán)重?cái)?shù)組以微調(diào)難度。

      10. 最后貼上完整代碼

      @page "/"
      
      <PageTitle>五子棋</PageTitle>
      
      <h1>五子棋游戲</h1>
      
      <div style="margin-bottom:10px;">
          <b>難度:</b>
          <button class="btn btn-sm @(aiLevel==0?"btn-primary":"btn-outline-primary")" @onclick="() => SetAILevel(0)">簡(jiǎn)單</button>
          <button class="btn btn-sm @(aiLevel==1?"btn-primary":"btn-outline-primary")" @onclick="() => SetAILevel(1)">中等</button>
          <button class="btn btn-sm @(aiLevel==2?"btn-primary":"btn-outline-primary")" @onclick="() => SetAILevel(2)">困難</button>
          <span style="margin-left:20px;">
              <b>模式:</b>
              <button class="btn btn-sm @(isHumanVsAI?"btn-success":"btn-outline-success")" @onclick="ToggleMode">
                  @(isHumanVsAI ? "人機(jī)對(duì)戰(zhàn)" : "人人對(duì)戰(zhàn)")
              </button>
          </span>
      </div>
      
      <div style="margin-bottom:10px;">
          當(dāng)前玩家: <b>@(currentPlayer == 1 ? "黑子" : (isHumanVsAI ? "白子(電腦)" : "白子"))</b>
          <span style="margin-left:20px;">黑子得分: <b>@blackScore</b></span>
          <span style="margin-left:20px;">白子得分: <b>@whiteScore</b></span>
          <button class="btn btn-danger" style="margin-left:20px;" @onclick="ResetScore">重置得分</button>
          @if (winner != 0)
          {
              <span style="color:red;margin-left:20px;">勝者: @(winner == 1 ? "黑子" : (isHumanVsAI ? "白子(電腦)" : "白子"))</span>
              <button class="btn btn-primary" style="margin-left:20px;" @onclick="Restart">重新開(kāi)始</button>
          }
      </div>
      
      <table style="border-collapse:collapse;">
          @for (int y = 0; y < BoardSize; y++)
          {
              <tr>
                  @for (int x = 0; x < BoardSize; x++)
                  {
                      int _x = x;
                      int _y = y;
                      <td style="width:32px;height:32px;border:1px solid #888;text-align:center;vertical-align:middle;cursor:pointer;background:@GetCellBg(x, y);"
                          @onclick="@(() => PlacePiece(_x, _y))">
                          @if (board[x, y] == 1)
                          {
                              <span style="font-size:24px;color:black;">●</span>
                          }
                          else if (board[x, y] == 2)
                          {
                              <span style="font-size:24px;color:#eee;text-shadow:0 0 2px #888;">●</span>
                          }
                      </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:簡(jiǎn)單 1:中等 2:困難
      
          void PlacePiece(int x, int y)
          {
              if (winner != 0 || board[x, y] != 0)
                  return;
      
              // 人機(jī)模式下,只有當(dāng)前為玩家時(shí)可落子
              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)
              {
                  // 簡(jiǎn)單:隨機(jī)落子
                  var empty = new List<(int x, int y)>();
                  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
              {
                  // 中等/困難:評(píng)分法
                  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);
                          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;
              // 不同難度權(quán)重
              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";
          }
      }
      

      image

      把運(yùn)行模式改回來(lái),Auto模式不占用服務(wù)器計(jì)算資源

      打開(kāi) App.razor 編輯 兩行 @rendermode="InteractiveServer" 改為 @rendermode="InteractiveAuto"

      網(wǎng)友反饋

      后續(xù)添加了美化UI, 添加動(dòng)畫, 悔棋

      開(kāi)源地址

      源碼g01Gobang

      demo
      https://game.app1.es 用blazor auto發(fā)布的

      posted @ 2025-10-03 19:59  AlexChow  閱讀(413)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 无码人妻熟妇av又粗又大| 绝顶丰满少妇av无码| 老熟女重囗味hdxx69| 国产精品一区二区久久精品无码| 国产精品多p对白交换绿帽| 亚洲人成网站在小说| 久久av无码精品人妻出轨| 亚洲成人精品在线伊人网| 国产精品疯狂输出jk草莓视频| 亚洲区欧美区综合区自拍区| 中文字幕国产日韩精品| 私人毛片免费高清影视院| 久久久久久久久久久免费精品| 加勒比无码人妻东京热| 天堂亚洲免费视频| 在线观看无码av五月花| 国产精品制服丝袜无码| 99riav精品免费视频观看| 久久精品国产99麻豆蜜月| 久久亚洲av成人无码软件| 人妻夜夜爽天天爽三区麻豆av| 四虎成人在线观看免费| 日产一区日产2区| 亚洲AV永久无码嘿嘿嘿嘿| 亚洲精品国产中文字幕| 国产免费播放一区二区三区| 九九热视频在线精品18| 国产av一区二区三区| 久久97超碰色中文字幕| AV人摸人人人澡人人超碰| 一区二区三区精品不卡| 国产热A欧美热A在线视频| 中文字幕无码免费久久9一区9| 亚洲粉嫩av一区二区黑人| 欧美福利电影A在线播放 | 拍摄av现场失控高潮数次| 一区二区三区四区五区色| 亚洲午夜理论无码电影| 亚洲一区成人在线视频| 国产精品第一页中文字幕| 国产精品久久久久久久久久|