commit 079c863152563bb66e8e19737a6c43ff9e9b23b0
Author: 张扬 <2125069575@qq.com>
Date: Fri Jan 9 09:35:42 2026 +0800
Update English learning app with DeepSeek API integration and new dialogue scenes
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 @@
+
+
+
+
+
+ 斗地主游戏
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 积分:
+ 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