纸牌接龙:Trae 轻松实现经典纸牌挑战

纸牌接龙是一个经典的单人纸牌游戏,玩家需要按照一定的规则将纸牌排成一堆,并完成接龙。通常,游戏规则要求玩家根据纸牌的点数和花色进行排列,从而逐步完成接龙。尽管规则简单,纸牌的自动排序和发放以及操作逻辑的实现却需要一定的复杂性,尤其是在处理牌堆和规则检查时。

过去,制作一个纸牌接龙游戏需要编写发牌、排序和判断的代码,确保游戏的逻辑和UI能够流畅地运行。但现在,通过 Trae IDE,只需要输入简单的指令,Trae 就能够自动帮我完成所有复杂的游戏逻辑和UI设计。接下来,我将分享如何通过 Trae 快速生成一个纸牌接龙游戏,让玩家轻松体验这款经典纸牌游戏。

💡 我的需求其实很简单

我的需求非常明确:制作一个纸牌接龙游戏,功能要求如下:

  • 纸牌发放:游戏开始时,纸牌会自动发放到指定位置。
  • 规则排列:玩家按规则排列纸牌,通常是按照点数从大到小,交替的红黑花色排列。
  • 自动排序:当玩家完成一部分排列时,纸牌会自动移动到正确的顺序。
  • 游戏完成:当所有纸牌正确排列完成时,游戏自动判定完成接龙。
  • 简洁的UI设计:游戏界面直观,操作简单,纸牌发放和排序清晰明了。

虽然规则看起来简单,但涉及到纸牌的发放、排序、移动和判断等操作,手动实现这些功能依然需要不少的时间。

✨ Trae 如何理解需求并生成代码?

我只需要在 Trae 中输入一句话:

"生成接龙游戏,玩家按规则排列纸牌,最终完成接龙。"

Trae 会自动解析我的需求,并生成完整的纸牌接龙游戏代码,包括:

  • 纸牌发放:游戏开始时,纸牌会按照指定规则自动发放到桌面上的不同位置。
  • 纸牌排序:玩家按照接龙规则排列纸牌,纸牌会自动按点数和花色排序。游戏规则确保纸牌的排列顺序正确。
  • 自动化操作:当玩家操作时,纸牌会自动进行排序和移动,确保游戏逻辑流畅运行。
  • 胜利判定:当玩家成功完成接龙后,系统会判定游戏胜利并显示"游戏完成"的提示。
  • 简洁的UI设计:游戏界面设计简洁,纸牌的排列和操作非常直观,玩家可以轻松完成接龙任务。

通过简单的指令,Trae 就能为我自动生成一个完整的纸牌接龙游戏,并处理所有复杂的操作和逻辑。

🧩 游戏操作简便,玩法清晰

Trae 生成的纸牌接龙游戏操作非常直观,玩家只需点击纸牌并拖动到正确的位置,游戏会根据规则自动排列纸牌。每次移动纸牌,游戏界面都会即时更新,确保玩家能够清晰看到纸牌的排序进展。

如果玩家完成了某部分接龙,纸牌会自动整理并移动到新的位置,玩家不需要手动去整理纸牌,操作十分流畅。

🛠 游戏拓展,功能轻松加

虽然 Trae 生成的纸牌接龙游戏已经非常完备,但它也支持轻松添加更多功能。例如:

  • 多种接龙模式:可以增加不同的接龙玩法,如四堆接龙、空位接龙等,给玩家提供更多的挑战。
  • 计时器功能:为游戏加入计时器,记录玩家完成接龙的时间,增加游戏的竞技性。
  • 得分系统:可以根据玩家完成接龙的速度和完成度来给出分数。
  • 音效和动画:为纸牌的发放、排序和移动添加动画和音效,使游戏更具互动性。

这些新功能都可以通过简单描述,Trae 会自动生成并将它们集成到现有的游戏中。

这就是纸牌接龙游戏开发的新体验

通过这次纸牌接龙游戏的开发,我深刻感受到了 Trae 带来的便利。从纸牌的发放,到玩家的操作,再到排序和判定,Trae 都能够自动帮我完成。这不仅节省了大量开发时间,也提高了开发效率,让我可以更专注于游戏设计和功能扩展。

对于独立开发者或小团队来说,Trae 是一个非常高效的工具,它帮助你将繁琐的逻辑和操作自动化,让你专注于创意和优化。

