HTML+CSS+JavaScript实现2048小游戏
相信很多人都玩过2048小游戏,规则易懂、操作简单,我曾经也“痴迷”于它,不到2048不罢休,最高成绩合成了4096,现在正好拿它来练练手。
我对于2048的实现,除了使用了现有2048小游戏的配色,其它所有的代码都是自己写的,尤其是上下左右移动时的逻辑部分,耗费了主要精力。
在草稿纸上设计、思考逻辑:

HTML:4x4的棋盘,上下左右方向键,开始新游戏,分数
<div class="wrapper">
<div class="square" id="s11"></div>
<div class="square" id="s12"></div>
<div class="square" id="s13"></div>
<div class="square" id="s14"></div>
<div class="square" id="s21"></div>
<div class="square" id="s22"></div>
<div class="square" id="s23"></div>
<div class="square" id="s24"></div>
<div class="square" id="s31"></div>
<div class="square" id="s32"></div>
<div class="square" id="s33"></div>
<div class="square" id="s34"></div>
<div class="square" id="s41"></div>
<div class="square" id="s42"></div>
<div class="square" id="s43"></div>
<div class="square" id="s44"></div>
<button class="direction" id="up" onclick="up()">↑</button>
<button class="direction" id="down" onclick="down()">↓</button>
<button class="direction" id="left" onclick="left()">←</button>
<button class="direction" id="right" onclick="right()">→</button>
<button id="new_game" onclick="new_game()">新游戏</button>
<div id="score"></div>
<div id="game_over">游戏结束!</div>
</div>
CSS:棋盘块配色使用了现有2048配色
<style type="text/css">
.wrapper {
width: 420px;
height: 420px;
background-color: #C3C0B7;
margin: 0 auto;
border-radius: 15px;
position: relative;
}
.square {
float: left;
width: 90px;
height: 90px;
margin: 7.5px;
background-color:#FBEFE3;
border-radius: 7.5px;
color: #59503F;
text-align: center;
line-height: 90px;
font-size: 35px;
}
.direction {
width: 120px;
height: 75px;
border: none;
border-radius: 7.5px;
color: white;
background-color: #C6BFB9;
font-size: 45px;
font-weight: bolder;
line-height: 75px;
}
#new_game {
width: 120px;
height: 75px;
border: none;
border-radius: 15px;
background-color: #C6BFB9;
font-size: 30px;
color: #FFFBF7;
position: absolute;
top:430px;
left: 0px;
}
#up {
position: absolute;
top:430px;
left:150px;
}
#left {
position: absolute;
top:512px;
left:0px;
}
#right {
position: absolute;
top:512px;
left:300px;
}
#down {
position: absolute;
top:512px;
left:150px;
}
#game_over {
width: 300px;
height: 100px;
color: #FFFFFF;
border-radius:20px ;
background-color: burlywood;
font-size: 40px;
position: absolute;
top: 160px;
left: 60px;
text-align: center;
line-height: 100px;
visibility: hidden;
}
#score {
width: 120px;
height: 75px;
border-radius: 15px;
background-color: #C6BFB9;
font-size: 20px;
color: #FFFBF7;
position: absolute;
top:430px;
left: 300px;
text-align: center;
line-height: 75px;
}
</style>
JavaScript:包括标记变量,新游戏加载函数,新数字生成函数,键盘事件绑定控制方向,以及最重要的各个方向的逻辑函数,具体的算法就不描述了,代码通俗易懂。
<script type="text/javascript">
var can_up = true; //可向上移动
var can_down = true; //可向下移动
var can_left = true; //可向左移动
var can_right = true; //可向右移动
//游戏结束
function game_over() {
if(!can_up&&!can_down&&!can_left&&!can_right) {
document.getElementById("game_over").style.visibility = "visible";
}
}
//开始新游戏
function new_game() {
document.getElementById("game_over").style.visibility = "hidden";
for(var i = 1;i < 5;i++) {
for(var j = 1;j < 5;j++) {
document.getElementById("s"+i+j).innerHTML = "";
}
}
born();
can_up = false;
can_down = false;
can_left = false;
can_right = false;
}
//键盘监听
document.onkeydown = function(event) {
switch(event.keyCode) {
case 37: left();break;
case 38: up();break;
case 39: right();break;
case 40: down();break;
default: ;
}
}
//生成新数字2或者4
function born() {
var rand_num = Math.random();
var new_num = (rand_num>0.5)?2:4;
while(true) {
var row = Math.ceil(Math.random()*4);
var col = Math.ceil(Math.random()*4);
var square = document.getElementById("s"+row+col);
if(square.innerHTML =="") {
square.innerHTML = new_num;
break;
}
}
}
//向上移动
function up() {
var new_square_num = [];
var target_square ;
var target_exist= false;
for(var i =1;i < 5;i++) {
for(var j = 2;j < 5;j++) {
var self_square = document.getElementById("s"+j+i);
if(self_square.innerHTML!="") {
for(var k =1;k < j;k++) {
var pre_square = document.getElementById("s"+(j-k)+i);
if(pre_square.innerHTML=="") {
target_square = pre_square ;
target_exist = true;
}
else if(self_square.innerHTML == pre_square.innerHTML && new_square_num[+((j-k).toString()+i)]==undefined ){
pre_square.innerHTML = 2*self_square.innerHTML;
document.getElementById("score").innerHTML = +(document.getElementById("score").innerHTML) + (+pre_square.innerHTML);
self_square.innerHTML = "";
new_square_num[+((j-k).toString()+i)] = 1;
can_up = true;
}
else {
break;
}
}
if(target_exist) {
target_square.innerHTML = self_square.innerHTML;
self_square.innerHTML = "";
can_up = true;
target_exist = false;
}
}
}
new_square_num = [];
}
if(can_up) {
born();
can_up = false;
} }
//向下移动
function down() {
var new_square_num = [];
var target_square ;
var target_exist= false;
for(var i =1;i < 5;i++) {
for(var j = 3;j > 0;j--) {
var self_square = document.getElementById("s"+j+i);
if(self_square.innerHTML!="") {
for(var k =j+1;k < 5;k++) {
var pre_square = document.getElementById("s"+k+i);
if(pre_square.innerHTML=="") {
target_square = pre_square ;
target_exist = true;
}
else if(self_square.innerHTML == pre_square.innerHTML && new_square_num[+((k).toString()+i)]==undefined ){
pre_square.innerHTML = 2*self_square.innerHTML;
document.getElementById("score").innerHTML = +(document.getElementById("score").innerHTML) + (+pre_square.innerHTML);
self_square.innerHTML = "";
new_square_num[+((k).toString()+i)] = 1;
can_down = true;
target_exist = false;
}
else {
break;
}
}
if(target_exist) {
target_square.innerHTML = self_square.innerHTML;
self_square.innerHTML = "";
can_down = true;
target_exist = false;
}
}
}
new_square_num = [];
}
if(can_down) {
born();
can_down = false;
}
}
//向左移动
function left() {
var new_square_num = [];
var target_square ;
var target_exist= false;
for(var j =1;j < 5;j++) {
for(var i = 2;i < 5;i++) {
var self_square = document.getElementById("s"+j+i);
if(self_square.innerHTML!="") {
for(var k =1;k < i;k++) {
var pre_square = document.getElementById("s"+j+(i-k));
if(pre_square.innerHTML=="") {
target_square = pre_square ;
target_exist = true;
}
else if(self_square.innerHTML == pre_square.innerHTML && new_square_num[+(j+(i-k).toString())]==undefined ){
pre_square.innerHTML = 2*self_square.innerHTML;
document.getElementById("score").innerHTML = +(document.getElementById("score").innerHTML) + (+pre_square.innerHTML);
self_square.innerHTML = "";
new_square_num[+(j+(i-k).toString())] = 1;
can_left = true;
target_exist = false;
}
else {
break;
}
}
if(target_exist) {
target_square.innerHTML = self_square.innerHTML;
self_square.innerHTML = "";
can_left = true;
target_exist = false;
}
}
}
new_square_num = [];
}
if(can_left) {
born();
can_left = false;
}
}
//向右移动
function right() {
var new_square_num = [];
var target_square ;
var target_exist= false;
for(var j =1;j < 5;j++) {
for(var i = 3;i > 0;i--) {
var self_square = document.getElementById("s"+j+i);
if(self_square.innerHTML!="") {
for(var k =i+1;k < 5;k++) {
var pre_square = document.getElementById("s"+j+k);
if(pre_square.innerHTML=="") {
target_square = pre_square ;
target_exist = true;
}
else if(self_square.innerHTML == pre_square.innerHTML && new_square_num[+(j.toString()+k)]==undefined ){
pre_square.innerHTML = 2*self_square.innerHTML;
document.getElementById("score").innerHTML = +(document.getElementById("score").innerHTML) + (+pre_square.innerHTML);
self_square.innerHTML = "";
new_square_num[+(j.toString()+k)] = 1;
can_right = true;
target_exist = false;
}
else {
break;
}
}
if(target_exist) {
target_square.innerHTML = self_square.innerHTML;
self_square.innerHTML = "";
can_right = true;
target_exist = false;
}
}
}
new_square_num = [];
}
if(can_right) {
born();
can_right = false;
}
}
//涂色
setInterval(function paint() {
for(var i = 1;i < 5;i++) {
for(var j = 1;j < 5;j++) {
var square = document.getElementById("s"+i+j);
switch(square.innerHTML) {
case "2" :square.style.backgroundColor = "#EEE4DA";
square.style.color = "#766D64";
break;
case "4" :square.style.backgroundColor = "#ECE0C8";
square.style.color = "#786D67";
break;
case "8" :square.style.backgroundColor = "#F2B179";
square.style.color = "#F6F7F2";
break;
case "16" :square.style.backgroundColor = "#F59565";
square.style.color = "#FAF6F5";
break;
case "32" :square.style.backgroundColor = "#F77B5F";
square.style.color = "#FBF3F0";
break;
case "64" :square.style.backgroundColor = "#F35F3B";
square.style.color = "#FAF4F4";
break;
case "128" :square.style.backgroundColor = "#EDCE71";
square.style.color = "#F8FAF7";
break;
case "256" :square.style.backgroundColor = "#EDCC61";
square.style.color = "#FAF6F7";
break;
case "512" :square.style.backgroundColor = "#ECC850";
square.style.color = "#FAF4F6";
break;
case "1024" :square.style.backgroundColor = "#EDC53F";
square.style.color = "#F9F4FA";
break;
case "2048" :square.style.backgroundColor = "#E9B501";
square.style.color = "#FFFCB0";
break;
case "4096" :square.style.backgroundColor = "#FCEDD8";
square.style.color = "#524B39";
break;
default:square.style.backgroundColor = "#FBEFE3";
}
}
}
},10); </script>
效果图:

