/** * 掼蛋游戏UI交互 */ // 游戏实例 let game = null; let selectedCards = new Set(); // 初始化 document.addEventListener('DOMContentLoaded', () => { initEventListeners(); }); function initEventListeners() { // 开始游戏 document.getElementById('btn-start').addEventListener('click', startGame); // 出牌按钮 document.getElementById('btn-play').addEventListener('click', playSelectedCards); document.getElementById('btn-pass').addEventListener('click', passTurn); document.getElementById('btn-hint').addEventListener('click', showHint); // 下一局 document.getElementById('btn-next-round').addEventListener('click', nextRound); } // 开始游戏 function startGame() { game = new GuandanGame(); const result = game.startGame(); if (result.success) { document.getElementById('start-screen').style.display = 'none'; document.getElementById('game-over-modal').style.display = 'none'; document.getElementById('game-status').style.display = 'none'; // 显示规则 showRules(); // 更新UI updateGameInfo(); renderHandCards(); updatePlayerStatus(); // 清除提示 document.getElementById('played-by').textContent = '等待出牌...'; document.getElementById('played-cards').innerHTML = ''; // 显示当前玩家 showTurnIndicator(); // 如果AI先手 if (game.currentPlayer !== 0) { setTimeout(() => processAITurn(), 1000); } } } // 显示规则 function showRules() { document.getElementById('rule-level').textContent = game.currentLevel; document.getElementById('rule-wild').textContent = game.currentLevel; document.getElementById('rules-modal').style.display = 'flex'; setTimeout(() => { document.getElementById('rules-modal').style.display = 'none'; }, 3000); } // 更新游戏信息 function updateGameInfo() { document.getElementById('current-level').textContent = game.currentLevel; document.getElementById('team-a-level').textContent = game.teamLevels[0]; document.getElementById('team-b-level').textContent = game.teamLevels[1]; } // 渲染手牌 function renderHandCards() { const container = document.getElementById('hand-cards'); container.innerHTML = ''; const player = game.players[0]; selectedCards.clear(); updatePlayButton(); player.cards.forEach((card, index) => { const cardEl = createCardElement(card, index); container.appendChild(cardEl); }); document.getElementById('my-card-count').textContent = `${player.cards.length}张`; } // 创建牌元素 function createCardElement(card, index) { const el = document.createElement('div'); el.className = 'card'; el.dataset.cardId = card.id; const isRed = card.suit === '♥' || card.suit === '♦'; const colorClass = isRed ? 'red' : 'black'; const isWild = game.isWildCard(card); if (isWild) { el.classList.add('wild'); } // 王牌的显示 let displayRank = card.rank; let displaySuit = card.suit; if (card.isJoker) { displaySuit = '🃏'; displayRank = card.rank === '大王' ? '大' : '小'; } el.innerHTML = `
${displayRank} ${displaySuit}
${displaySuit}
`; el.addEventListener('click', () => toggleCardSelection(card.id, el)); return el; } // 切换牌选择 function toggleCardSelection(cardId, el) { if (selectedCards.has(cardId)) { selectedCards.delete(cardId); el.classList.remove('selected'); } else { selectedCards.add(cardId); el.classList.add('selected'); } updatePlayButton(); } // 更新出牌按钮状态 function updatePlayButton() { const hasSelection = selectedCards.size > 0; const isMyTurn = game && game.currentPlayer === 0 && game.gameState === 'playing'; document.getElementById('btn-play').disabled = !hasSelection || !isMyTurn; document.getElementById('btn-pass').disabled = !isMyTurn; document.getElementById('btn-hint').disabled = !isMyTurn; } // 出牌 function playSelectedCards() { if (!game || game.currentPlayer !== 0) return; const cardIds = Array.from(selectedCards); const result = game.playCards(0, cardIds); if (result.success) { // 显示出的牌 showPlayedCards(result.cards, 0, result.cardType.type); // 更新手牌 renderHandCards(); // 更新玩家状态 updatePlayerStatus(); // 清空选中 selectedCards.clear(); // 检查是否出完 if (result.isFinished) { showGameStatus(`${game.players[0].name} 出完啦!排名第${game.players[0].rank}`); } // 检查游戏是否结束 if (game.gameState === 'ended') { showGameOver(); } else { // AI回合 setTimeout(() => processAITurn(), 800); } } else { showGameStatus(result.message, true); } } // 不出 function passTurn() { if (!game || game.currentPlayer !== 0) return; const result = game.pass(0); if (result.success) { showGameStatus('你选择了不出'); if (result.roundEnd) { showGameStatus('本轮结束,重新开始'); document.getElementById('played-cards').innerHTML = ''; document.getElementById('played-by').textContent = '等待出牌...'; } updatePlayButton(); setTimeout(() => processAITurn(), 800); } else { showGameStatus(result.message, true); } } // 提示 function showHint() { // 简化提示:选择最小的几张牌 const player = game.players[0]; if (player.cards.length > 0) { // 清除之前的选择 selectedCards.clear(); document.querySelectorAll('.card.selected').forEach(el => el.classList.remove('selected')); // 选择最小的牌(简化处理) const card = player.cards[player.cards.length - 1]; selectedCards.add(card.id); const el = document.querySelector(`[data-card-id="${card.id}"]`); if (el) el.classList.add('selected'); updatePlayButton(); showGameStatus('提示:已选择一张较小的牌'); } } // AI回合处理 function processAITurn() { if (!game || game.gameState === 'ended') return; const playerId = game.currentPlayer; if (playerId === 0) return; // 回到玩家回合 const player = game.players[playerId]; const decision = game.makeAIDecision(playerId); if (decision.action === 'play') { const cardIds = decision.cards.map(c => c.id); const result = game.playCards(playerId, cardIds); if (result.success) { showPlayedCards(result.cards, playerId, result.cardType.type); updatePlayerStatus(); if (result.isFinished) { showGameStatus(`${player.name} 出完啦!排名第${player.rank}`); } if (game.gameState === 'ended') { showGameOver(); return; } } } else { // 不出 game.pass(playerId); showGameStatus(`${player.name} 不出`); } showTurnIndicator(); updatePlayButton(); // 继续AI回合或等待玩家 if (game.currentPlayer !== 0 && game.gameState !== 'ended') { setTimeout(() => processAITurn(), 800); } } // 显示出的牌 function showPlayedCards(cards, playerId, cardType) { const container = document.getElementById('played-cards'); const player = game.players[playerId]; container.innerHTML = ''; cards.forEach(card => { const el = document.createElement('div'); el.className = 'card small'; const isRed = card.suit === '♥' || card.suit === '♦'; const colorClass = isRed ? 'red' : 'black'; const isWild = game.isWildCard(card); if (isWild) el.classList.add('wild'); // 王牌的显示 let displayRank = card.rank; let displaySuit = card.suit; if (card.isJoker) { displaySuit = '🃏'; displayRank = card.rank === '大王' ? '大' : '小'; } el.innerHTML = `
${displayRank} ${displaySuit}
${displaySuit}
`; container.appendChild(el); }); // 更新谁出的 const typeNames = { 'single': '单张', 'pair': '对子', 'triple': '三张', 'triple_pair': '三带二', 'straight': '顺子', 'consecutive_pairs': '三连对', 'steel_plate': '钢板', 'bomb4': '炸弹(4)', 'bomb5': '炸弹(5)', 'bomb6': '炸弹(6)', 'bomb7': '炸弹(7)', 'bomb8': '炸弹(8)', 'joker_bomb': '天王炸' }; document.getElementById('played-by').innerHTML = `${player.name} 出了 ${typeNames[cardType] || cardType}`; // 更新玩家剩余牌数 updateCardCount(playerId); } // 更新玩家状态 function updatePlayerStatus() { // 更新剩余牌数显示 for (let i = 0; i < 4; i++) { updateCardCount(i); } } // 更新某玩家牌数 function updateCardCount(playerId) { const player = game.players[playerId]; const count = player.cards.length; let selector; if (playerId === 0) { selector = '#my-card-count'; } else if (playerId === 1) { selector = '#player-left .card-count'; } else if (playerId === 2) { selector = '#player-top .card-count'; } else { selector = '#player-right .card-count'; } const el = document.querySelector(selector); if (el) el.textContent = `${count}张`; } // 显示回合指示 function showTurnIndicator() { if (!game) return; const player = game.players[game.currentPlayer]; // 更新出牌提示文字 const playedBy = document.getElementById('played-by'); if (playedBy && playedBy.textContent === '等待出牌...') { playedBy.innerHTML = `轮到 ${player.name} 出牌`; } // 高亮当前玩家 document.querySelectorAll('.player, .player-self').forEach(el => { el.classList.remove('active-turn'); }); const playerEl = document.getElementById( game.currentPlayer === 0 ? 'player-self' : game.currentPlayer === 1 ? 'player-left' : game.currentPlayer === 2 ? 'player-top' : 'player-right' ); if (playerEl) playerEl.classList.add('active-turn'); } // 显示游戏状态提示 function showGameStatus(message, isError = false) { const el = document.getElementById('game-status'); el.textContent = message; el.className = isError ? 'game-status error' : 'game-status'; el.style.display = 'block'; setTimeout(() => { el.style.display = 'none'; }, 2000); } // 显示游戏结束 function showGameOver() { const result = game.endGame(); document.getElementById('game-result-title').textContent = result.winner === 0 ? '我方胜利!' : '对方胜利!'; // 排名列表 const rankList = document.getElementById('rank-list'); rankList.innerHTML = ''; result.ranks.sort((a, b) => a.rank - b.rank).forEach(r => { const div = document.createElement('div'); div.className = 'rank-item'; div.innerHTML = ` 第${r.rank}名 ${r.name} `; rankList.appendChild(div); }); // 升级信息 const upgradeInfo = document.getElementById('upgrade-info'); const levelNames = { 1: '险胜(+1)', 2: '单上(+2)', 3: '双上(+3)' }; upgradeInfo.innerHTML = `

获胜方升 ${result.upgrade} 级

我方:${game.teamLevels[0]} → ${result.winner === 0 ? getNextLevel(game.teamLevels[0], result.upgrade) : game.teamLevels[0]}

`; document.getElementById('game-over-modal').style.display = 'flex'; } // 获取下一级 function getNextLevel(current, upgrade) { const levels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']; const idx = levels.indexOf(current); return levels[Math.min(idx + upgrade, levels.length - 1)]; } // 下一局 function nextRound() { if (!game) return; const result = game.endGame(); const nextResult = game.nextRound(result.winner, result.upgrade); if (nextResult.gameOver) { showGameStatus(nextResult.finalWinner === 0 ? '恭喜!你们赢得了整场比赛!' : '对方赢得了整场比赛!'); document.getElementById('start-screen').style.display = 'flex'; document.getElementById('game-over-modal').style.display = 'none'; return; } // 重置UI document.getElementById('game-over-modal').style.display = 'none'; document.getElementById('played-cards').innerHTML = ''; document.getElementById('played-by').textContent = '等待出牌...'; updateGameInfo(); renderHandCards(); updatePlayerStatus(); showTurnIndicator(); if (game.currentPlayer !== 0) { setTimeout(() => processAITurn(), 1000); } }