分享和讨论Javascript相关的话题
回复
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

加不進:

代码: 全选

h0h6 b9c7 b0c2 c6c5 e3e4 b7b6 h6h4 c9e7 g2e3 b6c6 g3g4 a9b9 g4g5 h7i7 h4h9 g7h9 a0b0 d9e8 b2b7 e7g5 b7i7 h9i7

position fen rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w 1 - 0 1 moves h2e2 h9g7 h0g2 i9h9 i0h0 g6g5
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

下面這段代碼: const fenMatch = text.match(/(?:position fen )?([a-zA-Z0-9/]+ [wb](?: -| \d+)*)/);
是為了匹配中國象棋局面的字符串,如:
「position fen rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w 1 - 0 1」,或者「rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w 1 - 0 1」,但是它不夠精確。現在改進為:必須包含九個「/」,前面一串含有/的字母只包含「rnbakcpRNBAKCP」,後面一個只能是「 w」或「 b」。

不用管position fen或其它可能的字符,只需要用空格分隔之後去檢查。

寫出改進的結果。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

代码: 全选

const text = "position fen rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w 1 - 0 1";

// 1. 如果只是想提取核心的局面和走子方
const match = text.match(/(?:[rnbakcpRNBAKCP1-9]+\/){9}[rnbakcpRNBAKCP1-9]+ [wb]/);

if (match) {
    console.log("匹配到的局勢:", match[0]);
}

// 2. 如果要檢查一個字串是否為合法的象棋 FEN (嚴格模式)
function isValidXiangqiFen(str) {
    // 這裡加上了結尾的後續參數匹配 (步數等,可選)
    const strictRegex = /^(?:[rnbakcpRNBAKCP1-9]+\/){9}[rnbakcpRNBAKCP1-9]+ [wb](?: -| \d+)*$/;
    return strictRegex.test(str.trim());
}
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

代码: 全选

const fenRegex = /\b(?:[rnbakcpRNBAKCP1-9]{1,9}\/){9}[rnbakcpRNBAKCP1-9]{1,9} [wb](?:(?: -| \d+){4})?\b/;
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

代码: 全选

                movesStr = movesStr.replace(/position fen /, '').replace(fenRegex, '').replace(/ moves /, '');
如何改進這段代碼?
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

代码: 全选

// 假設 fenRegex 已經定義好了
const cleanRegex = new RegExp(`position fen | moves |${fenRegex.source}`, 'g');

movesStr = movesStr.replace(cleanRegex, '').trim();
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

ejcees20260325fenRegex99972

解決了不能導入走法串的問題。

https://ejsoon.vip/wp-content/uploads/2 ... 99972.html
附件
ejcees20260325fenRegex99972.7z
(39.88 KiB) 已下载 54 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

評論顯示不全:
附件
Ejcees(1).jpg
Ejcees(1).jpg (69.04 KiB) 查看 2786 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

播放停止時應去掉「Auto-playing: 」。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

ejcees20260326comment99973

去掉comment錯誤的css,提示文字加上了step/total:

https://ejsoon.vip/wp-content/uploads/2 ... 99973.html
附件
ejcees20260326comment99973.7z
(39.88 KiB) 已下载 52 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

改進:
增加「home,end,pgup,pgdn,del,insert,up,down,left,right」按鍵功能。

home:回到棋局起始位置。

end:回到棋局結束位置。

pgup:往前五個回合。

pgdn:往後五個回合。

del:刪除後續走法(等同於btn-del-move)。

insert:導出/導入文本(等同於tool-exp-txt)。

up:往前一回合。

down:往後一回合。

left:往前一步。

right:往後一步。

所有按鍵功能在「自動播放、編輯局面、導出文本、範圍選取、改動移動及間隔時間」狀態下都將失效。

不過insert和del可以在「選圍選取」狀態下使用。

只需給出所要修改的地方,所有的代碼和注釋都應使用英文。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

對gemini pro來說非常簡單:

代码: 全选

