From 079c863152563bb66e8e19737a6c43ff9e9b23b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=89=AC?= <2125069575@qq.com> Date: Fri, 9 Jan 2026 09:35:42 +0800 Subject: [PATCH] Update English learning app with DeepSeek API integration and new dialogue scenes --- english-learning-uv | 1 + index.html | 85 +++++++ script.js | 601 ++++++++++++++++++++++++++++++++++++++++++++ style.css | 354 ++++++++++++++++++++++++++ 4 files changed, 1041 insertions(+) create mode 160000 english-learning-uv create mode 100644 index.html create mode 100644 script.js create mode 100644 style.css diff --git a/english-learning-uv b/english-learning-uv new file mode 160000 index 0000000..d8122fe --- /dev/null +++ b/english-learning-uv @@ -0,0 +1 @@ +Subproject commit d8122fe3d40ffbd244d0beb091ba52b0261278d5 diff --git a/index.html b/index.html new file mode 100644 index 0000000..2d51df5 --- /dev/null +++ b/index.html @@ -0,0 +1,85 @@ + + + + + + 斗地主游戏 + + + +
+
+

斗地主游戏

+
+ 等待开始游戏 + 当前玩家: +
+
+ +
+ +
+
地主牌:
+
+
+ + +
+
+ 电脑玩家1 + 17 + +
+
+
+
+ + +
+
+ 电脑玩家2 + 17 + +
+
+
+
+ + +
+
当前出牌:
+
+
+ + +
+
+ + 17 + +
+
+
+
+
+ +
+ + + +
+ 积分: + 0 +
+
+
+ + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..60d4b3f --- /dev/null +++ b/script.js @@ -0,0 +1,601 @@ +// 卡片类 +class Card { + constructor(suit, rank, value) { + this.suit = suit; // 花色:spades, hearts, clubs, diamonds, joker + this.rank = rank; // 点数:A, 2, 3, ..., 10, J, Q, K, 小王, 大王 + this.value = value; // 牌值:用于比较大小 + this.selected = false; + } + + // 获取卡片的HTML表示 + getHTML(selected = false) { + const cardDiv = document.createElement('div'); + cardDiv.className = `card ${this.suit} ${selected ? 'selected' : ''}`; + cardDiv.dataset.suit = this.suit; + cardDiv.dataset.rank = this.rank; + cardDiv.dataset.value = this.value; + + // 花色符号 + const suitSymbol = { + spades: '♠', + hearts: '♥', + clubs: '♣', + diamonds: '♦' + }[this.suit] || this.rank; + + // 创建卡片内容 + const rankTop = document.createElement('div'); + rankTop.className = 'rank-top'; + rankTop.textContent = this.rank; + + const suitMiddle = document.createElement('div'); + suitMiddle.className = 'suit-middle'; + suitMiddle.textContent = suitSymbol; + + const rankBottom = document.createElement('div'); + rankBottom.className = 'rank-bottom'; + rankBottom.textContent = this.rank; + + // 组装卡片 + cardDiv.appendChild(rankTop); + cardDiv.appendChild(suitMiddle); + cardDiv.appendChild(rankBottom); + + return cardDiv; + } + + // 获取背面HTML + static getBackHTML() { + const cardDiv = document.createElement('div'); + cardDiv.className = 'card card-back'; + return cardDiv; + } +} + +// 游戏类 +class LandlordGame { + constructor() { + this.players = [ + { id: 0, name: '我', cards: [], role: '', lastPlay: [] }, + { id: 1, name: '电脑玩家1', cards: [], role: '', lastPlay: [] }, + { id: 2, name: '电脑玩家2', cards: [], role: '', lastPlay: [] } + ]; + this.deck = []; + this.landlordCards = []; + this.currentPlayer = 0; + this.gameStatus = 'waiting'; // waiting, calling, playing, ended + this.landlord = -1; + this.lastPlayPlayer = -1; + this.lastPlayCards = []; + this.score = 0; + this.callLandlordCount = 0; + + this.initializeElements(); + this.initializeEventListeners(); + this.initializeDeck(); + } + + // 初始化DOM元素 + initializeElements() { + this.elements = { + startGame: document.getElementById('start-game'), + gameStatus: document.getElementById('game-status'), + currentPlayer: document.getElementById('current-player'), + landlordCardsArea: document.getElementById('landlord-cards-area'), + landlordButtons: document.querySelector('.landlord-buttons'), + callLandlord: document.getElementById('call-landlord'), + noCall: document.getElementById('no-call'), + playButtons: document.querySelector('.play-buttons'), + playCards: document.getElementById('play-cards'), + pass: document.getElementById('pass'), + currentPlayCards: document.getElementById('current-play-cards'), + currentPlayInfo: document.getElementById('current-play-info'), + playerCards: [ + document.getElementById('self-cards'), + document.getElementById('player-1-cards'), + document.getElementById('player-2-cards') + ], + playerCardsCount: [ + document.getElementById('self-cards-count'), + document.getElementById('player-1-cards-count'), + document.getElementById('player-2-cards-count') + ], + playerRoles: [ + document.getElementById('self-role'), + document.getElementById('player-1-role'), + document.getElementById('player-2-role') + ], + lastPlay: [ + document.getElementById('self-last-play'), + document.getElementById('player-1-last-play'), + document.getElementById('player-2-last-play') + ], + score: document.getElementById('score') + }; + } + + // 初始化事件监听器 + initializeEventListeners() { + this.elements.startGame.addEventListener('click', () => this.startGame()); + this.elements.callLandlord.addEventListener('click', () => this.callLandlord()); + this.elements.noCall.addEventListener('click', () => this.noCall()); + this.elements.playCards.addEventListener('click', () => this.playSelectedCards()); + this.elements.pass.addEventListener('click', () => this.pass()); + } + + // 初始化牌组 + initializeDeck() { + this.deck = []; + const suits = ['spades', 'hearts', 'clubs', 'diamonds']; + const ranks = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']; + const values = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + + // 添加普通牌 + for (let i = 0; i < ranks.length; i++) { + for (const suit of suits) { + this.deck.push(new Card(suit, ranks[i], values[i])); + } + } + + // 添加大小王 + this.deck.push(new Card('joker', '小王', 16)); + this.deck.push(new Card('joker', '大王', 17)); + } + + // 洗牌算法 + shuffleDeck() { + for (let i = this.deck.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [this.deck[i], this.deck[j]] = [this.deck[j], this.deck[i]]; + } + } + + // 开始游戏 + startGame() { + this.gameStatus = 'calling'; + this.currentPlayer = 0; + this.landlord = -1; + this.lastPlayPlayer = -1; + this.lastPlayCards = []; + this.callLandlordCount = 0; + + // 重置玩家数据 + for (const player of this.players) { + player.cards = []; + player.role = ''; + player.lastPlay = []; + } + + // 洗牌发牌 + this.initializeDeck(); + this.shuffleDeck(); + this.dealCards(); + + // 更新UI + this.updateGameStatus('开始叫地主'); + this.updateCurrentPlayer(); + this.renderAllCards(); + this.elements.startGame.style.display = 'none'; + this.elements.landlordButtons.style.display = 'flex'; + this.elements.playButtons.style.display = 'none'; + this.clearCurrentPlay(); + } + + // 发牌 + dealCards() { + // 发牌给三个玩家 + for (let i = 0; i < 17; i++) { + this.players[0].cards.push(this.deck.pop()); + this.players[1].cards.push(this.deck.pop()); + this.players[2].cards.push(this.deck.pop()); + } + + // 剩余的3张作为地主牌 + this.landlordCards = [...this.deck]; + this.deck = []; + + // 排序玩家的牌 + for (const player of this.players) { + this.sortCards(player.cards); + } + } + + // 排序卡片 + sortCards(cards) { + cards.sort((a, b) => a.value - b.value); + } + + // 叫地主 + callLandlord() { + this.landlord = this.currentPlayer; + this.players[this.currentPlayer].role = '地主'; + this.players[(this.currentPlayer + 1) % 3].role = '农民'; + this.players[(this.currentPlayer + 2) % 3].role = '农民'; + + // 将地主牌加入地主手中 + this.players[this.currentPlayer].cards.push(...this.landlordCards); + this.sortCards(this.players[this.currentPlayer].cards); + + // 开始游戏 + this.gameStatus = 'playing'; + this.updateGameStatus('游戏开始,地主出牌'); + this.updatePlayerRoles(); + this.renderAllCards(); + this.elements.landlordButtons.style.display = 'none'; + this.elements.playButtons.style.display = 'flex'; + + // 如果是电脑地主,自动出牌 + if (this.currentPlayer !== 0) { + setTimeout(() => this.computerPlay(), 1000); + } + } + + // 不叫地主 + noCall() { + this.callLandlordCount++; + this.currentPlayer = (this.currentPlayer + 1) % 3; + this.updateCurrentPlayer(); + + // 如果三个玩家都不叫,重新开始 + if (this.callLandlordCount === 3) { + this.updateGameStatus('无人叫地主,重新开始'); + setTimeout(() => this.startGame(), 1500); + return; + } + + // 如果是电脑玩家,自动选择 + if (this.currentPlayer !== 0) { + setTimeout(() => this.computerCallLandlord(), 1000); + } + } + + // 电脑叫地主 + computerCallLandlord() { + // 简单AI:如果有王或多张大牌,叫地主 + const hasBigCards = this.players[this.currentPlayer].cards.some(card => + card.value >= 16 || + (card.value >= 14 && this.players[this.currentPlayer].cards.filter(c => c.value >= 14).length >= 3) + ); + + if (hasBigCards) { + this.callLandlord(); + } else { + this.noCall(); + } + } + + // 选择卡片 + toggleCardSelection(cardElement) { + if (this.gameStatus !== 'playing' || this.currentPlayer !== 0) return; + + cardElement.classList.toggle('selected'); + const selected = cardElement.classList.contains('selected'); + const suit = cardElement.dataset.suit; + const rank = cardElement.dataset.rank; + const value = parseInt(cardElement.dataset.value); + + // 更新卡片对象的选中状态 + const card = this.players[0].cards.find(c => + c.suit === suit && c.rank === rank && c.value === value + ); + if (card) { + card.selected = selected; + } + } + + // 出牌 + playSelectedCards() { + if (this.gameStatus !== 'playing' || this.currentPlayer !== 0) return; + + // 获取选中的卡片 + const selectedCards = this.players[0].cards.filter(card => card.selected); + if (selectedCards.length === 0) return; + + // 验证出牌是否合法 + if (this.isValidPlay(selectedCards)) { + // 更新游戏状态 + this.players[0].lastPlay = selectedCards; + this.lastPlayPlayer = 0; + this.lastPlayCards = selectedCards; + + // 从手中移除出的牌 + this.players[0].cards = this.players[0].cards.filter(card => !card.selected); + + // 检查是否获胜 + if (this.players[0].cards.length === 0) { + this.endGame(0); + return; + } + + // 更新UI + this.renderPlayerCards(0); + this.updateCardsCount(0); + this.updateCurrentPlay(0, selectedCards); + this.updateSelfLastPlay(selectedCards); + + // 切换到下一个玩家 + this.currentPlayer = 1; + this.updateCurrentPlayer(); + + // 电脑玩家自动出牌 + setTimeout(() => this.computerPlay(), 1000); + } else { + alert('出牌不合法,请重新选择'); + } + } + + // 不出牌 + pass() { + if (this.gameStatus !== 'playing' || this.currentPlayer !== 0) return; + + // 更新游戏状态 + this.players[0].lastPlay = []; + this.updateGameStatus('玩家不出牌'); + + // 切换到下一个玩家 + this.currentPlayer = 1; + this.updateCurrentPlayer(); + + // 电脑玩家自动出牌 + setTimeout(() => this.computerPlay(), 1000); + } + + // 电脑出牌 + computerPlay() { + const player = this.players[this.currentPlayer]; + const playableCards = this.findPlayableCards(player.cards); + + if (playableCards.length > 0) { + // 选择最合适的牌组 + const selectedCards = this.chooseBestCards(playableCards); + + // 更新游戏状态 + player.lastPlay = selectedCards; + this.lastPlayPlayer = this.currentPlayer; + this.lastPlayCards = selectedCards; + + // 从手中移除出的牌 + player.cards = player.cards.filter(card => !selectedCards.includes(card)); + + // 检查是否获胜 + if (player.cards.length === 0) { + this.endGame(this.currentPlayer); + return; + } + + // 更新UI + this.renderPlayerCards(this.currentPlayer); + this.updateCardsCount(this.currentPlayer); + this.updateCurrentPlay(this.currentPlayer, selectedCards); + this.updateComputerLastPlay(this.currentPlayer, selectedCards); + + this.updateGameStatus(`${player.name} 出牌`); + } else { + // 不出牌 + player.lastPlay = []; + this.updateGameStatus(`${player.name} 不出牌`); + } + + // 切换到下一个玩家 + this.currentPlayer = (this.currentPlayer + 1) % 3; + this.updateCurrentPlayer(); + + // 如果下一个是电脑,继续自动出牌 + if (this.currentPlayer !== 0) { + setTimeout(() => this.computerPlay(), 1000); + } + } + + // 查找可出的牌组 + findPlayableCards(cards) { + const playable = []; + + // 如果是第一个出牌,可以出任何牌组 + if (this.lastPlayPlayer === -1) { + // 简单实现:找出所有可能的单牌、对子、顺子等 + // 这里简化处理,只考虑单牌 + for (const card of cards) { + playable.push([card]); + } + } else { + // 必须出比上一次大的同类型牌 + const lastType = this.getCardType(this.lastPlayCards); + const lastMaxValue = Math.max(...this.lastPlayCards.map(c => c.value)); + + if (lastType === 'single') { + // 找比lastMaxValue大的单牌 + const singles = cards.filter(card => card.value > lastMaxValue); + for (const card of singles) { + playable.push([card]); + } + } + } + + return playable; + } + + // 选择最好的牌组 + chooseBestCards(playableCards) { + // 简单AI:选择最小的可出牌组 + if (playableCards.length === 0) return []; + + // 由于只允许单牌,直接选择最小的可出牌 + return playableCards[0]; + } + + // 验证出牌是否合法 + isValidPlay(cards) { + if (cards.length === 0) return false; + + // 简化版:只允许出单牌 + if (cards.length !== 1) { + return false; + } + + // 如果是第一个出牌 + if (this.lastPlayPlayer === -1) { + return true; + } + + // 检查牌型是否相同(都是单牌) + const currentType = this.getCardType(cards); + const lastType = this.getCardType(this.lastPlayCards); + + if (currentType !== 'single' || lastType !== 'single') { + return false; + } + + // 检查大小 + const currentMax = Math.max(...cards.map(c => c.value)); + const lastMax = Math.max(...this.lastPlayCards.map(c => c.value)); + + return currentMax > lastMax; + } + + // 获取牌型 + getCardType(cards) { + if (cards.length === 0) return 'empty'; + if (cards.length === 1) return 'single'; + if (cards.length === 2) { + if (cards[0].value === cards[1].value) return 'pair'; + if (cards[0].value === 16 && cards[1].value === 17) return 'rocket'; + return 'invalid'; + } + // 这里可以扩展更多牌型判断 + return 'invalid'; + } + + // 结束游戏 + endGame(winner) { + this.gameStatus = 'ended'; + const winnerPlayer = this.players[winner]; + const isLandlordWin = winnerPlayer.role === '地主'; + + if (isLandlordWin) { + this.score += 200; + this.updateGameStatus(`地主 ${winnerPlayer.name} 获胜!`); + } else { + this.score -= 100; + this.updateGameStatus(`农民 ${winnerPlayer.name} 获胜!`); + } + + // 更新UI + this.elements.landlordButtons.style.display = 'none'; + this.elements.playButtons.style.display = 'none'; + this.elements.startGame.style.display = 'block'; + this.elements.startGame.textContent = '再来一局'; + this.updateScore(); + } + + // 更新游戏状态 + updateGameStatus(status) { + this.elements.gameStatus.textContent = status; + } + + // 更新当前玩家 + updateCurrentPlayer() { + this.elements.currentPlayer.textContent = `当前玩家:${this.players[this.currentPlayer].name}`; + } + + // 更新玩家角色 + updatePlayerRoles() { + for (let i = 0; i < 3; i++) { + this.elements.playerRoles[i].textContent = this.players[i].role; + } + } + + // 渲染所有卡片 + renderAllCards() { + for (let i = 0; i < 3; i++) { + this.renderPlayerCards(i); + this.updateCardsCount(i); + } + this.renderLandlordCards(); + } + + // 渲染玩家卡片 + renderPlayerCards(playerIndex) { + const container = this.elements.playerCards[playerIndex]; + container.innerHTML = ''; + + const player = this.players[playerIndex]; + + if (playerIndex === 0) { + // 自己的卡片,可以选择 + for (const card of player.cards) { + const cardElement = card.getHTML(card.selected); + cardElement.addEventListener('click', () => this.toggleCardSelection(cardElement)); + container.appendChild(cardElement); + } + } else { + // 电脑玩家的卡片,显示背面 + for (let i = 0; i < player.cards.length; i++) { + const cardElement = Card.getBackHTML(); + container.appendChild(cardElement); + } + } + } + + // 渲染地主牌 + renderLandlordCards() { + this.elements.landlordCardsArea.innerHTML = ''; + for (const card of this.landlordCards) { + const cardElement = card.getHTML(); + this.elements.landlordCardsArea.appendChild(cardElement); + } + } + + // 更新牌数 + updateCardsCount(playerIndex) { + this.elements.playerCardsCount[playerIndex].textContent = this.players[playerIndex].cards.length; + } + + // 更新当前出牌 + updateCurrentPlay(playerIndex, cards) { + this.elements.currentPlayInfo.textContent = `${this.players[playerIndex].name} 出牌:`; + this.elements.currentPlayCards.innerHTML = ''; + + for (const card of cards) { + const cardElement = card.getHTML(); + this.elements.currentPlayCards.appendChild(cardElement); + } + } + + // 清空当前出牌 + clearCurrentPlay() { + this.elements.currentPlayInfo.textContent = '当前出牌:'; + this.elements.currentPlayCards.innerHTML = ''; + } + + // 更新自己的上次出牌 + updateSelfLastPlay(cards) { + const container = this.elements.lastPlay[0]; + container.innerHTML = ''; + + for (const card of cards) { + const cardElement = card.getHTML(); + container.appendChild(cardElement); + } + } + + // 更新电脑玩家的上次出牌 + updateComputerLastPlay(playerIndex, cards) { + const container = this.elements.lastPlay[playerIndex]; + container.innerHTML = ''; + + for (const card of cards) { + const cardElement = card.getHTML(); + container.appendChild(cardElement); + } + } + + // 更新分数 + updateScore() { + this.elements.score.textContent = this.score; + } +} + +// 初始化游戏 +document.addEventListener('DOMContentLoaded', () => { + window.game = new LandlordGame(); +}); \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..c5796b5 --- /dev/null +++ b/style.css @@ -0,0 +1,354 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Arial', sans-serif; + background-color: #1a532a; + color: white; + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; +} + +.game-container { + width: 90vw; + max-width: 1200px; + min-height: 90vh; + background-color: rgba(0, 0, 0, 0.3); + border-radius: 20px; + padding: 20px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); +} + +.game-header { + text-align: center; + margin-bottom: 20px; +} + +.game-header h1 { + font-size: 2.5em; + color: #ffd700; + margin-bottom: 10px; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); +} + +.game-info { + display: flex; + justify-content: center; + gap: 20px; + font-size: 1.2em; +} + +.game-table { + position: relative; + width: 100%; + min-height: 500px; + background-color: rgba(255, 255, 255, 0.1); + border-radius: 15px; + padding: 20px; + display: flex; + flex-direction: column; + gap: 20px; +} + +/* 地主牌区域 */ +.landlord-cards { + text-align: center; + margin-bottom: 20px; +} + +#landlord-indicator { + font-size: 1.2em; + margin-bottom: 10px; + color: #ffd700; +} + +#landlord-cards-area { + display: flex; + justify-content: center; + gap: 5px; +} + +/* 玩家区域 */ +.player { + width: 100%; + text-align: center; +} + +.player-info { + display: flex; + justify-content: center; + align-items: center; + gap: 15px; + margin-bottom: 10px; + font-size: 1.1em; +} + +.player-name { + font-weight: bold; +} + +.cards-count { + background-color: rgba(255, 255, 255, 0.2); + padding: 5px 10px; + border-radius: 10px; +} + +.player-role { + color: #ff6b6b; + font-weight: bold; +} + +.player-cards { + display: flex; + justify-content: center; + gap: 5px; + flex-wrap: wrap; + margin-bottom: 10px; +} + +.last-play { + display: flex; + justify-content: center; + gap: 5px; + margin-top: 10px; + opacity: 0.7; +} + +/* 自己的玩家区域 */ +.player-self { + margin-top: 30px; +} + +.player-self .player-cards { + gap: 2px; +} + +/* 卡片样式 */ +.card { + width: 80px; + height: 120px; + background-color: white; + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 5px; + color: black; + font-weight: bold; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); + cursor: pointer; + transition: all 0.2s ease; + position: relative; + border: 2px solid transparent; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); +} + +.card.selected { + border-color: #ffd700; + background-color: #fff9c4; +} + +.card-back { + background-color: #424242; + background-image: radial-gradient(circle, #666 20%, transparent 20%), + radial-gradient(circle, #666 20%, transparent 20%); + background-size: 10px 10px; + background-position: 0 0, 5px 5px; + color: transparent; +} + +.card .rank-top { + font-size: 1.5em; + align-self: flex-start; +} + +.card .suit-middle { + font-size: 2em; + align-self: center; + margin: 10px 0; +} + +.card .rank-bottom { + font-size: 1.5em; + align-self: flex-end; + transform: rotate(180deg); +} + +/* 花色颜色 */ +.card.spades, .card.clubs { + color: black; +} + +.card.hearts, .card.diamonds { + color: red; +} + +/* 大王小王 */ +.card.joker-big .suit-middle, +.card.joker-small .suit-middle { + color: black; + font-size: 1.5em; +} + +/* 当前出牌区域 */ +.current-play-area { + text-align: center; + margin: 20px 0; +} + +#current-play-info { + font-size: 1.2em; + margin-bottom: 10px; + color: #ffd700; +} + +#current-play-cards { + display: flex; + justify-content: center; + gap: 5px; +} + +/* 游戏控制按钮 */ +.game-controls { + display: flex; + justify-content: center; + align-items: center; + gap: 15px; + margin-top: 20px; + flex-wrap: wrap; +} + +button { + padding: 12px 24px; + font-size: 1.1em; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s ease; + font-weight: bold; +} + +button:hover { + background-color: #45a049; +} + +button:active { + transform: translateY(1px); +} + +button:disabled { + background-color: #cccccc; + cursor: not-allowed; + transform: none; +} + +/* 叫地主按钮区域 */ +.landlord-buttons { + display: flex; + gap: 15px; +} + +#call-landlord { + background-color: #ff9800; +} + +#call-landlord:hover { + background-color: #f57c00; +} + +#no-call { + background-color: #f44336; +} + +#no-call:hover { + background-color: #da190b; +} + +/* 出牌按钮区域 */ +.play-buttons { + display: flex; + gap: 15px; +} + +#play-cards { + background-color: #2196F3; +} + +#play-cards:hover { + background-color: #0b7dda; +} + +#pass { + background-color: #9e9e9e; +} + +#pass:hover { + background-color: #757575; +} + +/* 游戏统计 */ +.game-stats { + margin-left: 30px; + font-size: 1.2em; + color: #ffd700; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .game-container { + width: 98vw; + padding: 10px; + } + + .game-header h1 { + font-size: 2em; + } + + .card { + width: 60px; + height: 90px; + font-size: 0.9em; + } + + .player-info { + font-size: 1em; + gap: 10px; + } + + .game-controls { + gap: 10px; + } + + button { + padding: 10px 20px; + font-size: 1em; + } +} + +@media (max-width: 480px) { + .card { + width: 50px; + height: 75px; + font-size: 0.8em; + } + + .game-info { + flex-direction: column; + gap: 5px; + } + + .game-controls { + flex-direction: column; + } +} \ No newline at end of file