改下哥尼斯堡網頁程式

分享和讨论Javascript相关的话题
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

改進:
一,當modal窗口在顯示時,將不會再進行自動搜尋。

二,本棋規則中有「出現重覆局面則判為和棋」,搜尋必殺時應避免和局。

只需給出所要修改的地方。

代码: 全选

這裡為你提供針對這兩項需求的具體修改程式碼片段。請在原始檔案中找到對應區塊進行替換:

### 第一部分:當 modal 顯示時暫停自動搜尋

在 `displayGame()` 函數內,找到自動下棋的邏輯(約在第 442 行附近),加上對 `mcts_modal` 顯示狀態的判斷:

**替換前:**
```javascript
        // 自動下棋
        clearTimeout(autoPlayTimer);
        if (game_status == 1 || game_status == 3) {
            let autoBlue = document.getElementById('mcts_auto_blue') && document.getElementById('mcts_auto_blue').checked;
```

**替換後:**
```javascript
        // 自動下棋
        clearTimeout(autoPlayTimer);
        if ((game_status == 1 || game_status == 3) && document.getElementById('mcts_modal').style.display !== 'block') {
            let autoBlue = document.getElementById('mcts_auto_blue') && document.getElementById('mcts_auto_blue').checked;
```

---

### 第二部分:在 MCTS 推演中加入「重覆局面則和局」判斷

共需修改三個地方來傳遞與檢查歷史紀錄 (`game_history`)。

**1. 展開 `rootState` 時拷貝當下歷史(約在 `runMCTS` 內第 746 行附近)**

**替換前:**
```javascript
        let rootState = {
            p0: parseInt(men_bottom[0].getAttribute("i") || men_top[0].getAttribute("i")),
            p1: parseInt(men_bottom[1].getAttribute("i") || men_top[1].getAttribute("i")),
            turn: current_man,
            empty_map: JSON.parse(JSON.stringify(empty_map)),
            arrow_map: JSON.parse(JSON.stringify(arrow_map)),
            stack_arrow: stack_arrow.slice()
        };
```

**替換後:**
```javascript
        let rootState = {
            p0: parseInt(men_bottom[0].getAttribute("i") || men_top[0].getAttribute("i")),
            p1: parseInt(men_bottom[1].getAttribute("i") || men_top[1].getAttribute("i")),
            turn: current_man,
            empty_map: JSON.parse(JSON.stringify(empty_map)),
            arrow_map: JSON.parse(JSON.stringify(arrow_map)),
            stack_arrow: stack_arrow.slice(),
            history: game_history.slice() // 拷貝歷史紀錄以供檢查和局
        };
```

**2. 在 `applyMove` 中傳遞歷史陣列(約第 930 行附近)**

**替換前:**
```javascript
    // 將某條路徑套用到當前狀態,翻轉橋樑,並判斷是否立刻分出勝負
    function applyMove(state, route) {
        let nextState = {
            p0: state.p0,
            p1: state.p1,
            turn: 1 - state.turn,
            empty_map: JSON.parse(JSON.stringify(state.empty_map)),
            arrow_map: JSON.parse(JSON.stringify(state.arrow_map)),
            stack_arrow: state.stack_arrow.slice()
        };
```

**替換後:**
```javascript
    // 將某條路徑套用到當前狀態,翻轉橋樑,並判斷是否立刻分出勝負
    function applyMove(state, route) {
        let nextState = {
            p0: state.p0,
            p1: state.p1,
            turn: 1 - state.turn,
            empty_map: JSON.parse(JSON.stringify(state.empty_map)),
            arrow_map: JSON.parse(JSON.stringify(state.arrow_map)),
            stack_arrow: state.stack_arrow.slice(),
            history: state.history ? state.history.slice() : [] // 傳遞並拷貝推演歷史
        };
```

**3. 在 `applyMove` 更新完位置後加入和局判定(約第 966 行附近)**

