小游戏日记(2048游戏最终版)

1.游戏说明

使用方向键移动方块,相同数字的方块会合并。目标是创造出2048方块!

2.游戏界面

在这里插入图片描述

3.游戏代码

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048 - 终极版AI算法</title>
    <style>
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            margin: 0;
            padding: 20px;
            height: 100vh;
            color: white;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            box-sizing: border-box;
        }

        /* 真实视频背景 */
        .video-background {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -2;
            overflow: hidden;
        }

        .video-background video {
            position: absolute;
            top: 50%;
            left: 50%;
            min-width: 100%;
            min-height: 100%;
            width: auto;
            height: auto;
            transform: translateX(-50%) translateY(-50%);
            object-fit: cover;
            /* 优化视频质量 */
            filter: contrast(1.1) brightness(0.9) saturate(1.2);
        }

        /* 备用背景 */
        .fallback-background {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -3;
            background: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #f5576c);
            background-size: 400% 400%;
            animation: fallbackAnimation 15s ease infinite;
        }

        @keyframes fallbackAnimation {
            0% {
                background-position: 0% 50%;
                filter: hue-rotate(0deg) brightness(1);
            }

            25% {
                background-position: 100% 50%;
                filter: hue-rotate(90deg) brightness(1.2);
            }

            50% {
                background-position: 100% 100%;
                filter: hue-rotate(180deg) brightness(0.8);
            }

            75% {
                background-position: 0% 100%;
                filter: hue-rotate(270deg) brightness(1.1);
            }

            100% {
                background-position: 0% 50%;
                filter: hue-rotate(360deg) brightness(1);
            }
        }

        /* 视频遮罩层 */
        .video-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -1;
            background: rgba(0, 0, 0, 0.4);
            pointer-events: none;
        }

        /* 游戏头部栏:得分、标题和控制按钮 */
        .game-header-bar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            width: 100%;
            gap: 20px;
            margin-bottom: 15px;
        }

        .game-info {
            display: flex;
            gap: 20px;
            font-size: 18px;
            font-weight: bold;
        }

        .game-title {
            text-align: center;
            margin-bottom: 15px;
            position: relative;
            padding: 15px 0;
            perspective: 1000px;
        }

        .game-title h1 {
            font-size: 4em;
            font-weight: 900;
            font-family: 'Impact', 'Arial Black', sans-serif;
            margin: 0;
            position: relative;
            letter-spacing: 4px;
            text-transform: uppercase;
            transform-style: preserve-3d;
            animation: titleFloat 4s ease-in-out infinite;
            background: linear-gradient(45deg,
                    #ff0080, #ff8c00, #ffd700, #00ff80, #0080ff, #8000ff, #ff0080);
            background-size: 400% 400%;
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            animation: neonFlow 3s linear infinite, titleFloat 4s ease-in-out infinite;
            filter: drop-shadow(0 0 10px rgba(255, 0, 128, 0.8)) drop-shadow(0 0 20px rgba(255, 140, 0, 0.6)) drop-shadow(0 0 30px rgba(255, 215, 0, 0.4));
        }

        .game-title h1::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg,
                    rgba(255, 215, 0, 0.3) 0%,
                    rgba(255, 237, 78, 0.2) 50%,
                    rgba(255, 215, 0, 0.3) 100%);
            border-radius: 15px;
            filter: blur(20px);
            z-index: -1;
            animation: titleGlow 2s ease-in-out infinite alternate;
        }

        .game-title h1::after {
            content: '2048 - 终极版';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            background: linear-gradient(135deg,
                    rgba(255, 215, 0, 0.1) 0%,
                    rgba(255, 237, 78, 0.05) 50%,
                    rgba(255, 215, 0, 0.1) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            z-index: -1;
            transform: translate(2px, 2px);
            filter: blur(1px);
        }

        /* 标题动画效果 */
        @keyframes titleShine {
            0% {
                background-position: 0% 50%;
            }

            50% {
                background-position: 100% 50%;
            }

            100% {
                background-position: 0% 50%;
            }
        }

        @keyframes titleGlow {
            0% {
                opacity: 0.3;
                transform: scale(0.95);
            }

            100% {
                opacity: 0.6;
                transform: scale(1.05);
            }
        }

        /* 标题装饰元素 */
        .game-title::before {
            content: '✨';
            position: absolute;
            left: 20%;
            top: 50%;
            transform: translateY(-50%);
            font-size: 1.5em;
            animation: sparkle 2s ease-in-out infinite;
            opacity: 0.8;
        }

        .game-title::after {
            content: '✨';
            position: absolute;
            right: 20%;
            top: 50%;
            transform: translateY(-50%);
            font-size: 1.5em;
            animation: sparkle 2s ease-in-out infinite 1s;
            opacity: 0.8;
        }

        @keyframes sparkle {

            0%,
            100% {
                opacity: 0.4;
                transform: translateY(-50%) scale(1);
            }

            50% {
                opacity: 1;
                transform: translateY(-50%) scale(1.2);
            }
        }

        /* 新的炫酷动画效果 */
        @keyframes neonFlow {
            0% {
                background-position: 0% 50%;
            }

            50% {
                background-position: 100% 50%;
            }

            100% {
                background-position: 0% 50%;
            }
        }

        @keyframes titleFloat {

            0%,
            100% {
                transform: translateY(0px) rotateX(0deg);
            }

            25% {
                transform: translateY(-8px) rotateX(3deg);
            }

            50% {
                transform: translateY(0px) rotateX(0deg);
            }

            75% {
                transform: translateY(8px) rotateX(-3deg);
            }
        }

        /* 响应式标题 */
        @media (max-width: 768px) {
            .game-title h1 {
                font-size: 2.5em;
                letter-spacing: 1px;
            }

            .game-title::before,
            .game-title::after {
                font-size: 1.2em;
            }
        }

        @media (max-width: 480px) {
            .game-title h1 {
                font-size: 2em;
                letter-spacing: 0.5px;
            }

            .game-title::before,
            .game-title::after {
                display: none;
            }
        }

        /* 合并的得分和控制区域 */
        .game-info-controls-bar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            width: 100%;
            max-width: 600px;
            margin-bottom: 20px;
            padding: 10px 0;
        }

        .game-score-section {
            display: flex;
            gap: 12px;
            align-items: center;
        }

        .game-controls-section {
            display: flex;
            gap: 6px;
            align-items: center;
            flex-wrap: wrap;
            justify-content: center;
        }

        /* 游戏控制区域样式 */
        .game-controls-container {
            margin-bottom: 15px;
        }

        .game-controls-container .game-controls-section {
            display: flex;
            flex-direction: column;
            gap: 8px;
            align-items: stretch;
        }

        .game-controls-container .btn {
            width: 100%;
            min-width: auto;
            justify-content: center;
        }

        .game-score-bar {
            display: flex;
            gap: 15px;
            justify-content: center;
            align-items: center;
        }

        .game-controls-bar {
            display: flex;
            gap: 8px;
            justify-content: center;
        }

        .score-box {
            background: linear-gradient(135deg,
                    rgba(255, 255, 255, 0.25) 0%,
                    rgba(255, 255, 255, 0.15) 50%,
                    rgba(255, 255, 255, 0.1) 100%);
            padding: 12px 18px;
            border-radius: 15px;
            text-align: center;
            backdrop-filter: blur(20px);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 3px;
            white-space: nowrap;
            border: 2px solid rgba(255, 255, 255, 0.2);
            box-shadow:
                0 6px 24px rgba(0, 0, 0, 0.15),
                inset 0 1px 0 rgba(255, 255, 255, 0.3),
                0 0 0 1px rgba(255, 255, 255, 0.1);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
            overflow: hidden;
            min-width: 100px;
        }

        .score-box::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg,
                    transparent,
                    rgba(255, 255, 255, 0.2),
                    transparent);
            transition: left 0.6s ease;
        }

        .score-box:hover {
            transform: translateY(-2px) scale(1.02);
            box-shadow:
                0 12px 40px rgba(0, 0, 0, 0.25),
                inset 0 1px 0 rgba(255, 255, 255, 0.4),
                0 0 0 1px rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.3);
        }

        .score-box:hover::before {
            left: 100%;
        }

        .score-label {
            font-size: 12px;
            font-weight: 600;
            color: rgba(255, 255, 255, 0.9);
            margin: 0;
            text-transform: uppercase;
            letter-spacing: 1px;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
        }

        .score-value {
            font-size: 28px;
            font-weight: 900;
            margin: 0;
            background: linear-gradient(135deg, #ffd700, #ffed4e, #ffd700);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
            font-family: 'Arial Black', Arial, sans-serif;
            line-height: 1;
        }

        /* 特殊效果:当分数更新时的动画 */
        .score-value.score-updated {
            animation: scoreUpdate 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
        }

        @keyframes scoreUpdate {
            0% {
                transform: scale(1);
            }

            50% {
                transform: scale(1.2);
                text-shadow: 0 0 20px rgba(255, 215, 0, 0.8);
            }

            100% {
                transform: scale(1);
            }
        }

        /* 最高分特殊样式 */
        .score-box.best-score {
            background: linear-gradient(135deg,
                    rgba(255, 107, 107, 0.3) 0%,
                    rgba(238, 90, 82, 0.2) 50%,
                    rgba(255, 107, 107, 0.15) 100%);
            border-color: rgba(255, 107, 107, 0.3);
        }

        .score-box.best-score:hover {
            border-color: rgba(255, 107, 107, 0.4);
            box-shadow:
                0 12px 40px rgba(255, 107, 107, 0.2),
                inset 0 1px 0 rgba(255, 255, 255, 0.4),
                0 0 0 1px rgba(255, 107, 107, 0.2);
        }

        .score-box.best-score .score-value {
            background: linear-gradient(135deg, #ff6b6b, #ee5a52, #ff6b6b);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }

        .game-board {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(4, 1fr);
            gap: 18px;
            width: 100%;
            max-width: 500px;
            aspect-ratio: 1;
            background: linear-gradient(145deg, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.2));
            padding: 25px;
            border-radius: 25px;
            box-shadow:
                inset 0 0 30px rgba(0, 0, 0, 0.4),
                0 15px 35px rgba(0, 0, 0, 0.3),
                0 5px 15px rgba(0, 0, 0, 0.2);
            position: relative;
            border: 2px solid rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(15px);
        }

        .tile {
            background: linear-gradient(135deg,
                    rgba(255, 255, 255, 0.2) 0%,
                    rgba(255, 255, 255, 0.1) 50%,
                    rgba(255, 255, 255, 0.05) 100%);
            border-radius: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 2em;
            font-weight: 900;
            font-family: 'Arial Black', Arial, sans-serif;
            transition: all 0.3s ease;
            border: 2px solid rgba(255, 255, 255, 0.2);
            backdrop-filter: blur(15px);
            box-shadow:
                0 10px 30px rgba(0, 0, 0, 0.2),
                inset 0 2px 0 rgba(255, 255, 255, 0.3),
                inset 0 -2px 0 rgba(0, 0, 0, 0.1);
            position: relative;
            overflow: hidden;
        }

        .tile::before {
            content: '';
            position: absolute;
            top: -2px;
            left: -2px;
            right: -2px;
            bottom: -2px;
            background: linear-gradient(45deg,
                    rgba(255, 255, 255, 0.1),
                    transparent,
                    rgba(255, 255, 255, 0.1));
            border-radius: 22px;
            z-index: -1;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .tile:hover::before {
            opacity: 1;
        }

        .tile-2 {
            background: linear-gradient(135deg,
                    #ffffff 0%,
                    #f8f5f0 50%,
                    #f0e8dc 100%);
            color: #776e65;
            border: 2px solid rgba(240, 232, 220, 0.6);
            box-shadow:
                0 8px 25px rgba(238, 228, 218, 0.3),
                inset 0 2px 0 rgba(255, 255, 255, 0.8),
                inset 0 -2px 0 rgba(240, 232, 220, 0.3);
            text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
        }

        .tile-4 {
            background: linear-gradient(135deg,
                    #fdf6e3 0%,
                    #f4ead8 50%,
                    #ede0c8 100%);
            color: #776e65;
            border: 2px solid rgba(237, 224, 200, 0.6);
            box-shadow:
                0 8px 25px rgba(237, 224, 200, 0.3),
                inset 0 2px 0 rgba(255, 255, 255, 0.7),
                inset 0 -2px 0 rgba(237, 224, 200, 0.3);
            text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
        }

        .tile-8 {
            background: linear-gradient(135deg,
                    #ffb347 0%,
                    #f7a02b 50%,
                    #f2941f 100%);
            color: #ffffff;
            border: 2px solid rgba(242, 148, 31, 0.6);
            box-shadow:
                0 10px 30px rgba(242, 177, 121, 0.4),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(242, 148, 31, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
        }

        .tile-16 {
            background: linear-gradient(135deg,
                    #ff8c42 0%,
                    #ff7b25 50%,
                    #ff6a08 100%);
            color: #ffffff;
            border: 2px solid rgba(255, 106, 8, 0.6);
            box-shadow:
                0 10px 30px rgba(245, 149, 99, 0.4),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(255, 106, 8, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
        }

        .tile-32 {
            background: linear-gradient(135deg,
                    #ff6b47 0%,
                    #ff5722 50%,
                    #e64a19 100%);
            color: #ffffff;
            border: 2px solid rgba(230, 74, 25, 0.6);
            box-shadow:
                0 10px 30px rgba(246, 124, 95, 0.4),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(230, 74, 25, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
        }

        .tile-64 {
            background: linear-gradient(135deg,
                    #ff5722 0%,
                    #f4511e 50%,
                    #d84315 100%);
            color: #ffffff;
            border: 2px solid rgba(216, 67, 21, 0.6);
            box-shadow:
                0 12px 35px rgba(246, 94, 59, 0.5),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(216, 67, 21, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }

        .tile-128 {
            background: linear-gradient(135deg,
                    #ffd700 0%,
                    #ffed4e 50%,
                    #ffc107 100%);
            color: #ffffff;
            font-size: 1.8em;
            border: 2px solid rgba(255, 193, 7, 0.6);
            box-shadow:
                0 12px 35px rgba(255, 215, 0, 0.4),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(255, 193, 7, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
        }

        .tile-256 {
            background: linear-gradient(135deg,
                    #ffb300 0%,
                    #ffa000 50%,
                    #ff8f00 100%);
            color: #ffffff;
            font-size: 1.8em;
            border: 2px solid rgba(255, 143, 0, 0.6);
            box-shadow:
                0 12px 35px rgba(255, 160, 0, 0.4),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(255, 143, 0, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
        }

        .tile-512 {
            background: linear-gradient(135deg,
                    #ff9800 0%,
                    #ff8a65 50%,
                    #ff7043 100%);
            color: #ffffff;
            font-size: 1.8em;
            border: 2px solid rgba(255, 112, 67, 0.6);
            box-shadow:
                0 12px 35px rgba(255, 138, 101, 0.4),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(255, 112, 67, 0.3);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
        }

        .tile-1024 {
            background: linear-gradient(135deg,
                    #e91e63 0%,
                    #ad1457 50%,
                    #880e4f 100%);
            color: #ffffff;
            font-size: 1.5em;
            border: 2px solid rgba(136, 14, 79, 0.6);
            box-shadow:
                0 15px 40px rgba(233, 30, 99, 0.5),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(136, 14, 79, 0.3);
            text-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
        }

        .tile-2048 {
            background: linear-gradient(135deg,
                    #9c27b0 0%,
                    #7b1fa2 50%,
                    #4a148c 100%);
            color: #ffffff;
            font-size: 1.5em;
            border: 2px solid rgba(74, 20, 140, 0.6);
            box-shadow:
                0 15px 40px rgba(156, 39, 176, 0.6),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(74, 20, 140, 0.3);
            text-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
        }

        .tile-4096 {
            background: linear-gradient(135deg,
                    #673ab7 0%,
                    #512da8 50%,
                    #311b92 100%);
            color: #ffffff;
            font-size: 1.3em;
            border: 2px solid rgba(49, 27, 146, 0.6);
            box-shadow:
                0 15px 40px rgba(103, 58, 183, 0.6),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(49, 27, 146, 0.3);
            text-shadow: 0 2px 6px rgba(0, 0, 0, 0.7);
        }

        .tile-8192 {
            background: linear-gradient(135deg,
                    #3f51b5 0%,
                    #303f9f 50%,
                    #1a237e 100%);
            color: #ffffff;
            font-size: 1.2em;
            border: 2px solid rgba(26, 35, 126, 0.6);
            box-shadow:
                0 15px 40px rgba(63, 81, 181, 0.6),
                inset 0 2px 0 rgba(255, 255, 255, 0.6),
                inset 0 -2px 0 rgba(26, 35, 126, 0.3);
            text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
        }

        /* 动画效果 */
        @keyframes pulse {

            0%,
            100% {
                transform: scale(1);
            }

            50% {
                transform: scale(1.05);
            }
        }

        @keyframes pulse-glow {

            0%,
            100% {
                transform: scale(1);
                box-shadow:
                    0 12px 35px rgba(237, 207, 114, 0.6),
                    inset 0 1px 0 rgba(255, 255, 255, 0.5),
                    0 0 20px rgba(255, 215, 0, 0.3);
            }

            50% {
                transform: scale(1.08);
                box-shadow:
                    0 15px 45px rgba(255, 215, 0, 0.8),
                    inset 0 1px 0 rgba(255, 255, 255, 0.7),
                    0 0 30px rgba(255, 215, 0, 0.6);
            }
        }

        @keyframes mega-glow {
            0% {
                transform: scale(1);
                box-shadow:
                    0 15px 40px rgba(237, 197, 63, 0.7),
                    inset 0 1px 0 rgba(255, 255, 255, 0.6),
                    0 0 30px rgba(255, 215, 0, 0.6);
                filter: brightness(1) saturate(1);
            }

            100% {
                transform: scale(1.1);
                box-shadow:
                    0 20px 60px rgba(255, 215, 0, 1),
                    inset 0 2px 0 rgba(255, 255, 255, 0.8),
                    0 0 50px rgba(255, 215, 0, 1);
                filter: brightness(1.3) saturate(1.5);
            }
        }

        @keyframes rainbow-supreme {
            0% {
                filter: hue-rotate(0deg) brightness(1.2) saturate(1.5);
                box-shadow:
                    0 15px 40px rgba(60, 58, 50, 0.8),
                    inset 0 1px 0 rgba(255, 255, 255, 0.3),
                    0 0 40px rgba(255, 100, 255, 0.4);
            }

            25% {
                filter: hue-rotate(90deg) brightness(1.4) saturate(1.8);
                box-shadow:
                    0 18px 50px rgba(100, 255, 100, 0.6),
                    inset 0 1px 0 rgba(255, 255, 255, 0.4),
                    0 0 50px rgba(100, 255, 100, 0.6);
            }

            50% {
                filter: hue-rotate(180deg) brightness(1.3) saturate(2);
                box-shadow:
                    0 20px 60px rgba(100, 100, 255, 0.7),
                    inset 0 1px 0 rgba(255, 255, 255, 0.5),
                    0 0 60px rgba(100, 100, 255, 0.7);
            }

            75% {
                filter: hue-rotate(270deg) brightness(1.5) saturate(1.6);
                box-shadow:
                    0 18px 50px rgba(255, 255, 100, 0.8),
                    inset 0 1px 0 rgba(255, 255, 255, 0.4),
                    0 0 50px rgba(255, 255, 100, 0.8);
            }

            100% {
                filter: hue-rotate(360deg) brightness(1.2) saturate(1.5);
                box-shadow:
                    0 15px 40px rgba(255, 100, 255, 0.6),
                    inset 0 1px 0 rgba(255, 255, 255, 0.3),
                    0 0 40px rgba(255, 100, 255, 0.6);
            }
        }

        @keyframes glow {
            0% {
                box-shadow: 0 8px 25px rgba(237, 194, 46, 0.7);
            }

            100% {
                box-shadow: 0 12px 35px rgba(255, 215, 0, 0.9);
            }
        }

        @keyframes rainbow {
            0% {
                filter: hue-rotate(0deg) brightness(1.2);
            }

            33% {
                filter: hue-rotate(120deg) brightness(1.4);
            }

            66% {
                filter: hue-rotate(240deg) brightness(1.3);
            }

            100% {
                filter: hue-rotate(360deg) brightness(1.2);
            }
        }

        .btn {
            background: linear-gradient(45deg, #e74c3c, #c0392b);
            color: white;
            border: none;
            padding: 10px 14px;
            border-radius: 12px;
            cursor: pointer;
            font-size: 11px;
            transition: all 0.3s ease;
            box-shadow: 0 3px 8px rgba(231, 76, 60, 0.3);
            font-weight: bold;
            min-width: 70px;
            white-space: nowrap;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }

        .auto-button {
            background: #27ae60;
        }

        .auto-button:hover {
            background: #2ecc71;
        }

        .auto-button.active {
            background: #e74c3c;
        }

        .auto-button.active:hover {
            background: #c0392b;
        }

        .reset-button {
            background: linear-gradient(45deg, #f39c12, #e67e22);
        }

        .reset-button:hover {
            background: linear-gradient(45deg, #e67e22, #d35400);
        }

        .game-over {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(255, 255, 255, 0.9);
            display: none;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            border-radius: 10px;
            z-index: 100;
        }

        .game-over.show {
            display: flex;
        }

        .game-over h2 {
            color: #333;
            margin-bottom: 20px;
            font-size: 2em;
        }



        .main-container {
            display: flex;
            gap: 15px;
            width: 100%;
            align-items: stretch;
            justify-content: center;
            padding: 10px;
            min-height: calc(100vh - 20px);
            box-sizing: border-box;
        }

        .side-panel {
            flex: 0 0 260px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            padding: 15px;
            display: flex;
            flex-direction: column;
            height: 90vh;
            max-height: 850px;
            overflow: hidden;
            box-sizing: border-box;
        }

        .side-panel h3 {
            font-size: 1.1rem;
            margin-bottom: 8px;
            text-align: center;
            background: linear-gradient(45deg, #ff6b6b, #feca57);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            padding-bottom: 6px;
            border-bottom: 2px solid rgba(255, 255, 255, 0.2);
            flex-shrink: 0;
        }

        .game-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: flex-start;
            text-align: center;
            padding: 20px 15px 15px 15px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            margin: 0;
            max-width: none;
            min-width: 0;
            gap: 15px;
            height: 90vh;
            max-height: 850px;
        }

        .game-content-wrapper {
            flex: 1;
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: center;
            width: 100%;
            gap: 30px;
            padding: 20px 0;
        }

        /* 左右两侧得分框的特殊样式 */
        .score-left,
        .score-right {
            flex: 0 0 auto;
            align-self: center;
        }

        .score-left {
            order: 1;
        }

        .game-board {
            order: 2;
            flex: 0 0 auto;
        }

        .score-right {
            order: 3;
        }

        .guide-content {
            display: flex;
            flex-direction: column;
            gap: 8px;
            flex: 1;
            overflow: hidden;
            width: 100%;
            box-sizing: border-box;
            height: 100%;
            justify-content: space-between;
        }

        .guide-section {
            margin-bottom: 10px;
            flex: 1;
        }

        .guide-section h4 {
            font-size: 0.85rem;
            margin-bottom: 6px;
            color: #feca57;
            border-bottom: 1px solid rgba(255, 255, 255, 0.2);
            padding-bottom: 3px;
        }

        .guide-item {
            background: rgba(255, 255, 255, 0.1);
            padding: 4px 6px;
            border-radius: 4px;
            font-size: 0.7rem;
            line-height: 1.2;
            border-left: 3px solid #feca57;
            transition: all 0.3s ease;
            margin-bottom: 3px;
        }

        .guide-item:hover {
            background: rgba(255, 255, 255, 0.15);
            transform: translateX(5px);
            border-left-color: #ff6b6b;
        }

        .guide-item strong {
            color: #feca57;
        }

        /* AI算法信息特殊样式 */
        .ai-algorithm-item {
            background: linear-gradient(135deg,
                    rgba(102, 126, 234, 0.15) 0%,
                    rgba(118, 75, 162, 0.1) 100%);
            border: 1px solid rgba(102, 126, 234, 0.3);
            border-radius: 10px;
            padding: 10px;
            margin: 6px 0;
            overflow: hidden;
            width: 100%;
            box-sizing: border-box;
        }

        .algorithm-title {
            font-size: 0.8rem;
            font-weight: bold;
            color: #feca57;
            margin-bottom: 6px;
            text-align: center;
            border-bottom: 1px solid rgba(254, 202, 87, 0.3);
            padding-bottom: 4px;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }

        .algorithm-details {
            display: flex;
            flex-direction: column;
            gap: 3px;
            width: 100%;
            overflow: hidden;
        }

        .algorithm-feature {
            font-size: 0.65rem;
            line-height: 1.2;
            color: rgba(255, 255, 255, 0.9);
            padding: 2px 0;
            border-left: 2px solid rgba(102, 126, 234, 0.4);
            padding-left: 8px;
            margin: 2px 0;
            overflow: hidden;
            word-wrap: break-word;
            word-break: break-all;
            white-space: normal;
        }

        .algorithm-feature strong {
            color: #a8d8ff;
        }

        .auto-controls {
            margin-top: 15px;
            padding: 15px;
            background: rgba(0, 0, 0, 0.05);
            border-radius: 10px;
        }

        .speed-control {
            margin: 10px 0;
        }

        .speed-control label {
            display: inline-block;
            width: 80px;
            text-align: left;
            color: white;
        }

        .speed-control input {
            width: 150px;
        }

        .ai-info {
            font-size: 11px;
            color: #eee;
            margin-top: 5px;
            background: rgba(0, 0, 0, 0.1);
            padding: 8px;
            border-radius: 5px;
            text-align: left;
            line-height: 1.4;
        }

        /* 超级玩家模式区域整体样式 */
        .settings-container {
            display: flex;
            flex-direction: column;
            gap: 12px;
            height: 100%;
        }

        .settings-section {
            background: rgba(255, 255, 255, 0.08);
            border-radius: 12px;
            padding: 12px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            transition: all 0.3s ease;
        }

        .settings-section:hover {
            background: rgba(255, 255, 255, 0.12);
            border-color: rgba(255, 255, 255, 0.2);
        }

        .settings-section-title {
            font-size: 0.9rem;
            font-weight: bold;
            margin-bottom: 8px;
            color: #feca57;
            display: flex;
            align-items: center;
            gap: 6px;
            border-bottom: 1px solid rgba(254, 202, 87, 0.3);
            padding-bottom: 6px;
            white-space: nowrap;
        }

        .settings-description {
            font-size: 0.75rem;
            color: rgba(255, 255, 255, 0.8);
            line-height: 1.3;
            margin-bottom: 10px;
        }

        /* 超级玩家模式样式 */
        .super-player-container {
            position: relative;
        }

        .super-player-container.active {
            background: linear-gradient(135deg, rgba(255, 215, 0, 0.2), rgba(255, 193, 7, 0.1));
            border-color: rgba(255, 215, 0, 0.4);
            box-shadow: 0 0 25px rgba(255, 215, 0, 0.3);
        }

        .super-player-container.active::before {
            content: '';
            position: absolute;
            top: -2px;
            left: -2px;
            right: -2px;
            bottom: -2px;
            background: linear-gradient(45deg, #ffd700, #ffed4e, #ffd700);
            border-radius: 14px;
            z-index: -1;
            opacity: 0.3;
        }

        .ai-game-toggle {
            background: linear-gradient(135deg, #ffd700, #ffed4e);
            color: #333;
            border: none;
            padding: 10px 16px;
            border-radius: 20px;
            cursor: pointer;
            font-size: 12px;
            font-weight: bold;
            transition: all 0.3s ease;
            width: 100%;
            box-shadow: 0 3px 12px rgba(255, 215, 0, 0.3);
            text-transform: uppercase;
            letter-spacing: 0.3px;
        }

        .ai-game-toggle:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 15px rgba(255, 215, 0, 0.4);
        }

        .ai-game-toggle.active {
            background: linear-gradient(135deg, #ff6b6b, #ee5a52);
            color: white;
            box-shadow: 0 3px 12px rgba(255, 107, 107, 0.4);
        }

        .ai-game-toggle.active:hover {
            box-shadow: 0 4px 15px rgba(255, 107, 107, 0.5);
        }

        .ai-play-status {
            margin-top: 8px;
            padding: 6px 10px;
            background: rgba(255, 215, 0, 0.2);
            border-radius: 15px;
            font-size: 10px;
            color: #ffd700;
            font-weight: bold;
            text-align: center;
            border: 1px solid rgba(255, 215, 0, 0.3);
        }

        /* AI高级设置样式 */
        .ai-advanced-settings {
            margin-top: 10px;
            padding-top: 10px;
            border-top: 1px solid rgba(255, 255, 255, 0.1);
        }

        .speed-control {
            margin-bottom: 10px;
            padding: 8px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 8px;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        .speed-control-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 6px;
        }

        .speed-control label {
            font-size: 10px;
            color: #feca57;
            font-weight: bold;
        }

        .speed-control input[type="range"] {
            width: 100%;
            height: 4px;
            border-radius: 2px;
            background: rgba(255, 255, 255, 0.2);
            outline: none;
            -webkit-appearance: none;
        }

        .speed-control input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 14px;
            height: 14px;
            border-radius: 50%;
            background: linear-gradient(135deg, #ffd700, #ffed4e);
            cursor: pointer;
            box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
        }

        .speed-value {
            font-size: 9px;
            color: #fff;
            background: rgba(255, 215, 0, 0.2);
            padding: 1px 6px;
            border-radius: 8px;
            border: 1px solid rgba(255, 215, 0, 0.3);
        }

        .ai-info {
            background: linear-gradient(135deg, rgba(102, 126, 234, 0.2), rgba(118, 75, 162, 0.2));
            border: 1px solid rgba(102, 126, 234, 0.3);
            border-radius: 8px;
            padding: 10px;
            font-size: 9px;
            color: #e8e8e8;
            line-height: 1.4;
        }

        .ai-info strong {
            color: #feca57;
            font-size: 10px;
            display: block;
            margin-bottom: 6px;
        }

        .ai-info-item {
            margin: 2px 0;
            padding-left: 6px;
            border-left: 2px solid rgba(254, 202, 87, 0.3);
        }

        /* 功能说明区域样式 */
        .feature-list {
            display: flex;
            flex-direction: column;
            gap: 4px;
        }

        .feature-item {
            background: rgba(255, 255, 255, 0.05);
            padding: 6px 8px;
            border-radius: 6px;
            border-left: 2px solid #feca57;
            font-size: 0.7rem;
            line-height: 1.2;
            transition: all 0.3s ease;
        }

        .feature-item:hover {
            background: rgba(255, 255, 255, 0.1);
            transform: translateX(2px);
            border-left-color: #ff6b6b;
        }

        .feature-item strong {
            color: #feca57;
        }

        /* 验证模态框样式 */
        .question-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 1001;
        }

        .question-content {
            background: linear-gradient(135deg, #667eea, #764ba2);
            padding: 40px;
            border-radius: 15px;
            text-align: center;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            color: white;
            max-width: 400px;
            width: 90%;
        }

        .question-input {
            width: 100%;
            padding: 12px;
            margin: 15px 0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: center;
            background: rgba(255, 255, 255, 0.9);
            box-sizing: border-box;
        }

        .question-buttons {
            display: flex;
            gap: 10px;
            justify-content: center;
            margin-top: 20px;
        }

        @media (max-width: 1200px) {
            .main-container {
                flex-direction: column;
                align-items: center;
                gap: 15px;
            }

            .side-panel {
                flex: none;
                width: 100%;
                max-width: 600px;
            }

            .game-container {
                margin: 0;
                width: 100%;
                max-width: 600px;
            }
        }

        @media (max-width: 768px) {
            body {
                padding: 15px;
            }

            .main-container {
                padding: 0 15px 20px 15px;
                gap: 15px;
                max-width: none;
            }

            .game-title h1 {
                font-size: 2.5em;
            }

            .side-panel {
                padding: 18px;
            }

            .game-container {
                padding: 15px;
                min-width: auto;
            }

            .game-board {
                width: 100%;
                max-width: 350px;
            }

            .game-tile {
                font-size: 1.8em;
                min-height: 70px;
                min-width: 70px;
            }

            .game-tile.tile-128,
            .game-tile.tile-256,
            .game-tile.tile-512 {
                font-size: 1.5em;
            }

            .game-tile.tile-1024,
            .game-tile.tile-2048 {
                font-size: 1.2em;
            }

            .game-header-bar {
                flex-direction: column;
                gap: 15px;
            }

            .game-info {
                justify-content: center;
                flex-wrap: wrap;
            }

            .game-controls-bar {
                justify-content: center;
                flex-wrap: wrap;
            }

            .score-box {
                padding: 8px 16px;
                min-width: 120px;
            }

            .score-label {
                font-size: 14px;
            }

            .score-value {
                font-size: 20px;
            }

            .btn {
                font-size: 12px;
                padding: 8px 16px;
                min-width: 80px;
            }

            .guide-item {
                font-size: 0.8rem;
            }
        }
    </style>
</head>

<body>
    <!-- 备用背景 -->
    <div class="fallback-background"></div>

    <!-- 真实视频背景 -->
    <div class="video-background">
        <video autoplay muted loop playsinline id="bgVideo" preload="auto">
            <source src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
                type="video/mp4">
            <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
            <source src="https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_5mb.mp4" type="video/mp4">
            您的浏览器不支持HTML5视频播放。
        </video>
    </div>

    <!-- 视频遮罩层 -->
    <div class="video-overlay"></div>

    <!-- 主要内容区域:左中右三栏布局 -->
    <div class="main-container">
        <!-- 左侧操作指南面板 -->
        <div class="side-panel">
            <h3>📖 游戏指南</h3>
            <div class="guide-content">
                <div class="guide-section">
                    <h4>⌨️ 基础操作</h4>
                    <div class="guide-item"><strong>方向键</strong><strong>WASD</strong>:移动合并方块</div>
                    <div class="guide-item"><strong>触摸滑动</strong>:移动端手势操作</div>
                    <div class="guide-item"><strong>空格键</strong>:暂停/继续游戏</div>
                </div>

                <div class="guide-section">
                    <h4>🎯 游戏规则</h4>
                    <div class="guide-item">• 滑动方块,相同数字会<strong>自动合并</strong></div>
                    <div class="guide-item">• 目标是创造出 <strong>2048</strong> 方块</div>
                    <div class="guide-item">• 方块填满且无法移动时游戏结束</div>
                    <div class="guide-item">• 达到2048后可继续挑战更高数字</div>
                </div>

                <div class="guide-section">
                    <h4>🧠 高级策略</h4>
                    <div class="guide-item"><strong>角落策略</strong>:将最大数字保持在角落</div>
                    <div class="guide-item"><strong>单向原则</strong>:尽量保持一个主要移动方向</div>
                    <div class="guide-item"><strong>空间管理</strong>:避免随意填满空格</div>
                    <div class="guide-item"><strong>提前规划</strong>:思考每步移动的后果</div>
                </div>

                <div class="guide-section">
                    <h4>🤖 终极AI算法</h4>
                    <div class="guide-item ai-algorithm-item">
                        <div class="algorithm-title">🧠 <strong>Expectimax v3.0</strong></div>
                        <div class="algorithm-details">
                            <div class="algorithm-feature">🔍 <strong>搜索算法:</strong> Expectimax深度搜索</div>
                            <div class="algorithm-feature">🎯 <strong>核心策略:</strong> 角落蛇形权重矩阵</div>
                            <div class="algorithm-feature"><strong>启发函数:</strong> 单调性 + 平滑度 + 空格奖励</div>
                            <div class="algorithm-feature">📊 <strong>成功率:</strong> 99%+ 达到2048, 90%+ 达到4096</div>
                            <div class="algorithm-feature"><strong>特色:</strong> 自适应搜索深度,智能决策</div>
                        </div>
                    </div>
                </div>

            </div>
        </div>

        <!-- 中间游戏区域 -->
        <div class="game-container">
            <!-- 标题区域 - 独占一行居中 -->
            <div class="game-title">
                <h1>2048 - 终极版</h1>
            </div>

            <!-- 游戏内容区域 - 棋盘居中,得分左右分布 -->
            <div class="game-content-wrapper">
                <!-- 左侧得分 -->
                <div class="score-box score-left">
                    <div class="score-label">当前得分</div>
                    <div class="score-value" id="score">0</div>
                </div>

                <!-- 中间棋盘 -->
                <div class="game-board" id="game-board">
                    <div class="game-over" id="game-over">
                        <h2 id="game-over-text">游戏结束!</h2>
                        <button class="btn" onclick="game.restart()">重新开始</button>
                    </div>
                </div>

                <!-- 右侧最高分 -->
                <div class="score-box best-score score-right">
                    <div class="score-label">历史最高</div>
                    <div class="score-value" id="best-score">0</div>
                </div>
            </div>

        </div>

        <!-- 右侧面板:超级玩家模式 -->
        <div class="side-panel">
            <h3>🌟 超级玩家模式</h3>
            <div class="settings-container">

                <!-- 游戏控制区域 -->
                <div class="settings-section game-controls-container">
                    <div class="settings-section-title">
                        🎮 游戏控制
                    </div>
                    <div class="settings-description">
                        基础游戏操作和功能控制
                    </div>
                    <div class="game-controls-section">
                        <button class="btn" onclick="game.restart()">新游戏</button>
                        <button class="btn" onclick="game.undo()" id="undo-btn">撤销</button>
                        <button class="btn reset-button" onclick="game.resetGameRecord()" id="reset-btn">重置记录</button>
                    </div>
                </div>

                <!-- 超级玩家模式区域 -->
                <div class="settings-section super-player-container" id="aiGameMode">
                    <div class="settings-section-title">
                        🌟 超级玩家模式
                    </div>
                    <div class="settings-description">
                        通过验证解锁AI自动游戏功能,体验终极算法的强大实力
                    </div>

                    <button class="ai-game-toggle" onclick="handleAIGameToggle()" id="aiGameToggle">
                        开启超级玩家模式
                    </button>

                    <div class="ai-play-status" id="aiPlayStatus" style="display: none;">
                        🤖 AI正在游戏中...
                    </div>

                    <!-- AI高级设置区域 - 只有验证通过后才显示 -->
                    <div class="ai-advanced-settings" id="aiAdvancedSettings" style="display: none;">
                        <div class="speed-control">
                            <div class="speed-control-header">
                                <label for="speed-slider">AI速度控制</label>
                                <span class="speed-value" id="speed-value">150ms</span>
                            </div>
                            <input type="range" id="speed-slider" min="50" max="500" value="150"
                                onchange="game.setAutoSpeed(this.value)">
                        </div>
                    </div>
                </div>
            </div>

        </div>
    </div>
    </div>

    <!-- 超级玩家模式验证模态框 -->
    <div class="question-modal" id="questionModal">
        <div class="question-content">
            <h2>🔐 超级玩家验证</h2>
            <p id="questionText">请回答以下问题以开启超级玩家模式:</p>
            <input type="text" class="question-input" id="questionInput" placeholder="请输入答案..." maxlength="50">
            <div class="question-buttons">
                <button class="btn" onclick="submitAnswer()">确认</button>
                <button class="btn" onclick="closeQuestionModal()">取消</button>
            </div>
        </div>
    </div>

    <script>
        // AI游戏验证问题集合
        const aiGameQuestions = [
            {
                question: "最靓仔的是谁?",
                answer: "你"
            },
            {
                question: "1+1等于几?",
                answer: "2"
            },
            {
                question: "2048游戏的目标数字是多少?",
                answer: "2048"
            },
            {
                question: "一周有几天?",
                answer: "7"
            }
        ];

        let currentQuestion = null;
        let superPlayerMode = false; // 超级玩家模式状态

        // 超级玩家模式验证相关函数
        function handleAIGameToggle() {
            if (!superPlayerMode) {
                // 超级玩家模式未开启,需要验证
                showQuestionModal();
            } else {
                // 超级玩家模式已开启,可以控制AI游戏
                if (game.isAutoPlaying) {
                    // 停止AI游戏
                    game.stopAutoPlay();
                } else {
                    // 开始AI游戏
                    game.startAutoPlay();
                }
                updateAIGameUI();
            }
        }

        function showQuestionModal() {
            currentQuestion = aiGameQuestions[Math.floor(Math.random() * aiGameQuestions.length)];
            document.getElementById('questionText').textContent = `请回答以下问题以开启超级玩家模式:${currentQuestion.question}`;
            document.getElementById('questionInput').value = '';
            document.getElementById('questionModal').style.display = 'flex';
            document.getElementById('questionInput').focus();
        }

        function closeQuestionModal() {
            document.getElementById('questionModal').style.display = 'none';
            currentQuestion = null;
        }

        function submitAnswer() {
            const userAnswer = document.getElementById('questionInput').value.trim();
            const correctAnswer = currentQuestion.answer;

            if (userAnswer === correctAnswer) {
                // 答案正确,开启超级玩家模式
                superPlayerMode = true;
                updateAIGameUI();
                closeQuestionModal();

                // 显示成功消息
                setTimeout(() => {
                    alert('🎉 验证成功!超级玩家模式已开启!\n现在可以使用AI游戏功能。');
                }, 100);
            } else {
                // 答案错误
                alert('❌ 答案错误,请重试!');
                document.getElementById('questionInput').value = '';
                document.getElementById('questionInput').focus();
            }
        }

        function updateAIGameUI() {
            const containerElement = document.getElementById('aiGameMode');
            const toggleButton = document.getElementById('aiGameToggle');
            const statusElement = document.getElementById('aiPlayStatus');
            const advancedSettings = document.getElementById('aiAdvancedSettings');

            if (superPlayerMode) {
                containerElement.classList.add('active');
                advancedSettings.style.display = 'block'; // 显示AI高级设置
                if (game.isAutoPlaying) {
                    toggleButton.textContent = '停止AI游戏';
                    toggleButton.classList.add('active');
                    statusElement.style.display = 'block';
                } else {
                    toggleButton.textContent = '开始AI游戏';
                    toggleButton.classList.remove('active');
                    statusElement.style.display = 'none';
                }
            } else {
                containerElement.classList.remove('active');
                toggleButton.textContent = '开启超级玩家模式';
                toggleButton.classList.remove('active');
                statusElement.style.display = 'none';
                advancedSettings.style.display = 'none'; // 隐藏AI高级设置
            }
        }

        // 键盘事件监听(回车键提交答案)
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && document.getElementById('questionModal').style.display === 'flex') {
                e.preventDefault();
                submitAnswer();
            }
        });

        class Game2048 {
            constructor() {
                this.board = [];
                this.score = 0;
                this.bestScore = localStorage.getItem('bestScore') || 0;
                this.previousState = null;
                this.size = 4;
                this.isAutoPlaying = false;
                this.autoSpeed = 150;
                this.autoInterval = null;
                this.init();
            }

            init() {
                this.board = Array(this.size).fill().map(() => Array(this.size).fill(0));
                this.score = 0;
                this.updateDisplay();
                this.addRandomTile();
                this.addRandomTile();
                this.render();
                this.bindEvents();
            }

            bindEvents() {
                document.addEventListener('keydown', (e) => {
                    if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
                        e.preventDefault();
                        if (!this.isAutoPlaying) {
                            this.saveState();
                            this.move(e.key);
                        }
                    }
                });

                // 触摸事件支持
                let startX, startY;
                const gameBoard = document.getElementById('game-board');

                gameBoard.addEventListener('touchstart', (e) => {
                    if (!this.isAutoPlaying) {
                        startX = e.touches[0].clientX;
                        startY = e.touches[0].clientY;
                    }
                });

                gameBoard.addEventListener('touchend', (e) => {
                    if (!startX || !startY || this.isAutoPlaying) return;

                    const endX = e.changedTouches[0].clientX;
                    const endY = e.changedTouches[0].clientY;

                    const diffX = startX - endX;
                    const diffY = startY - endY;

                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        if (diffX > 0) {
                            this.saveState();
                            this.move('ArrowLeft');
                        } else {
                            this.saveState();
                            this.move('ArrowRight');
                        }
                    } else {
                        if (diffY > 0) {
                            this.saveState();
                            this.move('ArrowUp');
                        } else {
                            this.saveState();
                            this.move('ArrowDown');
                        }
                    }

                    startX = null;
                    startY = null;
                });
            }

            saveState() {
                this.previousState = {
                    board: this.board.map(row => [...row]),
                    score: this.score
                };
            }

            undo() {
                if (this.previousState && !this.isAutoPlaying) {
                    this.board = this.previousState.board;
                    this.score = this.previousState.score;
                    this.previousState = null;
                    this.render();
                    this.updateDisplay();
                }
            }

            addRandomTile() {
                const emptyCells = [];
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        if (this.board[i][j] === 0) {
                            emptyCells.push({ x: i, y: j });
                        }
                    }
                }

                if (emptyCells.length > 0) {
                    const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    this.board[randomCell.x][randomCell.y] = Math.random() < 0.9 ? 2 : 4;
                }
            }

            move(direction) {
                let moved = false;
                const newBoard = this.board.map(row => [...row]);
                const originalScore = this.score;

                switch (direction) {
                    case 'ArrowLeft':
                        moved = this.moveLeft(newBoard);
                        break;
                    case 'ArrowRight':
                        moved = this.moveRight(newBoard);
                        break;
                    case 'ArrowUp':
                        moved = this.moveUp(newBoard);
                        break;
                    case 'ArrowDown':
                        moved = this.moveDown(newBoard);
                        break;
                }

                if (moved) {
                    this.board = newBoard;
                    this.addRandomTile();
                    this.render();
                    this.updateDisplay();

                    const maxTile = Math.max(...this.board.flat());
                    if (maxTile >= 2048 && !this.hasShownWin) {
                        this.hasShownWin = true;
                        setTimeout(() => {
                            alert(`恭喜!达到了${maxTile}!游戏继续...`);
                        }, 100);
                    }

                    if (this.isGameOver()) {
                        this.showGameOver();
                    }
                }
                return moved;
            }

            moveLeft(board) {
                let moved = false;
                for (let i = 0; i < this.size; i++) {
                    const row = board[i].filter(val => val !== 0);
                    for (let j = 0; j < row.length - 1; j++) {
                        if (row[j] === row[j + 1]) {
                            row[j] *= 2;
                            this.score += row[j];
                            row.splice(j + 1, 1);
                        }
                    }
                    while (row.length < this.size) {
                        row.push(0);
                    }

                    for (let j = 0; j < this.size; j++) {
                        if (board[i][j] !== row[j]) {
                            moved = true;
                        }
                        board[i][j] = row[j];
                    }
                }
                return moved;
            }

            moveRight(board) {
                let moved = false;
                for (let i = 0; i < this.size; i++) {
                    const row = board[i].filter(val => val !== 0);
                    for (let j = row.length - 1; j > 0; j--) {
                        if (row[j] === row[j - 1]) {
                            row[j] *= 2;
                            this.score += row[j];
                            row.splice(j - 1, 1);
                            j--;
                        }
                    }
                    while (row.length < this.size) {
                        row.unshift(0);
                    }

                    for (let j = 0; j < this.size; j++) {
                        if (board[i][j] !== row[j]) {
                            moved = true;
                        }
                        board[i][j] = row[j];
                    }
                }
                return moved;
            }

            moveUp(board) {
                let moved = false;
                for (let j = 0; j < this.size; j++) {
                    const column = [];
                    for (let i = 0; i < this.size; i++) {
                        if (board[i][j] !== 0) {
                            column.push(board[i][j]);
                        }
                    }

                    for (let i = 0; i < column.length - 1; i++) {
                        if (column[i] === column[i + 1]) {
                            column[i] *= 2;
                            this.score += column[i];
                            column.splice(i + 1, 1);
                        }
                    }

                    while (column.length < this.size) {
                        column.push(0);
                    }

                    for (let i = 0; i < this.size; i++) {
                        if (board[i][j] !== column[i]) {
                            moved = true;
                        }
                        board[i][j] = column[i];
                    }
                }
                return moved;
            }

            moveDown(board) {
                let moved = false;
                for (let j = 0; j < this.size; j++) {
                    const column = [];
                    for (let i = 0; i < this.size; i++) {
                        if (board[i][j] !== 0) {
                            column.push(board[i][j]);
                        }
                    }

                    for (let i = column.length - 1; i > 0; i--) {
                        if (column[i] === column[i - 1]) {
                            column[i] *= 2;
                            this.score += column[i];
                            column.splice(i - 1, 1);
                            i--;
                        }
                    }

                    while (column.length < this.size) {
                        column.unshift(0);
                    }

                    for (let i = 0; i < this.size; i++) {
                        if (board[i][j] !== column[i]) {
                            moved = true;
                        }
                        board[i][j] = column[i];
                    }
                }
                return moved;
            }

            render() {
                const gameBoard = document.getElementById('game-board');
                const tiles = gameBoard.querySelectorAll('.tile');

                // 移除现有的数字方块
                tiles.forEach(tile => {
                    if (!tile.classList.contains('game-over')) {
                        tile.remove();
                    }
                });

                // 创建新的方块
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        const tile = document.createElement('div');
                        tile.className = 'tile';

                        if (this.board[i][j] !== 0) {
                            tile.classList.add(`tile-${this.board[i][j]}`);
                            tile.textContent = this.board[i][j];
                        }

                        gameBoard.appendChild(tile);
                    }
                }
            }

            updateDisplay() {
                document.getElementById('score').textContent = this.score;
                if (this.score > this.bestScore) {
                    this.bestScore = this.score;
                    localStorage.setItem('bestScore', this.bestScore);
                }
                document.getElementById('best-score').textContent = this.bestScore;
            }

            isGameOver() {
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        if (this.board[i][j] === 0) return false;
                        if (i < this.size - 1 && this.board[i + 1][j] === this.board[i][j]) return false;
                        if (j < this.size - 1 && this.board[i][j + 1] === this.board[i][j]) return false;
                    }
                }
                return true;
            }

            showGameOver() {
                const gameOverElement = document.getElementById('game-over');
                const gameOverText = document.getElementById('game-over-text');
                const maxTile = Math.max(...this.board.flat());
                gameOverText.textContent = `游戏结束!最高数字: ${maxTile}`;
                gameOverElement.classList.add('show');
                if (this.isAutoPlaying) this.stopAutoPlay();
            }

            restart() {
                document.getElementById('game-over').classList.remove('show');
                this.stopAutoPlay();
                this.hasShownWin = false;
                this.init();
            }

            resetGameRecord() {
                // 确认对话框
                if (confirm('确定要重置游戏记录吗?这将清除最高分记录,此操作不可撤销!')) {
                    // 清除本地存储的最高分
                    localStorage.removeItem('bestScore');
                    this.bestScore = 0;

                    // 停止自动游戏
                    this.stopAutoPlay();

                    // 重新初始化游戏
                    this.hasShownWin = false;
                    this.init();

                    // 显示重置成功提示
                    setTimeout(() => {
                        alert('游戏记录已重置!最高分已清零。');
                    }, 100);
                }
            }

            toggleAutoPlay() {
                if (this.isAutoPlaying) {
                    this.stopAutoPlay();
                } else {
                    this.startAutoPlay();
                }
            }

            startAutoPlay() {
                this.isAutoPlaying = true;
                updateAIGameUI();

                this.autoInterval = setInterval(() => {
                    if (this.isGameOver()) {
                        this.stopAutoPlay();
                        this.showGameOver();
                        return;
                    }
                    const bestMove = this.getBestMove();
                    if (bestMove) {
                        this.saveState();
                        this.move(bestMove);
                    } else {
                        this.stopAutoPlay();
                    }
                }, this.autoSpeed);
            }

            stopAutoPlay() {
                this.isAutoPlaying = false;
                if (this.autoInterval) {
                    clearInterval(this.autoInterval);
                    this.autoInterval = null;
                }
                updateAIGameUI();
            }

            setAutoSpeed(speed) {
                this.autoSpeed = parseInt(speed);
                document.getElementById('speed-value').textContent = speed + 'ms';
                if (this.isAutoPlaying) {
                    this.stopAutoPlay();
                    this.startAutoPlay();
                }
            }

            // ===== 终极AI算法 v3.0 =====
            getBestMove() {
                const moves = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
                let bestMove = null;
                let bestScore = -Infinity;
                const searchDepth = this.getAdaptiveDepth();

                for (const move of moves) {
                    const tempBoard = this.cloneBoard(this.board);
                    const tempScore = this.score;

                    if (this.simulateMove(tempBoard, move)) {
                        const score = this.expectimax(tempBoard, searchDepth, false);
                        if (score > bestScore) {
                            bestScore = score;
                            bestMove = move;
                        }
                    }
                    this.score = tempScore; // Restore score after simulation
                }
                return bestMove;
            }

            getAdaptiveDepth() {
                const emptyCells = this.countEmptyCells(this.board);
                if (emptyCells > 6) return 3;
                if (emptyCells > 3) return 4;
                return 5; // Deeper search when board is crowded
            }

            expectimax(board, depth, isPlayerTurn) {
                if (depth === 0 || this.isTerminal(board)) {
                    return this.evaluate(board);
                }

                if (isPlayerTurn) { // Maximize for player
                    let maxScore = -Infinity;
                    const moves = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
                    for (const move of moves) {
                        const newBoard = this.cloneBoard(board);
                        const tempScore = this.score;
                        if (this.simulateMove(newBoard, move)) {
                            maxScore = Math.max(maxScore, this.expectimax(newBoard, depth - 1, false));
                        }
                        this.score = tempScore;
                    }
                    return maxScore;
                } else { // Calculate expectation for computer
                    let totalScore = 0;
                    const emptyCells = this.getEmptyCells(board);
                    if (emptyCells.length === 0) {
                        return this.evaluate(board);
                    }

                    for (const cell of emptyCells) {
                        // 90% chance for a 2
                        const board2 = this.cloneBoard(board);
                        board2[cell.x][cell.y] = 2;
                        totalScore += 0.9 * this.expectimax(board2, depth - 1, true);

                        // 10% chance for a 4
                        const board4 = this.cloneBoard(board);
                        board4[cell.x][cell.y] = 4;
                        totalScore += 0.1 * this.expectimax(board4, depth - 1, true);
                    }
                    return totalScore / emptyCells.length;
                }
            }

            isTerminal(board) {
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        if (board[i][j] === 0) return false;
                        if (i < this.size - 1 && board[i + 1][j] === board[i][j]) return false;
                        if (j < this.size - 1 && board[i][j + 1] === board[i][j]) return false;
                    }
                }
                return true;
            }

            evaluate(board) {
                const emptyCellsWeight = 100000;
                const monotonicityWeight = 10000;
                const smoothnessWeight = 500;
                const snakeWeight = 50000;

                return this.getSnakePatternScore(board) * snakeWeight +
                    this.getMonotonicity(board) * monotonicityWeight +
                    this.getSmoothness(board) * smoothnessWeight +
                    this.countEmptyCells(board) * emptyCellsWeight;
            }

            getSnakePatternScore(board) {
                const weights = [
                    [10, 8, 7, 6.5],
                    [5, 3, 1.5, 1],
                    [-0.5, -1.5, -1.8, -2],
                    [-3, -3.5, -4, -4.5]
                ];

                let score = 0;
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        if (board[i][j] !== 0) {
                            score += board[i][j] * weights[i][j];
                        }
                    }
                }
                return score;
            }

            getMonotonicity(board) {
                let totals = [0, 0, 0, 0]; // up, down, left, right

                // left/right
                for (let i = 0; i < this.size; i++) {
                    let current = 0;
                    let next = current + 1;
                    while (next < 4) {
                        while (next < 4 && board[i][next] === 0) next++;
                        if (next >= 4) next--;
                        const currentValue = board[i][current] !== 0 ? Math.log2(board[i][current]) : 0;
                        const nextValue = board[i][next] !== 0 ? Math.log2(board[i][next]) : 0;
                        if (currentValue > nextValue) {
                            totals[0] += nextValue - currentValue;
                        } else if (nextValue > currentValue) {
                            totals[1] += currentValue - nextValue;
                        }
                        current = next;
                        next++;
                    }
                }

                // up/down
                for (let j = 0; j < this.size; j++) {
                    let current = 0;
                    let next = current + 1;
                    while (next < 4) {
                        while (next < 4 && board[next][j] === 0) next++;
                        if (next >= 4) next--;
                        const currentValue = board[current][j] !== 0 ? Math.log2(board[current][j]) : 0;
                        const nextValue = board[next][j] !== 0 ? Math.log2(board[next][j]) : 0;
                        if (currentValue > nextValue) {
                            totals[2] += nextValue - currentValue;
                        } else if (nextValue > currentValue) {
                            totals[3] += currentValue - nextValue;
                        }
                        current = next;
                        next++;
                    }
                }
                return Math.max(totals[0], totals[1]) + Math.max(totals[2], totals[3]);
            }

            getSmoothness(board) {
                let smoothness = 0;
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        if (board[i][j] !== 0) {
                            const value = Math.log2(board[i][j]);
                            // right
                            if (j < this.size - 1 && board[i][j + 1] !== 0) {
                                const rightValue = Math.log2(board[i][j + 1]);
                                smoothness -= Math.abs(value - rightValue);
                            }
                            // down
                            if (i < this.size - 1 && board[i + 1][j] !== 0) {
                                const downValue = Math.log2(board[i + 1][j]);
                                smoothness -= Math.abs(value - downValue);
                            }
                        }
                    }
                }
                return smoothness;
            }

            // Helper functions
            cloneBoard(board) {
                return board.map(row => [...row]);
            }

            simulateMove(board, direction) {
                const originalScore = this.score;
                let moved = false;
                switch (direction) {
                    case 'ArrowLeft': moved = this.moveLeft(board); break;
                    case 'ArrowRight': moved = this.moveRight(board); break;
                    case 'ArrowUp': moved = this.moveUp(board); break;
                    case 'ArrowDown': moved = this.moveDown(board); break;
                }
                this.score = originalScore;
                return moved;
            }

            getEmptyCells(board) {
                const emptyCells = [];
                for (let i = 0; i < this.size; i++) {
                    for (let j = 0; j < this.size; j++) {
                        if (board[i][j] === 0) {
                            emptyCells.push({ x: i, y: j });
                        }
                    }
                }
                return emptyCells;
            }

            countEmptyCells(board) {
                return this.getEmptyCells(board).length;
            }
        }

        const game = new Game2048();
    </script>
</body>

</html>


4.总结

这个游戏比较有意思的地方是利用算法去做事情,在这个过程中有算法无法突破512的方块合并的问题、权重比不够、游戏方法理解不足等问题,最后还是解决了,总结下来用算法练练手,后续在实战项目可以更加丝滑的使用算法解决问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值