结语

如果你也想制作一个经典的纸牌接龙游戏,试试 Trae IDE,输入类似的需求:

"生成接龙游戏,玩家按规则排列纸牌,最终完成接龙。"

几秒钟内,Trae 就会生成完整的纸牌接龙游戏代码,带有纸牌发放、排序、玩家操作和胜利判定等功能。你可以直接将它嵌入到你的项目中,甚至根据需求继续扩展和优化。

快来体验一下 Trae,让你的纸牌接龙游戏开发变得更加轻松、有趣!

html 复制代码
<!DOCTYPE html>

<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>纸牌接龙游戏</title>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {

            font-family: Arial, sans-serif;
            background-color: #076324;
            color: white;
            padding: 20px;
        }
        .game-container {
            max-width: 1000px;
            margin: 0 auto;
        }
        .header {
            display: flex;
            justify-content: space-between;
            margin-bottom: 20px;
            align-items: center;
        }
        .title {
            font-size: 24px;
            font-weight: bold;
        }
        .controls button {
            padding: 8px 16px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-left: 10px;
        }
        .controls button:hover {
            background-color: #45a049;
        }
        .game-area {
            display: grid;
            grid-template-rows: auto auto;
            gap: 20px;
        }
        .top-row {
            display: grid;
            grid-template-columns: repeat(8, 1fr);
            gap: 10px;
        }
        .bottom-row {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 10px;
        }
        .card-slot {
            background-color: rgba(0, 0, 0, 0.2);
            border: 2px dashed rgba(255, 255, 255, 0.3);
            border-radius: 8px;
            height: 120px;
            position: relative;
        }

        .foundation {
            background-color: rgba(0, 100, 0, 0.5);
        }

        .tableau {

            min-height: 300px;
        }
        .card {
            width: 80px;
            height: 120px;
            background-color: white;
            border-radius: 8px;
            position: absolute;

            cursor: pointer;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
            transition: all 0.2s ease;
            user-select: none;
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }
        .card.red {
            color: red;
        }
        .card.black {
            color: black;
        }
        .card-content {
            display: flex;
            flex-direction: column;
            height: 100%;
            padding: 5px;
        }
        .card-value {
            font-size: 16px;
            font-weight: bold;
        }

        .card-suit {
            font-size: 16px;
        }
        .card-center {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-grow: 1;
            font-size: 30px;
        }
        .card-back {
            background-color: #2980b9;

            background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 10px, transparent 10px, transparent 20px);
        }
        .card.dragging {
            opacity: 0.8;
            z-index: 1000;
        }
        .message {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
            display: none;
            z-index: 2000;
        }
        .message h2 {
            margin-bottom: 15px;
        }
        .message button {
            padding: 8px 16px;
            background-color: #4CAF50;
            color: white;
            border: none;

            border-radius: 4px;
            cursor: pointer;
            margin-top: 10px;
        }
        .timer {

            font-size: 18px;
            margin-right: 20px;
        }
        .moves {
            font-size: 18px;
        }
    </style>