**替換前:**
```javascript
        // 更新位置
        if (state.turn === 0) nextState.p0 = route[route.length - 1];
        else nextState.p1 = route[route.length - 1];

        // 檢查對手是否能射擊你 (BFS 尋找連通性)
        let target = state.turn === 0 ? nextState.p0 : nextState.p1;
```

**替換後:**
```javascript
        // 更新位置
        if (state.turn === 0) nextState.p0 = route[route.length - 1];
        else nextState.p1 = route[route.length - 1];

        // 檢查是否出現重覆局面 (和局)
        let state_hash = JSON.stringify([nextState.p0, nextState.p1].concat(nextState.stack_arrow));
        if (nextState.history.includes(state_hash)) {
            return {
                terminal: true,
                winner: -1 // 回傳 -1 代表和局,MCTS 必殺判斷與 Playout 都會以此避開無窮迴圈
            };
        }
        nextState.history.push(state_hash);

        // 檢查對手是否能射擊你 (BFS 尋找連通性)
        let target = state.turn === 0 ? nextState.p0 : nextState.p1;
```
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

雖然判定必殺,卻最終和棋:

代码: 全选

[[3,6],[-5,3,4,0],[0,6,4,3,0,4],[-5,6,5,1,4,7,8],[0,8,4,3,0,4,5,6,1,5,4,1,7,4,8,7],[-5,0,4,8,5,6],[6,8,4,3,4,0,6,5,1,5,4,1,7,4,8,7,8,4,5,8],[-5,8,4,1,5,9,6,2],[6,2,4,3,4,0,6,5,5,1,1,4,7,4,8,7,4,8,5,8,9,5,6,9,2,6],[-5,6,5,2,1,4,8,7],[7,2,4,3,4,0,5,6,5,1,4,1,7,4,7,8,8,4,5,8,9,5,6,9,2,6,5,2,2,1],[-5,2,6,9,5],[7,5,4,3,4,0,5,6,5,1,4,1,7,4,7,8,8,4,5,8,5,9,9,6,6,2,5,2,2,1],[-5,7,4,0],[0,5,4,3,0,4,5,6,5,1,4,1,4,7,7,8,8,4,5,8,5,9,9,6,6,2,5,2,2,1],[-5,5,4,3,7,8],[0,8,3,4,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,9,6,6,2,5,2,2,1,5,4,3,7],[-5,0,3],[3,8,3,4,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,9,6,6,2,5,2,2,1,5,4,3,7,0,3],[-5,8,9],[3,9,3,4,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,9,6,6,2,5,2,2,1,5,4,3,7,0,3,8,9],[-5,3,4],[4,9,4,3,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,9,6,6,2,5,2,2,1,5,4,3,7,0,3,8,9],[-5,9,6],[4,6,4,3,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,6,9,6,2,5,2,2,1,5,4,3,7,0,3,8,9],[-5,4,3],[3,6,3,4,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,6,9,6,2,5,2,2,1,5,4,3,7,0,3,8,9],[-5,6,2],[3,2,3,4,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,6,9,2,6,5,2,2,1,5,4,3,7,0,3,8,9],[-5,3,4],[4,2,4,3,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,6,9,2,6,5,2,2,1,5,4,3,7,0,3,8,9],[-4,2,6],[4,6,4,3,0,4,5,6,5,1,4,1,4,7,8,7,8,4,5,8,5,9,6,9,6,2,5,2,2,1,5,4,3,7,0,3,8,9]]
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

為何改了之後,形成和局的走法被指為「致命步」?查找原因並修正。

代码: 全选

會出現這個問題,是因為原先的 `runMCTS` 程式碼中,對於「終局 (`res.terminal === true`)」的判定只有二分法:**「不是我贏,就是我輸(致命步)」**。

在我們上一版將和局的 `winner` 設定為 `-1` 後,當系統遇到和局時,因為 `winner (-1)` 不等於 `rootState.turn`(當前玩家),所以直接掉進了 `else` 區塊,被誤判為 `immediateLoss: true`(致命步)。

我們需要為和局(`-1`)獨立增加一個判斷,將其視為平局分數(例如 `wins: 0.5`)。