虽然小游戏简单,但是实现了也是自己的成果,也是一种进步!
HTML+CSS+JavaScript实现2048小游戏的更多相关文章
- 【2048小游戏】——CSS/原生js爬坑之纯CSS模态对话框&游戏结束
引言:2048小游戏的结束界面,使用纯CSS制作模态对话框,一般做模态对话框都会使用BootStrap自带的模态对话框组件方便使用,但在制作要运行在移动端的小项目时,就不能使用BootStrap,因为 ...
- jQuery实践-网页版2048小游戏
▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...
- js、jQuery实现2048小游戏
2048小游戏 一.游戏简介: 2048是一款休闲益智类的数字叠加小游戏 二. 游戏玩法: 在4*4的16宫格中,您可以选择上.下.左.右四个方向进行操作,数字会按方向移动,相邻的两个数字相同就会合 ...
- 使用JS实现2048小游戏
JS实现2048小游戏源码 效果图: 代码如下,复制即可使用: (适用浏览器:360.FireFox.Chrome.Opera.傲游.搜狗.世界之窗. 不支持Safari.IE8及以下浏览器.) &l ...
- 基于jQuery的2048小游戏设计(网页版)
上周模仿一个2048小游戏,总结一下自己在编写代码的时候遇到的一些坑. 游戏规则:省略,我想大部分人都玩过,不写了 源码地址:https://github.com/xinhua6/2048game.g ...
- 【2048小游戏】——原生js爬坑之遍历算法显示二维数组内容
引言:做2048小游戏会将横纵方向的数字内容,存储在一个二维数组中,要将这个二维数组中的内容显示在页面上,就一定要用遍历算法来实现了. 一.二维数组存储 首先考虑用二维数组存储所有行数,列数 ...
- C# 开发2048小游戏
这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的 ...
- Swift实战之2048小游戏
上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完 ...
- 如何在CentOS上安装一个2048小游戏
如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...
随机推荐
- Paxos算法原理
1.从ACID到CAP 我们知道传统集中式系统中实现ACID是很简单的,在分布式环境中,涉及到不同的节点,节点内的ACID可以控制,那么节点间的ACID如何控制呢?构建一个可用性和一致性的分布系统成为 ...
- 一文速览Vue全栈
一文速览Vue全栈 原创: 新哥Lewis 天道酬勤Lewis 7月7日 Vue 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用,专注于声明式渲染视图 ...
- Tomcat源码分析 (四)----- Pipeline和Valve
在 Tomcat源码分析 (二)----- Tomcat整体架构及组件 中我们简单分析了一下Pipeline和Valve,并给出了整体的结构图.而这一节,我们将详细分析Tomcat里面的源码. Val ...
- Java 在spring cloud中使用Redis,spring boot同样适用
1.本地安装redis服务,官网下载. 2.在开发中要使用redis,首先要启动本地redis服务,启动后页面如下: 3.在spring boot项目pom.xml文件中添加Redis需要的依赖包,可 ...
- 2017版 Jetbrains 系列软件激活方法
1. 到网站 http://idea.lanyus.com/ 获取注册码. 2.填入下面的license server: http://intellij.mandroid.cn/ http://ide ...
- 图灵学院Java架构师-VIP-【性能调优-Mysql索引数据结构详解与索引优化】
最近报名了图灵学院的架构专题的付费课程,没有赶上6月份开课,中途加入的.错过了多线程的直播课程,只能看录播了
- python 22 类与对象
目录 1. 从空间角度研究类 1.1 添加对象的属性: 1.2 添加类的属性: 1.3 类与对象的关系: 2. 类与类直接的关系 2.1 类与类的关系: 2.2 依赖关系 -- 主从之分 2.3 组合 ...
- 从0系统学Android-2.5更多隐式Intent用法
本系列文章,参考<第一行代码>,作为个人笔记 更多内容:更多精品文章分类 从0系统学Android-2.5更多隐式Intent用法 上一节中我们学习了通过隐式 Intent 来启动 Act ...
- Oracle - SQL语句实现数据库快速检索
SQL语句实现数据库快速检索 有时候在数据库Debug过程中,需要快速查找某个关键字. 1:使用PLSQL Dev自带的查找数据库对象,进行对象查找 缺点:查找慢.耗时. 2:使用SQL语句对数据库对 ...
- 【StyleCop】StyleCop规则汇总
所有规则的翻译(基于版本4.7.44.0): 文档规则 1.SA1600:ElementsMustBeDocumented元素必须添加注释 2.SA1601: PartialElementsMustB ...