Re: 改下哥尼斯堡網頁程式
发表于 : 2026年 4月 11日 09:09
當shooting取勝時,預估勝率應為100%,現在顯示0%,分析原因,並給出解決辦法。
代码: 全选
這是一個邏輯判斷上的錯誤。原因在於 `applyMove` 函數回傳的 `terminal` 狀態與 `winner` 的歸屬判斷在「當前玩家執行最後一擊」時,與 MCTS 的評分 logic 產生了衝突。
### 原因分析
在您的程式碼中:
1. **`applyMove` 的邏輯**:當一個動作導致勝負分出(例如綠方過橋達到 12 座或藍方無處可走),`applyMove` 會回傳 `terminal: true` 並設置 `winner`(0 或 1)。
2. **`runMCTS` 的邏輯**:
```javascript
let res = applyMove(rootState, move);
if (res.terminal) {
// 這裡原本寫死為 immediateLoss: true
moveStats.push({ move, wins: -999, plays: 1, immediateLoss: true });
}
```
問題就在這裡:程式碼**預設所有 `terminal` 都是「我被殺了」**。但實際上,如果這個 `terminal` 是由我方走出的「絕殺一步」(Shooting),`res.winner` 就會是我自己。此時應該判定為 **100% 勝率**,而不是 0%。
---
### 解決辦法
我們需要修改 `runMCTS` 中處理 `res.terminal` 的部分,根據 `res.winner` 是否等於當前移動者 (`rootState.turn`) 來判斷是「絕殺對方」還是「自殺/被困」。
#### 修改 `runMCTS` 核心判斷區塊:
請找到 `runMCTS` 函式中處理 `res.terminal` 的 `if` 語句,替換為以下邏輯:
```javascript
// 核心推演邏輯
let res = applyMove(rootState, move);
if (res.terminal) {
// 修改處:判斷贏家是誰
if (res.winner === rootState.turn) {
// 如果贏家是我,這是一步絕殺(Shooting 取勝)
moveStats.push({ move, wins: Infinity, plays: 1, guaranteedWin: true });
} else {
// 如果贏家不是我(或平局 -1),則視為失敗
moveStats.push({ move, wins: -999, plays: 1, immediateLoss: true });
}
} else if (canForceWin(res.state, 2, rootState.turn)) {
// ...其餘邏輯不變
```
#### 同步更新 `renderMctsResults` (或結果處理部分):
為了讓 UI 顯示得更清楚,當 `guaranteedWin` 為真時,確保勝率計算正確。
在顯示勝率的邏輯中(不論是 `isAuto` 還是 `renderMctsResults`),確保優先檢查 `guaranteedWin`:
```javascript
// 在 renderMctsResults 或 isAuto 結束判斷時
let scoreText = "";
if (stat.guaranteedWin) {
scoreText = "<span style='color:green'>🎯 100% (絕殺/必勝)</span>";
} else if (stat.immediateLoss) {
scoreText = "<span style='color:red'>💀 0% (致命錯誤)</span>";
} else if (stat.guaranteedLoss) {
scoreText = "<span style='color:orange'>⚠️ 0% (必敗走法)</span>";
} else {
scoreText = `勝率: ${((stat.wins / stat.plays) * 100).toFixed(1)}%`;
}
```
### 為什麼這能解決問題?
1. **Shooting 取勝辨識**:當執行走棋後滿足勝利條件,`res.winner` 會等於 `rootState.turn`。
2. **優先權排序**:透過將 `wins` 設為 `Infinity` 並標記 `guaranteedWin: true`,這步棋會被排在最前面,且自動走棋會毫不猶豫地執行這一步。
3. **消除誤報**:不再將所有結束遊戲的動作都視為「失敗」,讓 AI 能夠正確識別自己的勝利動作。