請找到 `runMCTS` 函數內的 `processNextChunk` 迴圈(約在第 846 行附近),將這段終局判斷進行替換:

**替換前:**
```javascript
                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, dynamicDepth, rootState.turn)) {
```

**替換後:**
```javascript
                if (res.terminal) {
                    if (res.winner === rootState.turn) {
                        // 如果贏家是我,這是一步絕殺(Shooting 取勝)
                        moveStats.push({
                            move,
                            wins: Infinity,
                            plays: 1,
                            guaranteedWin: true
                        });
                    } else if (res.winner === -1) {
                        // 如果是和局(重覆局面),給予平局基本分,避免被當成致命步
                        moveStats.push({
                            move,
                            wins: 0.5, 
                            plays: 1
                        });
                    } else {
                        // 真正走到死胡同或被對方射殺
                        moveStats.push({
                            move,
                            wins: -999,
                            plays: 1,
                            immediateLoss: true
                        });
                    }
                } else if (canForceWin(res.state, dynamicDepth, rootState.turn)) {
```

修改後,導致和局的路線將不再被標記為紅色的「💀 致命步」,而是會以正常的勝率(約 50% 基礎分)顯示,這樣 AI 就會知道這步雖然沒贏,但至少比輸掉(致命步或必敗步)來得好。

是否還有其他地方需要微調?
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

附件
konigsberg20260413killyou782.7z
(15.03 KiB) 已下载 5 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

太好了!高強度AI終於達成了和局:

代码: 全选

[[3,6],[-5,3,0,1,5,4,8],[8,6,0,3,1,0,5,1,4,5,8,4],[-5,6,2,1,4,3,7],[8,7,0,3,1,0,5,1,4,5,8,4,2,6,1,2,4,1,3,4,7,3],[-5,8,7,3,4,5],[5,7,0,3,1,0,5,1,5,4,8,4,2,6,1,2,4,1,4,3,3,7,7,8],[-5,7,8,5,1,2],[5,2,0,3,1,0,1,5,5,4,8,4,2,6,2,1,4,1,4,3,3,7,8,7,5,8],[-5,5,2,6,9,8,7,4,1,0],[0,2,0,3,0,1,1,5,5,4,8,4,6,2,2,1,1,4,4,3,3,7,7,8,5,8,5,2,6,9,9,8,7,4],[-5,2,1,5],[0,5,0,3,0,1,5,1,5,4,8,4,6,2,1,2,1,4,4,3,3,7,7,8,5,8,5,2,6,9,9,8,7,4],[-5,0,1,4,3,7],[7,5,0,3,1,0,5,1,5,4,8,4,6,2,1,2,4,1,3,4,7,3,7,8,5,8,5,2,6,9,9,8,7,4],[-5,5,6,9,8,4,1,2],[7,2,0,3,1,0,5,1,5,4,4,8,6,2,2,1,1,4,3,4,7,3,7,8,5,8,5,2,6,9,9,8,7,4,5,6],[-5,7,4,0,3],[3,2,3,0,1,0,5,1,5,4,4,8,6,2,2,1,1,4,3,4,7,3,7,8,5,8,5,2,6,9,9,8,7,4,5,6,4,0],[-5,2,1],[3,1,3,0,1,0,5,1,5,4,4,8,6,2,1,2,1,4,3,4,7,3,7,8,5,8,5,2,6,9,9,8,7,4,5,6,4,0],[-5,3,4,8],[8,1,3,0,1,0,5,1,5,4,8,4,6,2,1,2,1,4,4,3,7,3,7,8,5,8,5,2,6,9,9,8,7,4,5,6,4,0],[-5,1,2],[8,2,3,0,1,0,5,1,5,4,8,4,6,2,2,1,1,4,4,3,7,3,7,8,5,8,5,2,6,9,9,8,7,4,5,6,4,0],[-4,8,4,3],[3,2,3,0,1,0,5,1,5,4,4,8,6,2,2,1,1,4,3,4,7,3,7,8,5,8,5,2,6,9,9,8,7,4,5,6,4,0]]
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