// Add keyboard support at the end of DOMContentLoaded
        document.addEventListener('keydown', (e) => {
            // Check if user is currently changing move speed or interval
            const isEditingSettings = document.getElementById('interval-input') !== null || document.getElementById('speed-input') !== null;
            
            // Determine if the key pressed is allowed during Range Selection mode
            const allowedInRangeMode = e.key === 'Insert' || e.key === 'Delete';

            // Global block condition for shortcuts based on the application's current state
            if (isExportTextMode || isAutoPlaying || isEditingComment || isEditingSettings || (isRangeMode && !allowedInRangeMode)) {
                return;
            }

            // Undo / Redo logic (works in both Normal and Edit modes)
            if (e.ctrlKey && e.key === 'z') {
                e.preventDefault();
                isEditMode ? undoEdit() : undo();
                return;
            }
            if (e.ctrlKey && e.key === 'y') {
                e.preventDefault();
                isEditMode ? redoEdit() : redo();
                return;
            }

            // All subsequent navigation and action shortcuts are disabled in Edit Mode
            if (isEditMode) return;

            // Get max step bounds from the slider for navigation limits
            const maxStep = parseInt(stepSlider.max, 10) || 0;

            switch (e.key) {
                case 'Home':
                    e.preventDefault();
                    jumpToStep(0);
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'End':
                    e.preventDefault();
                    jumpToStep(maxStep);
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'PageUp':
                    e.preventDefault();
                    // Move backward 5 turns (10 steps/ply)
                    jumpToStep(Math.max(0, currentStepIndex - 10));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'PageDown':
                    e.preventDefault();
                    // Move forward 5 turns (10 steps/ply)
                    jumpToStep(Math.min(maxStep, currentStepIndex + 10));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowUp':
                case 'Up': // Handles legacy Edge/IE names
                    e.preventDefault();
                    // Move backward 1 turn (2 steps/ply)
                    jumpToStep(Math.max(0, currentStepIndex - 2));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowDown':
                case 'Down':
                    e.preventDefault();
                    // Move forward 1 turn (2 steps/ply)
                    jumpToStep(Math.min(maxStep, currentStepIndex + 2));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowLeft':
                case 'Left':
                    e.preventDefault();
                    // Move backward 1 step
                    jumpToStep(Math.max(0, currentStepIndex - 1));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowRight':
                case 'Right':
                    e.preventDefault();
                    // Move forward 1 step
                    jumpToStep(Math.min(maxStep, currentStepIndex + 1));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'Delete':
                case 'Del':
                    e.preventDefault();
                    // Triggers the deletion of the current move and the branch after it
                    deleteCurrentMoveAndAfter();
                    break;
                case 'Insert':
                case 'Ins':
                    e.preventDefault();
                    // Triggers the text export/import tool
                    document.getElementById('tool-exp-txt').click();
                    break;
            }
        });
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

ejcees20260326autoplay99974

去掉提示文字中的坐標,因為沒有太大意義。增加鍵盤事件,上下左右翻頁home,end,del,insert:

https://ejsoon.vip/wp-content/uploads/2 ... 99974.html
附件
ejcees20260326autoplay99974.7z
(40.38 KiB) 已下载 51 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

增加功能:
在「編輯局面、導出文本、範圍選取、改動移動及間隔時間、導出svg」狀態時,按下esc,則退出該狀態。

ctrl+left:回到上一個分支所在。
ctrl+right:回到下一個分支所在。
ctrl+up:前面最近一個分支,切換到上一個分支。
ctrl+up:前面最近一個分支,切換到下一個分支。

只需給出所要修改的地方,所有的代碼和注釋都應使用英文。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5786
注册时间: 2022年 11月 18日 17:36
联系:

Re: 將製作ejcees(中國象棋打譜程式)

帖子 ejsoon »

gemini pro

代码: 全选

