2048小游戲實現

2048小游戲實現

將創建一個完整的2048小游戲,包含游戲核心邏輯和美觀的用戶界面。
在這里插入圖片描述

設計思路

  • 4x4網格布局
  • 響應式設計,適配不同設備
  • 分數顯示和最高分記錄
  • 鍵盤控制(方向鍵)和觸摸滑動支持
  • 游戲狀態提示(勝利/失敗)

完整代碼實現

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>2048小游戲</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;}body {background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);min-height: 100vh;display: flex;justify-content: center;align-items: center;padding: 20px;}.container {max-width: 500px;width: 100%;}.header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 20px;}h1 {color: #776e65;font-size: 60px;font-weight: 700;text-shadow: 2px 2px 4px rgba(0,0,0,0.1);}.scores-container {display: flex;gap: 10px;}.score-box {background: #bbada0;color: white;padding: 10px 15px;border-radius: 6px;text-align: center;min-width: 100px;position: relative;}.score-box:after {content: attr(data-label);display: block;font-size: 12px;font-weight: bold;text-transform: uppercase;color: #eee4da;}.score {font-size: 22px;font-weight: bold;}.game-intro {display: flex;justify-content: space-between;align-items: center;margin-bottom: 20px;}.game-explanation {color: #776e65;font-size: 16px;line-height: 1.4;max-width: 250px;}.restart-button {background: #8f7a66;color: #f9f6f2;border: none;border-radius: 6px;padding: 12px 20px;font-size: 18px;font-weight: bold;cursor: pointer;transition: all 0.2s;}.restart-button:hover {background: #7c6b5a;transform: scale(1.05);}.game-container {background: #bbada0;border-radius: 6px;padding: 15px;position: relative;box-shadow: 0 10px 30px rgba(0,0,0,0.15);}.grid-container {display: grid;grid-template-columns: repeat(4, 1fr);grid-gap: 10px;background: rgba(238, 228, 218, 0.35);border-radius: 6px;padding: 10px;position: relative;touch-action: none;}.grid-cell {background: rgba(238, 228, 218, 0.35);border-radius: 4px;height: 0;padding-bottom: 100%;}.tile-container {position: absolute;top: 0;left: 0;right: 0;bottom: 0;padding: 10px;}.tile {position: absolute;width: calc(25% - 12.5px);height: calc(25% - 12.5px);border-radius: 4px;display: flex;justify-content: center;align-items: center;font-size: 35px;font-weight: bold;transition: all 0.15s ease;z-index: 10;}.tile-2 { background: #eee4da; color: #776e65; }.tile-4 { background: #ede0c8; color: #776e65; }.tile-8 { background: #f2b179; color: #f9f6f2; }.tile-16 { background: #f59563; color: #f9f6f2; }.tile-32 { background: #f67c5f; color: #f9f6f2; }.tile-64 { background: #f65e3b; color: #f9f6f2; }.tile-128 { background: #edcf72; color: #f9f6f2; font-size: 30px; }.tile-256 { background: #edcc61; color: #f9f6f2; font-size: 30px; }.tile-512 { background: #edc850; color: #f9f6f2; font-size: 30px; }.tile-1024 { background: #edc53f; color: #f9f6f2; font-size: 25px; }.tile-2048 { background: #edc22e; color: #f9f6f2; font-size: 25px; }.tile-super { background: #3c3a32; color: #f9f6f2; font-size: 20px; }.game-message {display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;background: rgba(238, 228, 218, 0.73);border-radius: 6px;flex-direction: column;justify-content: center;align-items: center;z-index: 100;}.game-message.game-won, .game-message.game-over {display: flex;}.game-message p {font-size: 50px;font-weight: bold;color: #776e65;margin-bottom: 20px;}.instructions {margin-top: 30px;color: #776e65;text-align: center;line-height: 1.6;font-size: 16px;}@media (max-width: 520px) {.header {flex-direction: column;align-items: flex-start;}h1 {font-size: 50px;margin-bottom: 15px;}.game-intro {flex-direction: column;align-items: flex-start;gap: 15px;}.tile {font-size: 24px;}.tile-128, .tile-256, .tile-512 {font-size: 22px;}.tile-1024, .tile-2048 {font-size: 18px;}}</style>
</head>
<body><div class="container"><div class="header"><h1>2048</h1><div class="scores-container"><div class="score-box" data-label="分數"><div class="score" id="score">0</div></div><div class="score-box" data-label="最高分"><div class="score" id="best-score">0</div></div></div></div><div class="game-intro"><div class="game-explanation">合并相同數字的方塊,得到2048方塊!</div><button class="restart-button" id="restart-button">新游戲</button></div><div class="game-container"><div class="grid-container"><!-- 4x4網格 --><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="grid-cell"></div><div class="tile-container" id="tile-container"></div><div class="game-message" id="game-message"><p id="message-text"></p><button class="restart-button" id="keep-playing-button">繼續游戲</button></div></div></div><div class="instructions"><p><strong>游戲指南:</strong>使用鍵盤方向鍵(↑, ↓, ←, →)或觸摸屏滑動移動方塊。當兩個相同數字的方塊碰撞時,它們會合并成它們的和!</p></div></div><script>document.addEventListener('DOMContentLoaded', () => {// 游戲常量const GRID_SIZE = 4;const CELL_SIZE = 20; // 百分比const CELL_GAP = 2;   // 百分比// 游戲狀態let grid = [];let score = 0;let bestScore = localStorage.getItem('bestScore') || 0;let gameOver = false;let gameWon = false;// DOM元素const gridContainer = document.querySelector('.grid-container');const tileContainer = document.getElementById('tile-container');const scoreDisplay = document.getElementById('score');const bestScoreDisplay = document.getElementById('best-score');const restartButton = document.getElementById('restart-button');const gameMessage = document.getElementById('game-message');const messageText = document.getElementById('message-text');const keepPlayingButton = document.getElementById('keep-playing-button');// 初始化游戲function initGame() {// 重置游戲狀態grid = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));tileContainer.innerHTML = '';score = 0;gameOver = false;gameWon = false;// 更新UIupdateScore();gameMessage.className = 'game-message';// 添加初始方塊addRandomTile();addRandomTile();// 渲染游戲板render();}// 添加隨機方塊function addRandomTile() {const emptyCells = [];// 查找所有空格子for (let row = 0; row < GRID_SIZE; row++) {for (let col = 0; col < GRID_SIZE; col++) {if (grid[row][col] === 0) {emptyCells.push({ row, col });}}}// 如果有空格子,隨機選擇一個并添加2或4if (emptyCells.length > 0) {const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];grid[randomCell.row][randomCell.col] = Math.random() < 0.9 ? 2 : 4;}}// 渲染游戲板function render() {tileContainer.innerHTML = '';for (let row = 0; row < GRID_SIZE; row++) {for (let col = 0; col < GRID_SIZE; col++) {const value = grid[row][col];if (value !== 0) {const tile = document.createElement('div');tile.className = `tile tile-${value}`;tile.textContent = value;// 設置位置tile.style.left = `${col * (CELL_SIZE + CELL_GAP) + CELL_GAP}%`;tile.style.top = `${row * (CELL_SIZE + CELL_GAP) + CELL_GAP}%`;tileContainer.appendChild(tile);}}}}// 移動方塊function move(direction) {if (gameOver) return;let moved = false;let newGrid = JSON.parse(JSON.stringify(grid));// 根據方向處理移動switch (direction) {case 'up':for (let col = 0; col < GRID_SIZE; col++) {const column = [];for (let row = 0; row < GRID_SIZE; row++) {if (newGrid[row][col] !== 0) {column.push(newGrid[row][col]);}}// 合并相同數字for (let i = 0; i < column.length - 1; i++) {if (column[i] === column[i + 1]) {column[i] *= 2;score += column[i];column.splice(i + 1, 1);}}// 更新列for (let row = 0; row < GRID_SIZE; row++) {newGrid[row][col] = row < column.length ? column[row] : 0;}}break;case 'down':for (let col = 0; col < GRID_SIZE; col++) {const column = [];for (let row = GRID_SIZE - 1; row >= 0; row--) {if (newGrid[row][col] !== 0) {column.push(newGrid[row][col]);}}// 合并相同數字for (let i = 0; i < column.length - 1; i++) {if (column[i] === column[i + 1]) {column[i] *= 2;score += column[i];column.splice(i + 1, 1);}}// 更新列for (let row = GRID_SIZE - 1; row >= 0; row--) {newGrid[row][col] = (GRID_SIZE - 1 - row) < column.length ? column[GRID_SIZE - 1 - row] : 0;}}break;case 'left':for (let row = 0; row < GRID_SIZE; row++) {const rowData = [];for (let col = 0; col < GRID_SIZE; col++) {if (newGrid[row][col] !== 0) {rowData.push(newGrid[row][col]);}}// 合并相同數字for (let i = 0; i < rowData.length - 1; i++) {if (rowData[i] === rowData[i + 1]) {rowData[i] *= 2;score += rowData[i];rowData.splice(i + 1, 1);}}// 更新行for (let col = 0; col < GRID_SIZE; col++) {newGrid[row][col] = col < rowData.length ? rowData[col] : 0;}}break;case 'right':for (let row = 0; row < GRID_SIZE; row++) {const rowData = [];for (let col = GRID_SIZE - 1; col >= 0; col--) {if (newGrid[row][col] !== 0) {rowData.push(newGrid[row][col]);}}// 合并相同數字for (let i = 0; i < rowData.length - 1; i++) {if (rowData[i] === rowData[i + 1]) {rowData[i] *= 2;score += rowData[i];rowData.splice(i + 1, 1);}}// 更新行for (let col = GRID_SIZE - 1; col >= 0; col--) {newGrid[row][col] = (GRID_SIZE - 1 - col) < rowData.length ? rowData[GRID_SIZE - 1 - col] : 0;}}break;}// 檢查是否有移動moved = JSON.stringify(grid) !== JSON.stringify(newGrid);if (moved) {grid = newGrid;addRandomTile();updateScore();render();checkGameStatus();}}// 檢查游戲狀態function checkGameStatus() {// 檢查是否達到2048for (let row = 0; row < GRID_SIZE; row++) {for (let col = 0; col < GRID_SIZE; col++) {if (grid[row][col] === 2048 && !gameWon) {gameWon = true;messageText.textContent = '恭喜你贏了!';gameMessage.className = 'game-message game-won';}}}// 檢查是否有空格子for (let row = 0; row < GRID_SIZE; row++) {for (let col = 0; col < GRID_SIZE; col++) {if (grid[row][col] === 0) {return;}}}// 檢查是否可以移動for (let row = 0; row < GRID_SIZE; row++) {for (let col = 0; col < GRID_SIZE; col++) {const value = grid[row][col];// 檢查右側if (col < GRID_SIZE - 1 && grid[row][col + 1] === value) {return;}// 檢查下方if (row < GRID_SIZE - 1 && grid[row + 1][col] === value) {return;}}}// 如果沒有空格子且無法移動,游戲結束gameOver = true;messageText.textContent = '游戲結束!';gameMessage.className = 'game-message game-over';}// 更新分數function updateScore() {scoreDisplay.textContent = score;// 更新最高分if (score > bestScore) {bestScore = score;localStorage.setItem('bestScore', bestScore);}bestScoreDisplay.textContent = bestScore;}// 鍵盤控制document.addEventListener('keydown', (event) => {switch (event.key) {case 'ArrowUp':move('up');break;case 'ArrowDown':move('down');break;case 'ArrowLeft':move('left');break;case 'ArrowRight':move('right');break;}});// 觸摸控制let touchStartX, touchStartY;gridContainer.addEventListener('touchstart', (event) => {touchStartX = event.touches[0].clientX;touchStartY = event.touches[0].clientY;event.preventDefault();});gridContainer.addEventListener('touchmove', (event) => {event.preventDefault();});gridContainer.addEventListener('touchend', (event) => {if (!touchStartX || !touchStartY) return;const touchEndX = event.changedTouches[0].clientX;const touchEndY = event.changedTouches[0].clientY;const dx = touchEndX - touchStartX;const dy = touchEndY - touchStartY;// 確定主要移動方向if (Math.abs(dx) > Math.abs(dy)) {// 水平移動if (dx > 0) {move('right');} else {move('left');}} else {// 垂直移動if (dy > 0) {move('down');} else {move('up');}}// 重置觸摸起點touchStartX = null;touchStartY = null;});// 按鈕事件restartButton.addEventListener('click', initGame);keepPlayingButton.addEventListener('click', () => {gameMessage.className = 'game-message';});// 初始化游戲initGame();bestScoreDisplay.textContent = bestScore;});</script>
</body>
</html>

功能說明

  1. 游戲核心功能

    • 4x4網格布局
    • 方塊移動和合并邏輯
    • 隨機生成新方塊(90%概率生成2,10%概率生成4)
    • 分數計算(每次合并累加得分)
    • 最高分記錄(使用localStorage保存)
  2. 游戲狀態

    • 勝利條件:創建出2048方塊
    • 失敗條件:棋盤填滿且無法繼續合并
    • 游戲結束后可重新開始
  3. 控制方式

    • 鍵盤方向鍵(↑, ↓, ←, →)
    • 觸摸屏滑動操作(支持移動設備)
  4. UI設計

    • 響應式布局,適配不同屏幕尺寸
    • 不同數字的方塊有不同的顏色
    • 分數顯示和最高分記錄
    • 游戲狀態提示(勝利/失敗)

使用說明

  1. 使用鍵盤方向鍵或觸摸屏滑動來移動方塊
  2. 當兩個相同數字的方塊碰撞時,它們會合并成它們的和
  3. 每次移動后,會在空白位置隨機生成一個新的方塊(2或4)
  4. 游戲目標:創建出一個2048方塊
  5. 當無法再移動方塊時,游戲結束

這個2048小游戲包含了所有核心功能,界面美觀,操作流暢,適合在桌面和移動設備上使用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87902.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87902.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87902.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows VMWare Centos Docker部署Springboot + mybatis + MySql應用

前置文章 Windows VMWare Centos環境下安裝Docker并配置MySqlhttps://blog.csdn.net/u013224722/article/details/148928081 Windows VMWare Centos Docker部署Springboot應用https://blog.csdn.net/u013224722/article/details/148958480 Windows VMWare Centos Docker部署…

【科普】Cygwin與wsl與ssh連接ubuntu有什么區別?DIY機器人工房

Cygwin、WSL&#xff08;Windows Subsystem for Linux&#xff09;和通過 SSH 連接 Ubuntu 是三種在 Windows 環境下與類 Unix/Linux 系統交互的工具&#xff0c;但它們的本質、運行環境、功能范圍有顯著區別。以下從核心定義、關鍵差異和適用場景三個維度詳細說明&#xff1a;…

Web前端數據可視化:ECharts高效數據展示完全指南

Web前端數據可視化&#xff1a;ECharts高效數據展示完全指南 當產品經理拿著一堆密密麻麻的Excel數據走向你時&#xff0c;你知道又到了"化腐朽為神奇"的時刻。數據可視化不僅僅是把數字變成圖表那么簡單&#xff0c;它是將復雜信息轉化為直觀洞察的藝術。 在過去兩…

# IS-IS 協議 | LSP 傳輸與鏈路狀態數據庫同步機制

略作整理&#xff0c;待校。 SRM 和 SSN 標志的作用 SRM 標志 功能&#xff1a;SRM 標志用于跟蹤路由器從一個接口向鄰居發送鏈路狀態協議數據單元&#xff08;LSP&#xff09;的狀態。作用&#xff1a;確保 LSP 的正確傳輸和狀態跟蹤。 SSN 標志 廣播網絡 功能&#xff1…

Windows DOS CMD 100

1. systeminfo&#xff1a;顯示系統詳細信息&#xff08;安裝日期/補丁/內存等&#xff09; 2. sfc /scannow&#xff1a;掃描并修復系統文件損壞 [管理員] 3. chkdsk /f&#xff1a;檢查磁盤錯誤并修復&#xff08;需重啟&#xff09; [管理員] 4. cleanmgr&#xff1a;啟動…

HTML初學者第三天

<1>文檔類型聲明標簽——<!DOCTYPE><!DOCTYPE>文檔聲明&#xff0c;作用是告訴瀏覽器使用哪種HTML版本來顯示網頁。<!DOCTYPE html>這句代碼的意思是&#xff1a;當前頁面采用的是HTML5版本來顯示網頁。注意&#xff1a;-<!DOCTYPE>聲明位于文檔…

學車筆記6

“不踩離合利用發動機制動”是指在駕駛過程中&#xff0c;駕駛員抬起油門踏板&#xff0c;但不踩下離合器踏板&#xff0c;利用發動機自身的阻力來減緩車輛速度的一種制動方式。具體介紹如下&#xff1a; #### 原理 - **動力傳遞反向**&#xff1a;正常情況下&#xff0c;發動…

人體坐姿檢測系統項目教程(YOLO11+PyTorch+可視化)

&#x1f4a1;本文主要內容&#xff1a;本項目基于YOLO11深度學習目標檢測算法&#xff0c;設計并實現了一個人體坐姿檢測系統。系統能夠自動識別圖像或視頻中的多種坐姿類型&#xff08;如&#xff1a;正常坐姿、不良坐姿等&#xff09;&#xff0c;為健康監測、智能教室、辦公…

服務網格可觀測性深度實踐與創新優化

主題&#xff1a;突破服務網格監控瓶頸——基于eBPF的無侵入式全鏈路可觀測性實踐 技術領域&#xff1a;云原生/微服務/服務網格&#xff08;Service Mesh&#xff09; 一、問題背景&#xff1a;傳統服務網格監控的痛點 在Istio、Linkerd等服務網格架構中&#xff0c;可觀測…

微信小程序41~50

1.列表渲染-進階用法 如果要對默認的變量名和下標進行修改&#xff0c;可以使用wx:for-item和wx:for-index wx:for-item可以指定數組當前元素的變量名 wx:for-index可以指定數組當前下標的變量名將wx:for用在標簽上&#xff0c;以渲染一個包含多個節點的結構快 并不是一個組件…

向量數據庫-Milvus快速入門

Milvus 概述 向量是神經網絡模型的輸出數據格式&#xff0c;可以有效地對信息進行編碼&#xff0c;在知識庫、語義搜索、檢索增強生成&#xff08;RAG&#xff09;等人工智能應用中發揮著舉足輕重的作用。 Milvus 是一個開源的向量數據庫&#xff0c;適合各種規模的人…

uniapp的光標跟隨和打字機效果

1、準備好容器文字的顯示textRef&#xff0c;以及光標的顯示 &#xff0c;使用transform-translate對光標進行移動到文字后面<template><view class"container" ref"contentRef"><u-parse :content"nodeText" ref"textRef&q…

「ECG信號處理——(21)基于Pan-Tompkins和隨機森林(RF)的睡眠呼吸暫停檢測算法」2025年7月4日

目錄 1、引言 2、數據庫介紹&#xff08;Apnea-ECG Database) 3、基于Pan-Tompkins和隨機森林&#xff08;RF&#xff09;的睡眠呼吸暫停檢測算法 3.1 算法概述 3.2 心電信號預處理及QRS波檢測算法 3.3 心電信號的隨機森林睡眠呼吸暫停識別 4、實驗結果 4.1 心電信號預處理及QR…

C++學習之STL學習:list的模擬實現

在上一篇學習了list的使用后&#xff0c;在本篇我們將通過模擬實現的方式深入了解list的底層運作原理。 作者的個人gitee&#xff1a;樓田莉子 (riko-lou-tian) - Gitee.com 感興趣的讀者可以看一看 目錄 前置準備 結點的定義 鏈表類的定義 迭代器 普通迭代器 const迭代器 …

不引入變量 異或交換的缺點

文章目錄選擇排序正確代碼交換兩個數位置的方法引入中間變量不引入中間變量&#xff0c;使用異或的方法錯誤原因優化代碼選擇排序正確代碼 // 數組中交換i和j位置的數public static void swap(int[] arr, int i, int j) {int tmp arr[i];arr[i] arr[j];arr[j] tmp;}// 選擇排…

VS Code中使用Git的方法:環境配置與Git操作

本文介紹在Windows電腦的VS Code中&#xff0c;配置Git環境并使用Git命令、功能的方法。 1 環境部署 首先&#xff0c;我們需要分別安裝Git環境與VS Code軟件。這里需要注意&#xff0c;即使是在VS Code中使用Git&#xff0c;也需要我們首先在電腦上單獨配置好Git的環境&#…

在 Windows 上安裝和運行 Apache Kafka

Apache Kafka是一款開源應用程序&#xff0c;用于實時處理海量數據流。Apache Kafka 是一個發布-訂閱消息系統。消息系統允許您在進程、應用程序和服務器之間發送消息。廣義上講&#xff0c;Apache Kafka 是一款可以定義主題并進行進一步處理的軟件。 下載和安裝 Apache Kafk…

【嵌入式電機控制#8】編碼器測速實戰

一、編碼器測速重要參數有刷電機編碼器參數&#xff08;其他的后面會慢慢提及&#xff0c;也可以在某寶看&#xff09;1. 編碼器分辨率&#xff08;PPR&#xff09;2. 編碼器工作電壓 3. 電機減速比 例如 30&#xff1a;1 指的就是電機減速軸轉1圈&#xff0c;編碼器轉30圈。注…

在C#中,可以不實例化一個類而直接調用其靜態字段

這是因為靜態成員&#xff08;static members&#xff09;屬于類本身&#xff0c;而不是類的實例。這是靜態成員的核心特性1. 靜態成員屬于類&#xff0c;而非實例當用static關鍵字修飾字段、方法或屬性時&#xff0c;這些成員會綁定到類級別&#xff0c;而不是實例級別。它們在…

Win11 安裝 Visual Studio(保姆教程 - 更新至2025.07)

Visual Studio 安裝&#xff08;保姆教程 - 更新至2025.07&#xff09; 前言安裝須知安裝過程1. 下載安裝包2. 安裝3. 注冊4. 創建桌面快捷方式 前言 本教程針對 非計算機相關專業的小白用戶 &#xff0c;手把手教你如何基于 win11 操作系統 安裝 Visual Studio 2022。安裝搭載…