增加鍵盤快捷鍵:

enter:btn_finish
backspace:btn_back
del:btn_cancel
whitespace:btn_play
ctrl+left:btn_history_prev
ctrl+right:btn_history_next
ctrl+up:btn_history_set
ctrl+down:setting_close
f:fullscreen

ins:open modal
esc:close modal
0~9:點擊dot或在它上面的man

僅在其顯示時可點擊。當其class=hide時它將不顯示。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

gemini pro:

代码: 全选

你可以將以下 JavaScript 程式碼加入到你的 `<script>` 標籤的最底部(也就是 `</script>` 之前)。這段程式碼會監聽所有的鍵盤事件,並且完全按照你的需求處理各個快捷鍵功能。同時也加入了判斷,確保玩家在輸入框(如設定參數)中輸入時,不會誤觸發快捷鍵。

```javascript
    // === 鍵盤快捷鍵控制 ===
    document.addEventListener('keydown', function(e) {
        // 如果正在輸入框或文字區域內輸入,除了 Esc 以外忽略其它快捷鍵,防止干擾打字
        const isInput = e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA';
        
        if (e.key === 'Escape') {
            closeMctsModal();
            return;
        }

        if (isInput) return;

        // 判斷元素是否顯示 (沒有 hide class)
        const isVisible = (el) => {
            if (!el) return false;
            // 設定關閉按鈕受父元素 setting_div 的顯示狀態控制
            if (el.id === 'setting_close') return !setting_div.classList.contains('hide');
            // 其他元件直接判斷自身是否包含 hide 類別
            return !el.classList.contains('hide');
        };

        // 觸發元素點擊的輔助函數
        const triggerClick = (el) => {
            if (isVisible(el)) {
                // 原程式大多使用 el.onclick = function() 的方式綁定
                if (typeof el.onclick === 'function') {
                    el.onclick.call(el);
                } else {
                    el.click(); // 備用:如果是使用 addEventListener 綁定的元素
                }
            }
        };

        switch (e.key) {
            case 'Enter':
                triggerClick(btn_finish);
                break;
            case 'Backspace':
                triggerClick(btn_back);
                break;
            case 'Delete':
                triggerClick(btn_cancel);
                break;
            case ' ': // 空白鍵 (Whitespace)
                e.preventDefault(); // 防止按下空白鍵時網頁向下滾動
                triggerClick(btn_play);
                break;
            case 'ArrowLeft':
                if (e.ctrlKey) triggerClick(btn_history_prev);
                break;
            case 'ArrowRight':
                if (e.ctrlKey) triggerClick(btn_history_next);
                break;
            case 'ArrowUp':
                if (e.ctrlKey) triggerClick(btn_history_set);
                break;
            case 'ArrowDown':
                if (e.ctrlKey) triggerClick(setting_close);
                break;
            case 'f':
            case 'F':
                triggerClick(fullscreenbtn);
                break;
            case 'Insert':
                openMctsModal();
                break;
            default:
                // 處理 0~9 數字鍵 (點擊 dot 或它上面的 man)
                if (e.key >= '0' && e.key <= '9') {
                    let dotIdx = parseInt(e.key);
                    let manToClick = null;
                    
                    // 優先檢查該點位上方是否有目前顯示中的「人 (man)」
                    if (isVisible(men_bottom[0]) && parseInt(men_bottom[0].getAttribute("i")) === dotIdx) {
                        manToClick = men_bottom[0];
                    } else if (isVisible(men_bottom[1]) && parseInt(men_bottom[1].getAttribute("i")) === dotIdx) {
                        manToClick = men_bottom[1];
                    }

                    if (manToClick) {
                        // 如果有顯示中的人,觸發點擊人
                        triggerClick(manToClick);
                    } else if (dots[dotIdx]) {
                        // 否則點擊該位置的點 (dot)
                        triggerClick(dots[dotIdx]);
                    }
                }
                break;
        }
    });
```
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

附件
konigsberg20260414ctrl7821.7z
(15.86 KiB) 已下载 2 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

