HTML2048小游戏
源代码在效果图后面
效果图

源代码
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>2048 Game</title><style>body {margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background: #f7f7f7;font-family: Arial, sans-serif;}.game-container {width: 400px;height: 400px;background: #fff;border-radius: 10px;overflow: hidden;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);}.tile {width: 25%;height: 25%;box-sizing: border-box;position: relative;background: #fff;border: 1px solid #eaeaea;margin: 0;float: left;text-align: center;line-height: 100px;font-size: 48px;color: #776e65;border-radius: 10px;transition: transform 0.2s;}.tile:after {content: '';display: block;padding-top: 100%;}.tile.new {animation: slideIn 0.5s;}.tile.tile-2 {background: #eee4da;}.tile.tile-4 {background: #ede0c8;}.tile.tile-8 {background: #f2b47b;}.tile.tile-16 {background: #f59563;}.tile.tile-32 {background: #f67c5f;}.tile.tile-64 {background: #f65e3b;}.tile.tile-128 {background: #edcf72;}.tile.tile-256 {background: #edcc61;}.tile.tile-512 {background: #edc850;}.tile.tile-1024 {background: #edc53f;}.tile.tile-2048 {background: #edc22e;}@keyframes slideIn {0% {transform: translate(-50%, -50%) rotate(90deg);}100% {transform: translate(-50%, -50%) rotate(0deg);}}</style>
</head><body><div class="game-container" id="game-container"></div><div style="margin-top: 20px;"><button onclick="moveUp()">上</button><button onclick="moveDown()">下</button><button onclick="moveLeft()">左</button><button onclick="moveRight()">右</button></div><script>const container = document.getElementById('game-container');let grid = [];let score = 0;function createGrid() {for (let i = 0; i < 4; i++) {const row = [];for (let j = 0; j < 4; j++) {const tile = document.createElement('div');tile.classList.add('tile');tile.dataset.row = i;tile.dataset.col = j;container.appendChild(tile);row.push(tile);}grid.push(row);}}function addRandomTile() {const emptyCells = [];grid.forEach((row, rowIndex) => {row.forEach((tile, colIndex) => {if (!tile.classList.contains('tile-2') &&!tile.classList.contains('tile-4') &&!tile.classList.contains('tile-8') &&!tile.classList.contains('tile-16') &&!tile.classList.contains('tile-32') &&!tile.classList.contains('tile-64') &&!tile.classList.contains('tile-128') &&!tile.classList.contains('tile-256') &&!tile.classList.contains('tile-512') &&!tile.classList.contains('tile-1024') &&!tile.classList.contains('tile-2048')) {emptyCells.push({ row: rowIndex, col: colIndex });}});});if (emptyCells.length) {const randomIndex = Math.floor(Math.random() * emptyCells.length);const cell = emptyCells[randomIndex];const value = Math.random() > 0.5? 2 : 4;addTile(cell.row, cell.col, value);}}function addTile(row, col, value) {const tile = grid[row][col];tile.classList.add(`tile-${value}`);tile.textContent = value;}function removeTile(row, col) {const tile = grid[row][col];tile.classList.remove('tile-2', 'tile-4', 'tile-8', 'tile-16', 'tile-32', 'tile-64', 'tile-128', 'tile-256', 'tile-512', 'tile-1024', 'tile-2048');tile.textContent = '';}function moveUp() {for (let col = 0; col < 4; col++) {let merged = false;let newRow = [];for (let row = 0; row < 4; row++) {const tile = grid[row][col];if (tile.textContent === '') continue;let currentValue = parseInt(tile.textContent);if (newRow.length === 0) {newRow.push(currentValue);} else {const lastValue = newRow[newRow.length - 1];if (lastValue === currentValue &&!merged) {newRow[newRow.length - 1] = currentValue * 2;score += currentValue * 2;merged = true;} else {newRow.push(currentValue);merged = false;}}}for (let row = 0; row < 4; row++) {if (row < newRow.length) {addTile(row, col, newRow[row]);} else {removeTile(row, col);}}}addRandomTile();}function moveDown() {for (let col = 0; col < 4; col++) {let merged = false;let newRow = [];for (let row = 3; row >= 0; row--) {const tile = grid[row][col];if (tile.textContent === '') continue;let currentValue = parseInt(tile.textContent);if (newRow.length === 0) {newRow.push(currentValue);} else {const lastValue = newRow[newRow.length - 1];if (lastValue === currentValue &&!merged) {newRow[newRow.length - 1] = currentValue * 2;score += currentValue * 2;merged = true;} else {newRow.push(currentValue);merged = false;}}}for (let row = 3; row >= 0; row--) {if (3 - row < newRow.length) {addTile(row, col, newRow[3 - row]);} else {removeTile(row, col);}}}addRandomTile();}function moveLeft() {for (let row = 0; row < 4; row++) {let merged = false;let newCol = [];for (let col = 0; col < 4; col++) {const tile = grid[row][col];if (tile.textContent === '') continue;let currentValue = parseInt(tile.textContent);if (newCol.length === 0) {newCol.push(currentValue);} else {const lastValue = newCol[newCol.length - 1];if (lastValue === currentValue &&!merged) {newCol[newCol.length - 1] = currentValue * 2;score += currentValue * 2;merged = true;} else {newCol.push(currentValue);merged = false;}}}for (let col = 0; col < 4; col++) {if (col < newCol.length) {addTile(row, col, newCol[col]);} else {removeTile(row, col);}}}addRandomTile();}function moveRight() {for (let row = 0; row < 4; row++) {let merged = false;let newCol = [];for (let col = 3; col >= 0; col--) {const tile = grid[row][col];if (tile.textContent === '') continue;let currentValue = parseInt(tile.textContent);if (newCol.length === 0) {newCol.push(currentValue);} else {const lastValue = newCol[newCol.length - 1];if (lastValue === currentValue &&!merged) {newCol[newCol.length - 1] = currentValue * 2;score += currentValue * 2;merged = true;} else {newCol.push(currentValue);merged = false;}}}for (let col = 3; col >= 0; col--) {if (3 - col < newCol.length) {addTile(row, col, newCol[3 - col]);} else {removeTile(row, col);}}}addRandomTile();}function checkGameEnd() {// 检查是否无法再进行移动let canMove = false;for (let row = 0; row < 4; row++) {for (let col = 0; col < 4; col++) {const tile = grid[row][col];if (tile.textContent === '') {canMove = true;break;}if (row > 0 && parseInt(grid[row - 1][col].textContent) === parseInt(tile.textContent)) {canMove = true;break;}if (row < 3 && parseInt(grid[row + 1][col].textContent) === parseInt(tile.textContent)) {canMove = true;break;}if (col > 0 && parseInt(grid[row][col - 1].textContent) === parseInt(tile.textContent)) {canMove = true;break;}if (col < 3 && parseInt(grid[row][col + 1].textContent) === parseInt(tile.textContent)) {canMove = true;break;}}if (canMove) break;}if (!canMove) {alert('游戏结束!你的得分是:' + score);}}document.addEventListener('keydown', (e) => {switch (e.key) {case 'ArrowUp':moveUp();break;case 'ArrowDown':moveDown();break;case 'ArrowLeft':moveLeft();break;case 'ArrowRight':moveRight();break;}});createGrid();addRandomTile();addRandomTile();</script>
</body></html>
相关文章:
HTML2048小游戏
源代码在效果图后面 效果图 源代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>2048 Game&l…...
为 android编译 luajit库、 交叉编译
时间:20200719 本机环境:iMac2017 macOS11.4 参考: 官方的文档:Use the NDK with other build systems 写在前边:交叉编译跟普通编译类似,无非是利用特殊的编译器、链接器生成动态或静态库; make 本质上是按照 Make…...
【音视频】音频重采样
文章目录 前言音频重采样的基本概念音频重采样的原因1. 设备兼容性2. 文件大小和带宽3. 音质优化4. 标准化和规范5. 多媒体同步6. 降低处理负载重采样的注意事项 总结 前言 音频重采样是指将音频文件的采样率转换成另一种采样率的过程。这在音频处理和传输中是一个常见且重要的…...
卷积神经网络学习问题总结
问题一: 深度学习中的损失函数和应用场景 回归任务: 均方误差函数(MSE)适用于回归任务,如预测房价、预测股票价格等。 import torch.nn as nn loss_fn nn.MSELoss() 分类任务: 交叉熵损失函数&…...
嵌入式面试总结
C语言中struct和union的区别 struct和union都是常见的复合结构。 结构体和联合体虽然都是由多个不同的数据类型成员组成的,但不同之处在于联合体中所有成员共用一块地址空间,即联合体只存放了一个被选中的成员,结构体中所有成员占用空间是累…...
超简单安装指定版本的clickhouse
超简单安装指定版本的clickhouse 命令执行shell脚本 idea连接 命令执行 参考官网 # 下载脚本 wget https://raw.githubusercontent.com/183461750/doc-record/d988dced891d70b23c153a3bbfecee67902a3757/middleware/data/clickhouse/clickhouse-install.sh # 执行安装脚本(中…...
FlowUs横向对比几款笔记应用的优势所在
FlowUs作为一个本土化的生产力工具,在中国市场的环境下相对于Notion有其独特的优势,尤其是在稳定性和模板适应性方面。 尽管Notion在笔记和生产力工具领域享有极高的声誉,拥有着诸多创新功能和强大的生态系统,但它并不一定适合每…...
收银系统源码-千呼新零售收银视频介绍
千呼新零售2.0系统是零售行业连锁店一体化收银系统,包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体,线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…...
从Catalog说到拜义父-《分析模式》漫谈11
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的Preface(前言)有这么一句: This book is thus a catalog, rather than a book to be read from cover to cover. 2004&am…...
Qt判定鼠标是否在该多边形的线条上
要判断鼠标是否在由QPainterPath或一系列QPointF点定义的多边形的线条上,你可以使用以下步骤: 获取鼠标当前位置:在鼠标事件中,使用QMouseEvent的pos()方法获取鼠标的当前位置。 检查点与线段的距离:遍历多边形的每条…...
【笔记:3D航路规划算法】一、随机搜索锚点(python实现,讲解思路)
目录 关键概念3D路径规划算法1. A*算法2. 快速随机锚点1. 初始化:2. 实例化搜索算法:3. 路径生成:4. 绘制图像: 3D路径规划是在三维空间中寻找从起点到终点的最短或最优路径的一种技术。它广泛应用于无人机导航、机器人运动规划、…...
ubuntu如何彻底卸载android studio?
最新版的ubuntu已经使用snap进行软件管理了,我用snap-store安装android studio以后,在安装plugin的时候强制退出后,直接再也进不去了,启动就报错。 先后进行了如下操作依然不行: 1 重装snap-store和android studio都…...
使用Windows Linux 子系统安装 Tensorflow,并使用GPU环境
在Microsoft Store商店安装Ubuntu 20.04 使用 nvidia-smi 命令查看GPU信息,查看支持的CUDA版本,这里最高支持11.7 安装cuda工具集 进入官网:CUDA Toolkit Archive | NVIDIA Developer,现在对应版本,点击 配置平台&…...
C++案例三:猜数字游戏
文章目录 介绍代码说明设置随机种子生成随机数猜测循环完整代码运行效果介绍 猜数字游戏是一个经典的编程练习,通过这个案例可以学习到基本的输入输出、随机数生成、条件判断和循环结构。 代码说明 设置随机种子 std::srand(static_cast<unsigned int>(std::time(nu…...
LNMP架构部署及应用
部署LNMP架构流程 1.安装Nginx(上传软件包,执行脚本) yum -y install pcre-devel zlib-devel gcc gcc useradd -M -s /sbin/nologin nginx tar zxf nginx-1.12.0.tar.gz cd nginx-1.12.0 ./configure --prefix/usr/local/nginx --usernginx…...
【医学影像】X86+FPGA:支持AI医学影像设备应用的工控主板,赋能CT、MRI、X线、超声等医学影像设备
支持AI医学影像设备应用的工控主板 在我国人口老龄化问题不断加剧,对影像诊断需求持续增长,和国家利好高端医学影像市场发展的系列法规和政策接连出台的大环境下,AI医学影像设备产业迎来发展黄金期。紧跟发展大势,基于12/13代 In…...
【PostgreSQL】PostgreSQL简史
博主介绍:✌全网粉丝20W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
Linux的热插拔UDEV机制和守护进程
目录 一、Linux的热插拔UDEV机制 二、守护进程 2.1 守护进程概念和基本特点: 2.2 显示进程信息: 2.3 守护进程和后台进程的区别: 2.4 创建守护进程的步骤和守护进程的特征: 2.4.1 创建守护进程的步骤: 2.4.2 守…...
laravel框架基础通识-新手
常用目录及其解析 routes 该目录为路由目录 一般根据api uri可以反向查找对应路由及其controller,目录下的文件名一般和url的第一级对应为了规范,然后根据根据里面具体分组和别名对应拼接对应路由url,后面对应的则是controller,…...
c++ extern 关键字
C中的extern关键字和跨语言互操作 变量的声明与定义 extern关键字用于声明在另一个翻译单元(文件)中定义的变量或函数。通过extern关键字,可以在多个文件中访问全局变量或函数。 变量声明示例 文件:main.cpp #include <io…...
从Kinect到奥比中光:为什么我的深度学习项目选了Gemini 2L?附Python SDK踩坑实录
从Kinect到奥比中光:为什么我的深度学习项目选了Gemini 2L?附Python SDK踩坑实录 深度视觉技术正在重塑人机交互的边界。当我的团队启动一个需要实时三维重建的农业机器人项目时,我们面临着一个关键抉择:在众多深度相机品牌中&…...
2026年AI大爆发:DeepSeek、Claude、Gemini三强鼎立,智能体应用成为新战场
进入2026年,AI领域迎来前所未有的激烈竞争格局。DeepSeek凭借极低的训练成本和开源策略强势出圈,R1模型在推理能力上直追GPT-o1,引发全球AI圈震动;Anthropic的Claude 3.7 Sonnet推出了扩展思考模式,在代码和复杂推理任…...
南京四季旅游攻略:最美时节去最美地方
南京四季旅游攻略:最美时节去最美地方 🌸🍃🍂❄️本文作者:南京码农 发布日期:2026年3月26日 关键词:南京旅游、四季景点、旅游攻略、南京必去、季节推荐前言:南京,一座四…...
解锁Navicat密码:突破加密限制的开源解密工具
解锁Navicat密码:突破加密限制的开源解密工具 【免费下载链接】navicat_password_decrypt 忘记navicat密码时,此工具可以帮您查看密码 项目地址: https://gitcode.com/gh_mirrors/na/navicat_password_decrypt 当数据库连接密码被Navicat加密保存却无法记起&…...
OpenClaw飞书机器人配置指南:百川2-13B-4bits量化模型对话触发
OpenClaw飞书机器人配置指南:百川2-13B-4bits量化模型对话触发 1. 为什么选择OpenClaw飞书百川2的组合? 去年我接手了一个小团队的日报自动化项目,需要每天收集5个成员的进度更新并生成汇总报告。最初尝试用Python脚本钉钉机器人࿰…...
【开题答辩全过程】以 基于大数据的智能推送系统设计与实现为例,包含答辩的问题和答案
个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…...
PyTorch 3.0静态图分布式训练源码分析窗口即将关闭:官方已标记torch.distributed._spmd模块为“实验性冻结”,2024 Q3后将移除调试钩子入口
第一章:PyTorch 3.0静态图分布式训练的演进背景与冻结决策动因PyTorch 3.0正式宣布冻结静态图(TorchScript)在分布式训练路径中的演进支持,这一决策并非技术倒退,而是基于多年大规模生产实践与生态协同的理性收敛。随着…...
线上年销 10 亿的背后:实体转型的 “线上 + 线下” 实战逻辑复盘
在行业的讨论声中,总有声音将某些日化品牌的崛起归类为 “资本运作” 或 “流量套路”。但实际上,深耕日化赛道近 20 年的顶俏,凭借 10 亿级的年销售额,为无数身处转型期的实体商家,提供了一份极具含金量的实战答卷。从…...
5个步骤掌握抖音批量下载高效解决方案:从需求到实战指南
5个步骤掌握抖音批量下载高效解决方案:从需求到实战指南 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在数字内容管理领域,短视频资源的高效获取已成为内容创作者、研究人员和普通用…...
QDKTAI实战面试题50问之41-50
一、逐题详细解析(41-50题)第41题:如何设计一个有效的AI内容审核系统?1. 考察重点对大模型“生成式而非判别式”核心特性的理解识别AI审核场景中的关键冲突点(长文本处理、语气/风格干扰)针对性解决方案的设…...