</head>
<body>
    <div class="game-container">
        <div class="header">
            <div class="title">纸牌接龙</div>
            <div class="stats">
                <span class="timer">时间: 00:00</span>
                <span class="moves">移动次数: 0</span>
            </div>
            <div class="controls">
                <button id="new-game">新游戏</button>
                <button id="undo">撤销</button>
                <button id="hint">提示</button>
            </div>
        </div>
        <div class="game-area">
            <div class="top-row">
                <div class="card-slot stock" id="stock"></div>

                <div class="card-slot waste" id="waste"></div>
                <div class="card-slot placeholder"></div>
                <div class="card-slot foundation" id="foundation-0"></div>
                <div class="card-slot foundation" id="foundation-1"></div>
                <div class="card-slot foundation" id="foundation-2"></div>
                <div class="card-slot foundation" id="foundation-3"></div>
            </div>
            <div class="bottom-row">
                <div class="card-slot tableau" id="tableau-0"></div>
                <div class="card-slot tableau" id="tableau-1"></div>
                <div class="card-slot tableau" id="tableau-2"></div>
                <div class="card-slot tableau" id="tableau-3"></div>
                <div class="card-slot tableau" id="tableau-4"></div>
                <div class="card-slot tableau" id="tableau-5"></div>
                <div class="card-slot tableau" id="tableau-6"></div>
            </div>
        </div>

    </div>


    <div class="message" id="win-message">
        <h2>恭喜你赢了!</h2>
        <p>你用了 <span id="final-time"></span> 和 <span id="final-moves"></span> 次移动完成了游戏</p>
        <button id="play-again">再玩一次</button>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 游戏状态变量
            let deck = [];
            let stock = [];
            let waste = [];
            let foundations = [[], [], [], []];
            let tableaus = [[], [], [], [], [], [], []];

            let selectedCard = null;
            let selectedStack = [];
            let selectedSource = null;
            let moves = 0;
            let seconds = 0;
            let timerInterval = null;
            let moveHistory = [];
            let isDragging = false;
            let draggedCard = null;
            let draggedCards = [];
            let startX, startY;
            let offsetX, offsetY;

            // DOM 元素
            const stockElement = document.getElementById('stock');

            const wasteElement = document.getElementById('waste');
            const foundationElements = [
                document.getElementById('foundation-0'),
                document.getElementById('foundation-1'),
                document.getElementById('foundation-2'),
                document.getElementById('foundation-3')
            ];
            const tableauElements = [
                document.getElementById('tableau-0'),
                document.getElementById('tableau-1'),
                document.getElementById('tableau-2'),
                document.getElementById('tableau-3'),

                document.getElementById('tableau-4'),
                document.getElementById('tableau-5'),
                document.getElementById('tableau-6')
            ];
            const timerElement = document.querySelector('.timer');
            const movesElement = document.querySelector('.moves');
            const newGameButton = document.getElementById('new-game');
            const undoButton = document.getElementById('undo');
            const hintButton = document.getElementById('hint');
            const winMessage = document.getElementById('win-message');
            const finalTimeElement = document.getElementById('final-time');
            const finalMovesElement = document.getElementById('final-moves');
            const playAgainButton = document.getElementById('play-again');

            // 初始化游戏
            initGame();


            // 事件监听器
            newGameButton.addEventListener('click', initGame);
            undoButton.addEventListener('click', undoMove);
            hintButton.addEventListener('click', showHint);
            playAgainButton.addEventListener('click', () => {
                winMessage.style.display = 'none';
                initGame();
            });
            stockElement.addEventListener('click', dealFromStock);

            // 初始化游戏函数
            function initGame() {
                // 重置游戏状态
                deck = createDeck();
                stock = [...deck];
                waste = [];
                foundations = [[], [], [], []];
                tableaus = [[], [], [], [], [], [], []];
                selectedCard = null;
                selectedStack = [];
                selectedSource = null;
                moves = 0;
                seconds = 0;
                moveHistory = [];
                updateMovesDisplay();


                // 清除计时器并重置
                if (timerInterval) {

                    clearInterval(timerInterval);
                }
                timerInterval = setInterval(updateTimer, 1000);
                updateTimerDisplay();

                // 洗牌
                shuffleDeck(stock);

                // 发牌到tableau
                dealInitialCards();


                // 渲染游戏
                renderGame();

                // 添加事件监听器
                addEventListeners();
            }

            // 创建一副牌
            function createDeck() {
                const suits = ['♥', '♦', '♠', '♣'];
                const values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
                const deck = [];

                for (let suit of suits) {
                    const color = (suit === '♥' || suit === '♦') ? 'red' : 'black';
                    for (let i = 0; i < values.length; i++) {
                        deck.push({
                            suit,

                            value: values[i],

                            color,
                            rank: i + 1,
                            faceUp: false,

                            id: `${values[i]}-${suit}`
                        });
                    }
                }

                return deck;
            }

            // 洗牌函数
            function shuffleDeck(deck) {

                for (let i = deck.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [deck[i], deck[j]] = [deck[j], deck[i]];

                }
            }

            // 发初始牌
            function dealInitialCards() {
                for (let i = 0; i < 7; i++) {

                    for (let j = i; j < 7; j++) {
                        const card = stock.pop();
                        if (i === j) {

                            card.faceUp = true;
                        }
                        tableaus[j].push(card);
                    }
                }

            }

            // 从stock发牌
            function dealFromStock() {
                if (stock.length === 0) {
                    // 如果stock为空,将waste中的牌放回stock
                    if (waste.length > 0) {
                        stock = waste.reverse();
                        waste = [];
                        stock.forEach(card => card.faceUp = false);
                        renderGame();
                    }
                    return;
                }


                // 记录移动历史
                recordMove({
                    type: 'dealFromStock',

                    stockLength: stock.length,
                    wasteLength: waste.length
                });

                // 从stock顶部取一张牌放到waste
                const card = stock.pop();
                card.faceUp = true;
                waste.push(card);
                moves++;

                updateMovesDisplay();
                renderGame();
            }


            // 渲染游戏
            function renderGame() {
                // 清空所有区域
                stockElement.innerHTML = '';
                wasteElement.innerHTML = '';
                foundationElements.forEach(el => el.innerHTML = '');
                tableauElements.forEach(el => el.innerHTML = '');

                // 渲染stock
                if (stock.length > 0) {
                    const cardElement = createCardElement({ faceUp: false });
                    stockElement.appendChild(cardElement);
                }

                // 渲染waste
                if (waste.length > 0) {
                    const topCard = waste[waste.length - 1];
                    const cardElement = createCardElement(topCard);
                    cardElement.dataset.source = 'waste';
                    cardElement.dataset.index = waste.length - 1;
                    wasteElement.appendChild(cardElement);
                }

                // 渲染foundations
                foundations.forEach((foundation, i) => {
                    if (foundation.length > 0) {
                        const topCard = foundation[foundation.length - 1];
                        const cardElement = createCardElement(topCard);
                        cardElement.dataset.source = `foundation-${i}`;
                        cardElement.dataset.index = foundation.length - 1;
                        foundationElements[i].appendChild(cardElement);
                    }
                });

                // 渲染tableaus
                tableaus.forEach((tableau, i) => {
                    tableau.forEach((card, j) => {
                        const cardElement = createCardElement(card);
                        cardElement.style.top = `${j * 25}px`;

                        cardElement.dataset.source = `tableau-${i}`;
                        cardElement.dataset.index = j;
                        tableauElements[i].appendChild(cardElement);
                    });
                });

                // 检查是否获胜
                checkWinCondition();
            }

            // 创建卡牌元素

            function createCardElement(card) {
                const cardElement = document.createElement('div');
                cardElement.className = 'card';
                
                if (!card.faceUp) {
                    cardElement.classList.add('card-back');
                    return cardElement;
                }

                cardElement.classList.add(card.color);
                cardElement.dataset.id = card.id;


                const cardContent = document.createElement('div');
                cardContent.className = 'card-content';

                const topValue = document.createElement('div');
                topValue.className = 'card-value';

                topValue.textContent = card.value;

                const topSuit = document.createElement('div');
                topSuit.className = 'card-suit';
                topSuit.textContent = card.suit;

                const center = document.createElement('div');

                center.className = 'card-center';
                center.textContent = card.suit;

                const bottomValue = document.createElement('div');
                bottomValue.className = 'card-value';
                bottomValue.style.transform = 'rotate(180deg)';
                bottomValue.textContent = card.value;

                const bottomSuit = document.createElement('div');
                bottomSuit.className = 'card-suit';
                bottomSuit.style.transform = 'rotate(180deg)';
                bottomSuit.textContent = card.suit;

                cardContent.appendChild(topValue);

                cardContent.appendChild(topSuit);
                cardContent.appendChild(center);
                cardContent.appendChild(bottomSuit);
                cardContent.appendChild(bottomValue);

                cardElement.appendChild(cardContent);
                return cardElement;

            }


            // 添加事件监听器
            function addEventListeners() {
                // 为waste中的牌添加点击事件
                document.querySelectorAll('#waste .card').forEach(card => {
                    card.addEventListener('click', handleCardClick);
                    card.addEventListener('mousedown', handleCardMouseDown);
                });

                // 为foundation中的牌添加点击事件

                document.querySelectorAll('.foundation .card').forEach(card => {
                    card.addEventListener('click', handleCardClick);
                    card.addEventListener('mousedown', handleCardMouseDown);
                });


                // 为tableau中的牌添加点击事件
                document.querySelectorAll('.tableau .card').forEach(card => {
                    card.addEventListener('click', handleCardClick);
                    card.addEventListener('mousedown', handleCardMouseDown);
                });

                // 为空的foundation添加点击事件
                document.querySelectorAll('.foundation:empty').forEach((foundation, i) => {
                    foundation.addEventListener('click', () => handleEmptyFoundationClick(i));
                });

                // 为空的tableau添加点击事件
                document.querySelectorAll('.tableau:empty').forEach((tableau, i) => {
                    tableau.addEventListener('click', () => handleEmptyTableauClick(i));
                });

                // 添加全局鼠标事件
                document.addEventListener('mousemove', handleMouseMove);
                document.addEventListener('mouseup', handleMouseUp);
            }

            // 处理卡牌点击
            function handleCardClick(e) {
                const cardElement = e.currentTarget;
                const source = cardElement.dataset.source;
                const index = parseInt(cardElement.dataset.index);

                // 如果已经选中了卡牌,尝试移动
                if (selectedCard) {
                    const targetCard = getCardFromElement(cardElement);
                    const targetSource = source;
                    const targetIndex = index;


                    // 尝试移动卡牌
                    if (tryMoveCard(selectedCard, selectedSource, targetCard, targetSource)) {
                        // 移动成功,重置选中状态
                        selectedCard = null;
                        selectedStack = [];
                        selectedSource = null;
                        document.querySelectorAll('.card.selected').forEach(card => {
                            card.classList.remove('selected');
                        });

                        renderGame();
                    } else {
                        // 移动失败,选中新卡牌
                        selectCard(cardElement, source, index);
                    }
                } else {
                    // 选中卡牌
                    selectCard(cardElement, source, index);
                }
            }

            // 选中卡牌

            function selectCard(cardElement, source, index) {
                // 清除之前的选中状态
                document.querySelectorAll('.card.selected').forEach(card => {
                    card.classList.remove('selected');
                });

                // 设置新的选中状态
                selectedCard = getCardFromElement(cardElement);
                selectedSource = source;

                // 如果是tableau中的牌,可能需要选中一堆牌
                if (source.startsWith('tableau-')) {
                    const tableauIndex = parseInt(source.split('-')[1]);
                    const tableau = tableaus[tableauIndex];
                    
                    // 只能选择正面朝上的牌
                    if (selectedCard.faceUp) {
                        // 选中从index到末尾的所有牌
                        selectedStack = tableau.slice(index);
                        
                        // 高亮显示选中的牌
                        const tableauElement = document.getElementById(`tableau-${tableauIndex}`);
                        const cards = tableauElement.querySelectorAll('.card');
                        for (let i = index; i < cards.length; i++) {
                            cards[i].classList.add('selected');
                        }
                    }
                } else {
                    // 其他区域只能选中一张牌
                    selectedStack = [selectedCard];
                    cardElement.classList.add('selected');
                }
            }


            // 从元素获取卡牌对象
            function getCardFromElement(cardElement) {
                const source = cardElement.dataset.source;
                const index = parseInt(cardElement.dataset.index);
                
                if (source === 'waste') {
                    return waste[index];
                } else if (source.startsWith('foundation-')) {
                    const foundationIndex = parseInt(source.split('-')[1]);
                    return foundations[foundationIndex][index];

                } else if (source.startsWith('tableau-')) {
                    const tableauIndex = parseInt(source.split('-')[1]);
                    return tableaus[tableauIndex][index];
                }
                

                return null;

            }

            // 尝试移动卡牌

            function tryMoveCard(sourceCard, sourceLocation, targetCard, targetLocation) {
                // 如果源和目标相同,不移动
                if (sourceLocation === targetLocation) {
                    return false;
                }

                // 移动到foundation
                if (targetLocation && targetLocation.startsWith('foundation-')) {
                    const foundationIndex = parseInt(targetLocation.split('-')[1]);
                    
                    // 只能移动单张牌到foundation
                    if (selectedStack.length !== 1) {
                        return false;
                    }

                    
                    // 检查移动规则
                    if (canMoveToFoundation(sourceCard, foundations[foundationIndex])) {
                        // 记录移动历史
                        recordMove({
                            type: 'moveToFoundation',
                            sourceCard,
                            sourceLocation,
                            foundationIndex
                        });
                        
                        // 执行移动
                        moveCardToFoundation(sourceCard, sourceLocation, foundationIndex);
                        return true;
                    }
                }
                // 移动到tableau
                else if (targetLocation && targetLocation.startsWith('tableau-')) {
                    const tableauIndex = parseInt(targetLocation.split('-')[1]);
                    
                    // 检查移动规则
                    if (canMoveToTableau(selectedStack[0], tableaus[tableauIndex])) {
                        // 记录移动历史
                        recordMove({

                            type: 'moveToTableau',
                            sourceStack: [...selectedStack],

                            sourceLocation,
                            tableauIndex
                        });
                        
                        // 执行移动
                        moveCardToTableau(selectedStack, sourceLocation, tableauIndex);
                        return true;
                    }
                }
                
                return false;
            }

            // 处理空foundation点击
            function handleEmptyFoundationClick(foundationIndex) {
                if (selectedCard && selectedStack.length === 1) {
                    // 检查是否可以移动到空foundation
                    if (canMoveToEmptyFoundation(selectedCard)) {
                        // 记录移动历史
                        recordMove({
                            type: 'moveToFoundation',
                            sourceCard: selectedCard,
                            sourceLocation: selectedSource,
                            foundationIndex
                        });
                        
                        // 执行移动
                        moveCardToFoundation(selectedCard, selectedSource, foundationIndex);
                        
                        // 重置选中状态
                        selectedCard = null;
                        selectedStack = [];
                        selectedSource = null;
                        document.querySelectorAll('.card.selected').forEach(card => {
                            card.classList.remove('selected');
                        });
                        
                        renderGame();
                    }
                }
            }

            // 处理空tableau点击
            function handleEmptyTableauClick(tableauIndex) {
                if (selectedCard && selectedStack.length > 0) {
                    // 检查是否可以移动到空tableau
                    if (canMoveToEmptyTableau(selectedStack[0])) {
                        // 记录移动历史
                        recordMove({
                            type: 'moveToTableau',
                            sourceStack: [...selectedStack],
                            sourceLocation: selectedSource,
                            tableauIndex
                        });
                        
                        // 执行移动
                        moveCardToTableau(selectedStack, selectedSource, tableauIndex);
                        
                        // 重置选中状态
                        selectedCard = null;
                        selectedStack = [];
                        selectedSource = null;
                        document.querySelectorAll('.card.selected').forEach(card => {
                            card.classList.remove('selected');

                        });
                        
                        renderGame();
                    }
                }

            }

            // 检查是否可以移动到foundation
            function canMoveToFoundation(card, foundation) {
                // 如果foundation为空,只能放A
                if (foundation.length === 0) {
                    return card.value === 'A';
                }
                
                // 否则,检查花色和顺序
                const topCard = foundation[foundation.length - 1];
                return card.suit === topCard.suit && card.rank === topCard.rank + 1;
            }


            // 检查是否可以移动到空foundation
            function canMoveToEmptyFoundation(card) {
                return card.value === 'A';
            }

            // 检查是否可以移动到tableau
            function canMoveToTableau(card, tableau) {
                // 如果tableau为空,只能放K
                if (tableau.length === 0) {
                    return card.value === 'K';
                }
                

                // 否则,检查颜色和顺序
                const topCard = tableau[tableau.length - 1];
                return topCard.faceUp && card.color !== topCard.color && card.rank === topCard.rank - 1;
            }

            // 检查是否可以移动到空tableau
            function canMoveToEmptyTableau(card) {
                return card.value === 'K';
            }

            // 移动卡牌到foundation
            function moveCardToFoundation(card, sourceLocation, foundationIndex) {
                // 从源位置移除卡牌
                if (sourceLocation === 'waste') {
                    waste.pop();
                } else if (sourceLocation.startsWith('tableau-')) {
                    const tableauIndex = parseInt(sourceLocation.split('-')[1]);
                    tableaus[tableauIndex].pop();
                    
                    // 如果tableau中还有牌,翻转顶部的牌
                    if (tableaus[tableauIndex].length > 0 && !tableaus[tableauIndex][tableaus[tableauIndex].length - 1].faceUp) {
                        tableaus[tableauIndex][tableaus[tableauIndex].length - 1].faceUp = true;
                    }

                } else if (sourceLocation.startsWith('foundation-')) {
                    const sourceFoundationIndex = parseInt(sourceLocation.split('-')[1]);
                    foundations[sourceFoundationIndex].pop();
                }
                
                // 添加到foundation
                foundations[foundationIndex].push(card);
                
                // 更新移动次数
                moves++;
                updateMovesDisplay();
            }

            // 移动卡牌到tableau
            function moveCardToTableau(cardStack, sourceLocation, tableauIndex) {
                // 从源位置移除卡牌
                if (sourceLocation === 'waste') {
                    waste.pop();
                } else if (sourceLocation.startsWith('tableau-')) {
                    const sourceTableauIndex = parseInt(sourceLocation.split('-')[1]);
                    const startIndex = tableaus[sourceTableauIndex].length - cardStack.length;
                    tableaus[sourceTableauIndex].splice(startIndex, cardStack.length);
                    
                    // 如果tableau中还有牌,翻转顶部的牌
                    if (tableaus[sourceTableauIndex].length > 0 && !tableaus[sourceTableauIndex][tableaus[sourceTableauIndex].length - 1].faceUp) {
                        tableaus[sourceTableauIndex][tableaus[sourceTableauIndex].length - 1].faceUp = true;
                    }

                } else if (sourceLocation.startsWith('foundation-')) {
                    const foundationIndex = parseInt(sourceLocation.split('-')[1]);
                    foundations[foundationIndex].pop();
                }
                
                // 添加到tableau
                tableaus[tableauIndex].push(...cardStack);
                
                // 更新移动次数
                moves++;
                updateMovesDisplay();

            }

            // 记录移动历史
            function recordMove(move) {
                moveHistory.push({
                    ...move,
                    stock: [...stock],
                    waste: [...waste],
                    foundations: foundations.map(f => [...f]),
                    tableaus: tableaus.map(t => t.map(card => ({...card}))),
                    moves
                });

            }

            // 撤销移动
            function undoMove() {

                if (moveHistory.length === 0) {
                    return;
                }
                
                const lastMove = moveHistory.pop();
                stock = [...lastMove.stock];
                waste = [...lastMove.waste];
                foundations = lastMove.foundations.map(f => [...f]);
                tableaus = lastMove.tableaus.map(t => t.map(card => ({...card})));
                moves = lastMove.moves;
                

                updateMovesDisplay();
                renderGame();
            }

            // 显示提示
            function showHint() {
                // 实现提示逻辑
                alert('提示功能正在开发中...');
            }

            // 更新移动次数显示

            function updateMovesDisplay() {
                movesElement.textContent = `移动次数: ${moves}`;
            }

            // 更新计时器
            function updateTimer() {
                seconds++;
                updateTimerDisplay();
            }

            // 更新计时器显示

            function updateTimerDisplay() {
                const minutes = Math.floor(seconds / 60);
                const remainingSeconds = seconds % 60;
                timerElement.textContent = `时间: ${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
            }


            // 检查胜利条件
            function checkWinCondition() {
                // 检查所有foundation是否都有13张牌
                const isWin = foundations.every(foundation => foundation.length === 13);
                
                if (isWin) {

                    // 停止计时器
                    clearInterval(timerInterval);
                    

                    // 显示胜利消息
                    finalTimeElement.textContent = timerElement.textContent.replace('时间: ', '');
                    finalMovesElement.textContent = `${moves}`;
                    winMessage.style.display = 'block';
                }
            }

            // 拖拽相关函数
            function handleCardMouseDown(e) {
                if (e.button !== 0) return; // 只处理左键点击
                
                const cardElement = e.currentTarget;
                const source = cardElement.dataset.source;
                const index = parseInt(cardElement.dataset.index);

                
                // 只能拖拽正面朝上的牌
                const card = getCardFromElement(cardElement);
                if (!card.faceUp) return;
                
                isDragging = true;
                
                // 设置拖拽的卡牌
                if (source.startsWith('tableau-')) {
                    const tableauIndex = parseInt(source.split('-')[1]);
                    const tableau = tableaus[tableauIndex];
                    draggedCards = tableau.slice(index);
                    draggedCard = card;
                    selectedSource = source;
                } else {
                    draggedCards = [card];
                    draggedCard = card;
                    selectedSource = source;
                }
                
                // 记录鼠标位置
                startX = e.clientX;
                startY = e.clientY;
                
                // 计算偏移量
                const rect = cardElement.getBoundingClientRect();
                offsetX = e.clientX - rect.left;

                offsetY = e.clientY - rect.top;
                
                // 添加拖拽样式
                cardElement.classList.add('dragging');
                

                e.preventDefault();
            }


            function handleMouseMove(e) {

                if (!isDragging || !draggedCard) return;
                
                const cardElements = document.querySelectorAll('.dragging');
                cardElements.forEach(card => {
                    card.style.position = 'fixed';
                    card.style.left = `${e.clientX - offsetX}px`;
                    card.style.top = `${e.clientY - offsetY}px`;
                    card.style.zIndex = '1000';
                });

            }

            function handleMouseUp(e) {
                if (!isDragging) return;
                
                isDragging = false;
                
                // 移除拖拽样式
                document.querySelectorAll('.dragging').forEach(card => {
                    card.classList.remove('dragging');

                    card.style.position = '';
                    card.style.left = '';

                    card.style.top = '';
                    card.style.zIndex = '';
                });
                
                // 检查是否放在有效位置
                const targetElement = document.elementFromPoint(e.clientX, e.clientY);
                if (targetElement) {
                    let dropTarget = targetElement;

                    

                    // 查找最近的卡牌或槽位
                    while (dropTarget && !dropTarget.classList.contains('card') && !dropTarget.classList.contains('card-slot')) {
                        dropTarget = dropTarget.parentElement;
                    }
                    
                    if (dropTarget) {
                        // 如果是卡牌
                        if (dropTarget.classList.contains('card')) {
                            const targetSource = dropTarget.dataset.source;
                            const targetIndex = parseInt(dropTarget.dataset.index);

                            const targetCard = getCardFromElement(dropTarget);
                            
                            // 尝试移动卡牌
                            tryMoveCard(draggedCard, selectedSource, targetCard, targetSource);
                        }
                        // 如果是空槽位
                        else if (dropTarget.classList.contains('card-slot')) {
                            if (dropTarget.classList.contains('foundation')) {
                                const foundationIndex = parseInt(dropTarget.id.split('-')[1]);
                                if (draggedCards.length === 1 && canMoveToEmptyFoundation(draggedCards[0])) {
                                    // 记录移动历史
                                    recordMove({
                                        type: 'moveToFoundation',
                                        sourceCard: draggedCards[0],
                                        sourceLocation: selectedSource,
                                        foundationIndex
                                    });
                                    
                                    // 执行移动
                                    moveCardToFoundation(draggedCards[0], selectedSource, foundationIndex);
                                }
                            }
                            else if (dropTarget.classList.contains('tableau')) {
                                const tableauIndex = parseInt(dropTarget.id.split('-')[1]);
                                if (canMoveToEmptyTableau(draggedCards[0])) {
                                    // 记录移动历史
                                    recordMove({
                                        type: 'moveToTableau',
                                        sourceStack: [...draggedCards],
                                        sourceLocation: selectedSource,
                                        tableauIndex
                                    });
                                    
                                    // 执行移动
                                    moveCardToTableau(draggedCards, selectedSource, tableauIndex);
                                }
                            }
                        }
                    }
                }
                
                // 重置拖拽状态
                draggedCard = null;
                draggedCards = [];
                selectedSource = null;
                
                // 重新渲染游戏
                renderGame();
            }
        });
    </script>
</body>
</html>
相关推荐
MobotStone12 分钟前
你以为AI在思考?其实90%在搬砖!
ai编程
前端的日常2 小时前
不会写Mcp server,那就让Trae写吧
trae
Goboy2 小时前
消消乐游戏:Trae 轻松实现色彩缤纷的消除乐趣
ai编程·trae
liang_jy4 小时前
数组(Array)
数据结构·面试·trae
这人是玩数学的4 小时前
在 Cursor 中规范化生成 UI 稿实践
前端·ai编程·cursor
coder_pig4 小时前
👦抠腚男孩的AI学习之旅 | 4、如何借助AI,高效学习,实现快速"跨域"
aigc·ai编程·cursor
CF14年老兵5 小时前
「Vue 3 + View Transition 实现炫酷圆形缩放换肤动画」
前端·css·trae
bug菌5 小时前
还在为Java集成AI应用而头疼?Trae让你3分钟从小白变大神!
aigc·ai编程·trae
bug菌5 小时前
还在为Java Web后端开发而码字到深夜?Trae让你秒变全栈大神!
aigc·ai编程·trae