當走棋時,如果我的瀏覽器切至其它頁面,再切回來時,發現棋子消失了。查找原因。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

gemini pro:

代码: 全选

這是一個非常經典的**「瀏覽器背景標籤頁節流 (Background Tab Throttling)」**所引發的計時器非同步/競爭條件 (Race Condition) 問題。

### 🔍 消失的原因分析

當你將瀏覽器切換到背景或其他分頁時,為了節省 CPU 與電池資源,現代瀏覽器(如 Chrome, Edge, Safari)會**大幅度降低 `setInterval` 和 `setTimeout` 的執行頻率**(通常最快只能每 1 秒執行一次,甚至更慢)。

在你的 `createAnimateMotion()` 函式中,動畫分成了兩個各自獨立的計時器來控制:
1. **`cssmoveinroute = setInterval(...)`**:負責每秒計算一次位移,並用 `transform: translate(x, y)` 推動棋子。
2. **`cssturntimeout = setTimeout(...)`**:負責在預計的總時間 (`dur * 1000 + 7` 毫秒) 抵達時,進行**「收尾動作」**——將棋子的真實 `cx` 與 `cy` 屬性瞬間設定到終點,並且把 `transform` 歸零 (`translate(0px)`)。

**💥 衝突發生點:**
當你在動畫途中切換分頁,`setInterval` 的執行次數會因為節流而**「嚴重落後」**。
然而,總結算時間到了,`setTimeout` 被觸發了,它幫你把棋子的 `cx/cy` 座標更新到了「最終目的地」,並移除了 `transform`。
**但是,落後的 `setInterval` 任務還在佇列中沒執行完!**
這時,落後的 `setInterval` 終於被瀏覽器放行執行,它會計算出舊的位移量(例如:`translate(360px, 180px)`),然後加在**已經到達終點的新座標上**。

這導致棋子從「終點位置」又被硬生生往外偏移了數百像素,直接**飛出了 SVG 的畫布範圍(ViewBox)**,看起來就像是憑空消失了。

---

### 🛠️ 解決方案

要解決這個問題,只需要在「收尾動作」的 `setTimeout` 觸發時,**強制清除那個可能還沒跑完的 `setInterval`** 即可。

請找到你的程式碼中的 `createAnimateMotion()` 函式,在 `cssturntimeout = setTimeout(function() {` 的**第一行**加上 `clearInterval(cssmoveinroute);`:

```javascript
    function createAnimateMotion() {
        // ... (前面程式碼省略) ...
            if (route_tmp.length > 2) {
                rgo++;
                cssmoveinroute = setInterval(function() {
                    // ... 計時器移動邏輯 ...
                }, 1000);
            }
            cssturntimeout = setTimeout(function() {
                
                // 👇 加入這行:確保收尾時,強制殺掉可能因為背景節流而卡住的移動計時器
                clearInterval(cssmoveinroute); 

                let last_dot = dots[route_tmp[route_tmp.length - 1]];
                moveman_top.innerHTML = "";
                moveman_bottom.innerHTML = "";
                moveman_top.setAttribute("cx", last_dot.getAttribute("cx"));
                moveman_top.setAttribute("cy", last_dot.getAttribute("cy"));
                // ... (後面程式碼省略) ...
                
            }, dur * 1000 + 7);
        }, 7);
    }
```

加上這行防呆機制後,當使用者切換回網頁時,如果時間已經到了,系統會直接讓棋子安穩地「瞬移」停在終點,而不會被殘留的位移計時器給推飛出界了!
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

附件
konigsberg20260414clearintv7822.7z
(15.88 KiB) 已下载 2 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

今日對局:

贏「簡單」:

代码: 全选

