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

分享和讨论Javascript相关的话题
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

根據盤面及走法,得到所移動的棋子起始和結束坐標:

代码: 全选

/**
 * Advanced: Derives coordinates from FEN and English notation (supports handling ambiguity for multiple pawns)
 * Supported formats: C2=5, +2=3, =P+1, 3P=9, etc.
 */
function deriveCoordsFromEN(fen, moveEN) {
    if (!moveEN) return null;

    // 1. Parse FEN to get the board array and the current turn
    const parts = fen.split(' ');
    const isRed = (parts[1] === 'w');
    const board = parseFENToBoard(parts[0]); // Convert to 10x9 array

    // 2. Parse English move string
    // Format parsing: [prefix?][piece/col?][action][target value]
    const match = moveEN.match(/^([+\-=1-9])?([a-zA-Z1-9])?([+\-=])(\d)$/);
    if (!match) return null;

    let prefix = match[1];      // +, -, =, 1-9 (representing front, back, middle, or ordinal number)
    let indicator = match[2];   // Piece code (e.g., P) or starting column (e.g., 2)
    const action = match[3];    // +, -, =
    const targetVal = parseInt(match[4], 10);

    // 3. Collect all pieces of the same type belonging to the current side on the board
    let searchChar = (indicator && /[a-zA-Z]/.test(indicator)) ? 
                     (isRed ? indicator.toUpperCase() : indicator.toLowerCase()) : 
                     (isRed ? 'P' : 'p'); // Default to pawn

    let candidates = [];
    for (let y = 0; y < 10; y++) {
        for (let x = 0; x < 9; x++) {
            if (board[y][x] === searchChar) {
                candidates.push({ x, y, col: isRed ? (9 - x) : (x + 1) });
            }
        }
    }

    // 4. Filter starting piece (startX, startY) based on ambiguity rules
    let piece = null;

    // Case A: Starting column specified (e.g., "2" in C2=5 or +2=3)
    if (indicator && /[1-9]/.test(indicator)) {
        const startCol = parseInt(indicator, 10);
        let colPieces = candidates.filter(p => p.col === startCol);

        if (prefix) {
            // Handle cases like "+2=3" (front-2-move-to-3)
            sortPiecesFrontToBack(colPieces, isRed);
            const idx = parsePrefixToIndex(prefix, colPieces.length);
            piece = colPieces[idx];
        } else {
            // Handle cases like "C2=5"
            piece = colPieces[0];
        }
    } 
    // Case B: Special prefix used (e.g., =P+1 or 3P=9)
    else if (prefix) {
        // First, identify columns with multiple pieces
        let multiCols = [];
        for(let c=1; c<=9; c++) {
            if (candidates.filter(p => p.col === c).length > 1) multiCols.push(c);
        }

        if (multiCols.length > 1 && prefix !== '=') {
            // This is the "two-column pawn" rule: prefix represents "front/back", indicator represents "which column"
            // If indicator is P, we need to search all candidates
            sortPiecesFrontToBack(candidates, isRed);
            const idx = parsePrefixToIndex(prefix, candidates.length); 
            piece = candidates[idx];
        } else {
            // Single-column, multiple-piece rule (front, middle, back)
            sortPiecesFrontToBack(candidates, isRed);
            const idx = parsePrefixToIndex(prefix, candidates.length);
            piece = candidates[idx];
        }
    }

    if (!piece) return null;

    // 5. Calculate target coordinates (endX, endY)
    const startX = piece.x;
    const startY = piece.y;
    let endX = startX, endY = startY;

    if (action === '=') {
        endX = isRed ? (9 - targetVal) : (targetVal - 1);
    } else {
        const direction = isRed ? -1 : 1; // Red moves decrease Y, Black moves increase Y
        const sign = (action === '+') ? 1 : -1;
        const isJumping = ['N','B','A'].includes(searchChar.toUpperCase());

        if (isJumping) {
            endX = isRed ? (9 - targetVal) : (targetVal - 1);
            const dx = Math.abs(endX - startX);
            const dy = (searchChar.toUpperCase() === 'N') ? (dx === 1 ? 2 : 1) : (dx === 2 ? 2 : 1);
            endY = startY + (direction * sign * dy);
        } else {
            endY = startY + (direction * sign * targetVal);
        }
    }

    return { startX, startY, endX, endY };
}

/** Helper: Parse FEN into an array */
function parseFENToBoard(fenPart) {
    return fenPart.split('/').map(row => {
        let line = [];
        for (let char of row) {
            if (/\d/.test(char)) line.push(...Array(parseInt(char)).fill(null));
            else line.push(char);
        }
        return line;
    });
}

/** Helper: Sort pieces based on Xiangqi rules (from front to back) */
function sortPiecesFrontToBack(pieces, isRed) {
    // Red: Smaller Y is closer to the front
    // Black: Larger Y is closer to the front
    if (isRed) pieces.sort((a, b) => a.y - b.y);
    else pieces.sort((a, b) => b.y - a.y);
}