// Add keyboard support at the end of DOMContentLoaded
        document.addEventListener('keydown', (e) => {
            const isEditingSettings = document.getElementById('interval-input') !== null || document.getElementById('speed-input') !== null;
            
            // --- Feature: ESC key to exit various active states ---
            if (e.key === 'Escape' || e.key === 'Esc') {
                e.preventDefault();
                
                // 1. Export SVG Modal
                const exportModal = document.querySelector('.ejcees-export-modal');
                if (exportModal) {
                    const closeBtn = exportModal.querySelector('.close-btn');
                    if (closeBtn) closeBtn.click();
                    return;
                }
                // 2. Edit Mode
                if (isEditMode) {
                    const editCancelBtn = document.getElementById('edit-cancel');
                    if (editCancelBtn) editCancelBtn.click();
                    return;
                }
                // 3. Export Text Mode
                if (isExportTextMode) {
                    const expCancelBtn = document.getElementById('exp-cancel');
                    if (expCancelBtn) expCancelBtn.click();
                    return;
                }
                // 4. Range Selection Mode
                if (isRangeMode) {
                    const rangeBtn = document.getElementById('btn-range');
                    if (rangeBtn) rangeBtn.click();
                    return;
                }
                // 5. Interval / Speed Settings
                if (isEditingSettings) {
                    const intervalCancel = document.getElementById('interval-cancel');
                    const speedCancel = document.getElementById('speed-cancel');
                    if (intervalCancel) intervalCancel.click();
                    if (speedCancel) speedCancel.click();
                    return;
                }
                // 6. Editing Comment
                if (isEditingComment) {
                    const commentCancel = document.querySelector('.btn-cancel'); 
                    if (commentCancel) commentCancel.click();
                    return;
                }
                return;
            }

            // --- Feature: Ctrl + Arrow keys for branch navigation ---
            if (e.ctrlKey) {
                if (e.key === 'ArrowLeft' || e.key === 'Left') {
                    e.preventDefault();
                    // Jump to the previous fork point
                    for (let i = currentStepIndex - 1; i >= 0; i--) {
                        let node = getNodeAtStep(i);
                        if (node && node.v && node.v.length > 1) {
                            jumpToStep(i);
                            saveStateToUndo();
                            updateToolHighlights();
                            break;
                        }
                    }
                    return;
                }
                if (e.key === 'ArrowRight' || e.key === 'Right') {
                    e.preventDefault();
                    // Jump to the next fork point
                    const totalDepth = getPathDepth(historyFEN, currentBranch);
                    for (let i = currentStepIndex + 1; i < totalDepth; i++) {
                        let node = getNodeAtStep(i);
                        if (node && node.v && node.v.length > 1) {
                            jumpToStep(i);
                            saveStateToUndo();
                            updateToolHighlights();
                            break;
                        }
                    }
                    return;
                }
                if (e.key === 'ArrowUp' || e.key === 'Up' || e.key === 'ArrowDown' || e.key === 'Down') {
                    e.preventDefault();
                    const isUp = (e.key === 'ArrowUp' || e.key === 'Up');
                    
                    // Find the nearest previous fork and its respective index
                    let forkIndex = -1;
                    let tempNode = historyFEN;
                    let currentForks = []; 

                    for (let i = 0; i <= currentStepIndex; i++) {
                        if (tempNode && tempNode.v && tempNode.v.length > 1) {
                            forkIndex++;
                            currentForks.push({ step: i, forkIdx: forkIndex, node: tempNode });
                        }
                        const choice = (tempNode && tempNode.v && tempNode.v.length > 1) ? (currentBranch[forkIndex] || 0) : 0;
                        if (tempNode && tempNode.v && tempNode.v.length > 0) {
                            tempNode = tempNode.v[choice];
                        } else {
                            break;
                        }
                    }

                    if (currentForks.length > 0) {
                        let lastFork = currentForks[currentForks.length - 1];
                        let choicesCount = lastFork.node.v.length;
                        let currentChoice = currentBranch[lastFork.forkIdx] !== undefined ? currentBranch[lastFork.forkIdx] : 0;
                        let newChoice;
                        
                        if (isUp) {
                            // Switch to previous branch
                            newChoice = (currentChoice - 1 + choicesCount) % choicesCount;
                        } else {
                            // Switch to next branch
                            newChoice = (currentChoice + 1) % choicesCount;
                        }
                        
                        // Apply branch change and rerender
                        updateBranchPath(lastFork.forkIdx, newChoice);
                        renderRecordUI();
                        
                        // Stay at the current depth if possible, or cap at the new branch's maximum depth
                        const newDepth = getPathDepth(historyFEN, currentBranch);
                        jumpToStep(Math.min(currentStepIndex, newDepth - 1));
                        
                        saveStateToUndo();
                        updateToolHighlights();
                    }
                    return;
                }
            }

            // Determine if the key pressed is allowed during Range Selection mode
            const allowedInRangeMode = e.key === 'Insert' || e.key === 'Delete';

            // Global block condition for shortcuts based on the application's current state
            if (isExportTextMode || isAutoPlaying || isEditingComment || isEditingSettings || (isRangeMode && !allowedInRangeMode)) {
                return;
            }

            // Undo / Redo logic
            if (e.ctrlKey && e.key === 'z') {
                e.preventDefault();
                isEditMode ? undoEdit() : undo();
                return;
            }
            if (e.ctrlKey && e.key === 'y') {
                e.preventDefault();
                isEditMode ? redoEdit() : redo();
                return;
            }

            // Navigation and action shortcuts are disabled in Edit Mode
            if (isEditMode) return;

            // Get max step bounds from the slider for navigation limits
            const maxStep = parseInt(stepSlider.max, 10) || 0;

            switch (e.key) {
                case 'Home':
                    e.preventDefault();
                    jumpToStep(0);
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'End':
                    e.preventDefault();
                    jumpToStep(maxStep);
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'PageUp':
                    e.preventDefault();
                    // Move backward 5 turns (10 steps/ply)
                    jumpToStep(Math.max(0, currentStepIndex - 10));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'PageDown':
                    e.preventDefault();
                    // Move forward 5 turns (10 steps/ply)
                    jumpToStep(Math.min(maxStep, currentStepIndex + 10));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowUp':
                case 'Up': // Handles legacy Edge/IE names
                    e.preventDefault();
                    // Move backward 1 turn (2 steps/ply)
                    jumpToStep(Math.max(0, currentStepIndex - 2));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowDown':
                case 'Down':
                    e.preventDefault();
                    // Move forward 1 turn (2 steps/ply)
                    jumpToStep(Math.min(maxStep, currentStepIndex + 2));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowLeft':
                case 'Left':
                    e.preventDefault();
                    // Move backward 1 step
                    jumpToStep(Math.max(0, currentStepIndex - 1));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'ArrowRight':
                case 'Right':
                    e.preventDefault();
                    // Move forward 1 step
                    jumpToStep(Math.min(maxStep, currentStepIndex + 1));
                    saveStateToUndo();
                    updateToolHighlights();
                    break;
                case 'Delete':
                case 'Del':
                    e.preventDefault();
                    // Triggers the deletion of the current move and the branch after it
                    deleteCurrentMoveAndAfter();
                    break;
                case 'Insert':
                case 'Ins':
                    e.preventDefault();
                    // Triggers the text export/import tool
                    document.getElementById('tool-exp-txt').click();
                    break;
            }
        });
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复
  • 相似主题
    回复总数
    阅读次数
    最新帖子

在线用户

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