[[3,6],[-5,3,4,8,9,5,1],[1,6,4,3,8,4,9,8,5,9,1,5],[-5,6,5,4,7],[1,7,4,3,8,4,9,8,5,9,1,5,5,6,4,5,7,4],[-5,1,2,6,9,8],[8,7,4,3,8,4,8,9,5,9,1,5,5,6,4,5,7,4,2,1,6,2,9,6],[-5,7,4,5,2,1],[8,1,4,3,8,4,8,9,5,9,1,5,5,6,5,4,4,7,1,2,6,2,9,6,2,5],[-5,8,7,3,0,4,1,5,9],[9,1,4,3,8,4,8,9,9,5,5,1,5,6,5,4,4,7,1,2,6,2,9,6,2,5,8,7,7,3,3,0,0,4,4,1],[-5,1,0,4,7],[9,7,4,3,8,4,8,9,9,5,5,1,5,6,5,4,7,4,1,2,6,2,9,6,2,5,8,7,7,3,3,0,0,4,4,1,1,0],[-5,9,5,8,7,4,1,2],[2,7,4,3,8,4,8,9,5,9,5,1,5,6,5,4,4,7,2,1,6,2,9,6,2,5,8,7,7,3,3,0,0,4,4,1,1,0,5,8],[-5,7,3],[2,3,4,3,8,4,8,9,5,9,5,1,5,6,5,4,4,7,2,1,6,2,9,6,2,5,8,7,7,3,3,0,0,4,4,1,1,0,5,8],[-1,2,5,2,1,5,6,5,4,5,1,5,8,5,9,1,0,6,2,4,3,4,1,4,7,8,4,8,9,8,7,9,6,0,4,3,0,7,3]]
輸給「困難」:

代码: 全选

[[3,6],[-5,3,4,8,5],[5,6,4,3,8,4,5,8],[-5,6,9,5,1,2],[5,2,4,3,8,4,5,8,9,6,5,9,1,5,2,1],[-5,5,4,3],[3,2,3,4,8,4,5,8,9,6,5,9,1,5,2,1,4,5],[-5,2,1,5,8,4,0,3,7],[3,7,3,4,4,8,8,5,9,6,5,9,5,1,1,2,4,5,0,4,3,0,7,3],[-5,3,4,8,9,6],[6,7,4,3,8,4,8,5,6,9,5,9,5,1,1,2,4,5,0,4,3,0,7,3,9,8],[-5,7,3,0,4,5,2,6,9],[6,9,4,3,8,4,8,5,9,6,5,9,5,1,1,2,5,4,4,0,0,3,3,7,9,8,5,2,2,6],[-5,6,5,9,8],[8,9,4,3,8,4,8,5,9,6,9,5,5,1,1,2,5,4,4,0,0,3,3,7,8,9,5,2,2,6,6,5],[-5,9,6,5,1],[8,1,4,3,8,4,8,5,6,9,9,5,1,5,1,2,5,4,4,0,0,3,3,7,8,9,5,2,2,6,6,5],[-5,8,7,4,0],[0,1,4,3,8,4,8,5,6,9,9,5,1,5,1,2,5,4,0,4,0,3,3,7,8,9,5,2,2,6,6,5,8,7,7,4],[-5,1,0,3,7],[0,7,4,3,8,4,8,5,6,9,9,5,1,5,1,2,5,4,0,4,3,0,7,3,8,9,5,2,2,6,6,5,8,7,7,4,1,0],[-5,0,4,1,2,6,9],[9,7,4,3,8,4,8,5,9,6,9,5,1,5,2,1,5,4,4,0,3,0,7,3,8,9,5,2,2,6,6,5,8,7,7,4,1,0,4,1],[-5,7,4,3],[9,3,3,4,8,4,8,5,9,6,9,5,1,5,2,1,5,4,4,0,3,0,7,3,8,9,5,2,2,6,6,5,8,7,7,4,1,0,4,1],[-5,9,6],[6,3,3,4,8,4,8,5,6,9,9,5,1,5,2,1,5,4,4,0,3,0,7,3,8,9,5,2,2,6,6,5,8,7,7,4,1,0,4,1],[-1,3,0,3,4,4,1,4,0,1,5,1,0,5,4,5,2,2,6,2,1,6,5,6,9,9,5]]
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

konigsberg20260414backgroud7823

給svg加上background: blue;
附件
konigsberg20260414backgroud7823.7z
(15.88 KiB) 已下载 2 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