/** Helper: Convert prefix symbol to array index */
function parsePrefixToIndex(prefix, total) {
    if (prefix === '+') return 0; // Front
    if (prefix === '-') return total - 1; // Back
    if (prefix === '=') return 1; // Middle (assuming 3 pieces)
    if (/[1-9]/.test(prefix)) return parseInt(prefix, 10) - 1; // 1-9 ordinal
    return 0;
}
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

著法的添加應在棋子移動開始前,而不是移完之後。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

寫幾個js函式:

一,查詢對象深度的js函式:

historyFEN是一個全局對象變量,該對象的格式為{f:'sth', m:'sth',v:[...]}

v中又可能有一個或多個相同格式的子對象,子對象中的v還會有子對象,依此類推。

查詢這個對象的單線子節點數量。

當某個節點中的v存在兩個以上的子對象時,將由全局數組變量currentBranch中的數字指定走哪條分支。

比如historyFEN=a->b->(c->d->e,f->(g->h,i)),currentBranch=[1,0],說明在遇到第一個分支時選擇f,第二個分支走g,最終結果是a->b->f->g->h,深度為5。

二,更改currentBranch函式:

當某個節點切換時,currentBranch將需要更改。從所更改的節點往下探索,當遇到一個分支時,currentBranch.push(0),選擇首個分支繼續往下探索。

比如historyFEN=a->b->(c->d->e,f->(g->h,i)),currentBranch原值為[0](abcde),當我把分支由c切至f時,其值變為[1,0](abfgh)。

三,通過currentStepIndex獲取指定對象:

currentStepIndex是全局變量,它是大於或等於0的整數。

currentBranch跟historyFEN結合,成了一個單線的父子對象路徑。currentStepIndex指的該路徑的第幾個子對象。

比如historyFEN=a->b->(c->d->e,f->(g->h,i)),currentBranch值為[1,0],currentStepIndex=2,則指定的對象是f。

四,刪除某個對象節點及其子對象。

五,為某個節點添加對象。

所有代碼和注釋都要是英文。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

ejceesrcdstep內有branch-marker。

當存在分支時,branch-marker將顯示出分子和分母,如2/2,分母指有幾個分支,分子指當前處於第幾個分支。branch-marker的背景將變為淺紅色。

如果點擊ejceesrcdstep的target是branch-marker,則將生成一個菜單,選擇切換分支。再次點擊則收回菜單

菜單有「序號,走法,刪除符號」,如「1. 兵五進一,刪除」。點擊走法就會切換到該分支。點擊「刪除符號」就會把這個分支刪除。

只需給出所要修改的地方。所有注釋都要使用英文。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

上次由 ejsoon 在 2026年 2月 22日 16:42,总共编辑 2 次。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

評論點擊就會進入編輯。

下面是一排小按鈕,有「刪除著法、範圍選取、自動播放、移動速度、棋譜文本」,當評論開始時,這排按鈕會換成「確認、取消」。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

改進:

一,當分支切換之後,.ejceesstepdrop的拖動最大值並沒有改變,請修正。

二,評論點擊就會進入編輯。

下面是一排小按鈕,有「刪除著法、範圍選取、自動播放、移動速度、棋譜文本」,當評論開始時,這排按鈕會換成「確認、取消」。

三,保存和上傳json

只需給出所要修改的地方。所有注釋都要使用英文。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 4559
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 172 次
被圈友点赞: 200 次
联系:

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

帖子 ejsoon »

改進:

一,當分支切換之後,.ejceesstepdrop的拖動最大值並沒有改變,請修正。

當非兵卒的兩個相同棋子處於同一列時,轉中文出錯。比如「+A-5」應轉為「前仕退五」,但是現在轉成了「前退五」。請修正。

二,.ejceesnote內的html結構為「div.ejceescomment+div.ejceestextbtn」。其中div.ejceestextbtn佔據底部一行,div.ejceescomment佔據餘下區域。

div.ejceescomment顯示文字評論,即以下數據結構
historyFEN = {
fen: INITIAL_FEN,
move: null,
lastMove: null,
comment: "some words"
v: []
};
中的comment。

當點擊div.ejceescomment時,這個區域就會變成一個textarea,進入輸入評論狀態。這時將不能走棋,不能拖動棋譜。

當進入輸入評論狀態時,div.ejceestextbtn將變成「確認、取消」兩個按鍵。當點擊確認時,文字評論將被錄入historyFEN中對應的節點,點擊取消則不會錄入,之後取消評論狀態。

當不處於評論狀態時,div.ejceestextbtn裡面是一排小按鍵,有「刪除著法、範圍選取、自動播放、移動速度」。

這些按鍵的樣式參考.tool-btn,裡面都是一個svg-path圖案(移動速度除外)。其中「確認」是一個綠色的鉤,取消是紅色的叉,刪除著法是一個垃圾桶,範圍選取是左右兩個直角引號(類似繁體中文的引號),自動播放是一個朝右的三角形(但播放時會變成兩個豎線),移動速度會直接顯示數字加s(如0.36s),

只需給出所要修改的地方。所有注釋都要使用英文。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复

在线用户

正浏览此版面之用户: Google [Bot] 和 1 访客