代码: 全选
在提供的源代碼中,當玩家(包括後手方)選擇一個自己面板上的棋子後,再點擊場上對方的棋子以顯示預放棋子(ghost pieces),主要涉及以下三個核心函數與邏輯區塊:
### 1. 綁定點擊事件的邏輯 (`renderBoard`)
在 `renderBoard()` 函數中,當遍歷並渲染棋盤上的棋子時,若該棋子屬於**對方**(`p.owner !== currentPlayer`),程式會動態移除 `placed-piece`,賦予 `board-target` 類別,並綁定點擊事件來觸發 `handleTargetClick(p.id)`:
```javascript
if (p.owner !== currentPlayer && tempPieces.length < ((turnNumber===1||pieces.length===35)?1:2)) {
use.classList.remove('placed-piece');
use.classList.add('board-target');
use.onclick = (e) => { e.stopPropagation(); handleTargetClick(p.id); };
}
```
---
### 2. 處理目標點擊的邏輯 (`handleTargetClick`)
當點擊對方的棋子後,會執行 `handleTargetClick(pieceId)` 函數。此函數會確認是否已先選定模板棋子 (`selectedTile`)、驗證點擊目標是否為對手棋子,並在通過條件後設定 `targetOpponentPieceId`,接著調用 `generateGhosts()`:
```javascript
function handleTargetClick(pieceId) {
if (!selectedTile) return;
let p = pieces.find(x => x.id === pieceId);
if (!p || p.owner === currentPlayer) return;
if (tempPieces.length === 1 && turnNumber > 1) {
let firstScored = checkTriGoldenScoring(tempPieces[0], true);
if (pieceId !== tempPieces[0].targetId && !firstScored) {
targetOpponentPieceId = pieceId;
} else {
targetOpponentPieceId = pieceId;
}
} else {
targetOpponentPieceId = pieceId;
}
generateGhosts(); // 生成預放棋子
updateUI();
renderBoard();
}
```
---
### 3. 計算並生成預放棋子的邏輯 (`generateGhosts`)
此函數負責實際計算預放棋子(Ghosts)的幾何位置。它會讀取目標棋子的邊長,透過 `attachByEdge` 嘗試將所選形狀貼合在目標棋子的邊緣上,並進行重疊與貼合次數的合法性檢查,最後將結果存入 `ghosts` 陣列中以便在畫面上渲染半透明預放塊:
```javascript
function generateGhosts() {
ghosts = [];
if (!selectedTile || !targetOpponentPieceId) return;
const tPiece = pieces.find(p => p.id === targetOpponentPieceId);
const selType = SHAPE_MAP[selectedTile];
const selMir = isFlipped[selectedTile];
// 透過迴圈計算邊緣貼合與碰撞檢測...
// 滿足條件的候選位置會被push進 ghosts 陣列中
}
```