當搜尋到「致命」或「必敗」時,仍應把不會被對方一步殺的走法作為最佳走法。

代码: 全选

[[3,6],[-5,3,4,0,1,5,2,6,9],[9,6,4,3,0,4,1,0,5,1,2,5,6,2,9,6],[-5,6,2,1,4,5,8],[9,8,4,3,0,4,1,0,5,1,2,5,2,6,9,6,1,2,4,1,5,4,8,5],[-5,9,8,7,4,1,2],[2,8,4,3,0,4,1,0,5,1,2,5,2,6,9,6,2,1,1,4,5,4,8,5,8,9,8,7,7,4],[-5,8,4],[2,4,4,3,0,4,1,0,5,1,2,5,2,6,9,6,2,1,1,4,5,4,8,5,8,9,8,7,7,4,8,4],[-1,2,5,2,6,2,1,5,1,5,4,1,0,1,4,4,3,0,4]]
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5141
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 174 次
被圈友点赞: 204 次
联系:

Re: 改下哥尼斯堡網頁程式

帖子 ejsoon »

gemini pro:

代码: 全选

這是一個非常棒且敏銳的觀察!在很多棋類 AI 的開發中,這被稱為**「消極抵抗(Horizon Effect / Resignation)」問題**。

在原先的程式碼中,當 AI 發現某條路徑是「必敗(Guaranteed Loss)」時,排序邏輯把它往後推;但如果遇到「致命步(Immediate Loss,走這步馬上死)」時,原先的排序邏輯卻沒有正確地把「致命步」墊在「必敗步」的更下面。這導致 AI 產生了「反正都要輸了,不如直接撞上去早點解脫」的行為。

我們應該要教導 AI:**「好死不如賴活著,就算必敗,也要選擇撐最久的走法,等待對手失誤。」**

### 🛠️ 修正排序邏輯

請找到程式碼中 `runMCTS` 函式結尾處的 `moveStats.sort(...)` 區塊(大約在 730 行左右),將它**替換**為以下這段邏輯更嚴謹的排序程式碼:

```javascript
                moveStats.sort((a, b) => {
                    // 1. 【優先級最高】:必勝步 (Guaranteed Win) 必須排在最前面
                    if (a.guaranteedWin && !b.guaranteedWin) return -1;
                    if (!a.guaranteedWin && b.guaranteedWin) return 1;

                    // 2. 【優先級最低】:致命步 (Immediate Loss,走完馬上死) 必須排在最後面
                    if (a.immediateLoss && !b.immediateLoss) return 1;
                    if (!a.immediateLoss && b.immediateLoss) return -1;

                    // 3. 【優先級次低】:必敗步 (Guaranteed Loss,遲早會死) 排在倒數第二。
                    // 這樣就算全部都是敗局,AI 也會選擇「必敗步」而不是「致命步」來拖延時間。
                    if (a.guaranteedLoss && !b.guaranteedLoss) return 1;
                    if (!a.guaranteedLoss && b.guaranteedLoss) return -1;

                    // 4. 【常規比較】:都不是絕對勝負的情況,依照 MCTS 模擬的勝率排序
                    let aWinRate = a.wins / a.plays;
                    let bWinRate = b.wins / b.plays;
                    return bWinRate - aWinRate;
                });
```

### 💡 這段改動的意義:
我們明確地將走法的優先級劃分為四個階層:
1. **必勝步** `(Guaranteed Win)`:直接絕殺,優先走。
2. **常規步** `(Normal)`:看勝率高低決定。
3. **必敗步** `(Guaranteed Loss)`:陷入死胡同或被逼死,但至少能活過這回合。
4. **致命步** `(Immediate Loss)`:走過去直接被對手射殺,絕對不走(除非無路可退)。

這樣一來,當 AI 在介面上顯示 `⚠️ 必敗` 或 `💀 告負` 時,它為你自動走的那一步,絕對會是「能苟活最久」的最佳防守步,而不會自尋短見了!
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 2 访客