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小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...
随机推荐
- as更新3.0.1的时候的编译异常
- XML简单了解一下
XML是一种纯文本文档.HTML,标记是已经被W3C规定好的,自己创建一个标签是不被允许的. XML现在的用途是用来存储数据.config文件就是个XML文档.XML是可以自定义的. 每一个XML文档 ...
- DataPipeline丨DataOps的组织架构与挑战
作者:DataPipeline CEO 陈诚 前两周,我们分别探讨了“数据的资产负债表与现状”及“DataOps理念与设计原则”.接下来,本文会在前两篇文章的基础上继续探讨由DataOps设计原则衍生 ...
- 002——Netty之Netty介绍
Netty出现背景 Java NIO难用 据说存在bug 业界其他NIO框架不成熟 Netty主要解决两个相应关注领域 (1)异步和事件驱动的实现. (2)一组设计模式,将应用逻辑与网络层解耦. 特性 ...
- java高并发系列 - 第27天:实战篇,接口性能成倍提升,让同事刮目相看,现学现用
这是java高并发系列第27篇文章. 开发环境:jdk1.8. 案例讲解 电商app都有用过吧,商品详情页,需要给他们提供一个接口获取商品相关信息: 商品基本信息(名称.价格.库存.会员价格等) 商品 ...
- Django Mysql数据库-F查询和Q查询
一.F查询和Q查询 F查询: 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢? Django 提供 F() 来做这样的比较.F() 的 ...
- 写论文的第二天 Hbase集群搭建
日志______2019.1.24 Hbase分布式搭建 注意:hbase的使用基于hadoop,开启以及关闭需要注意顺序,由于我是的是自带的zookeeper,说以开启关闭顺序应如下 启动:hado ...
- Nacos(四):SpringCloud项目中接入Nacos作为配置中心
前言 通过前两篇文章: Nacos(二):Nacos与OpenFeign的对接使用 Nacos(三):SpringCloud项目中接入Nacos作为注册中心 相信大家已经对Nacos作为注册中心的基本 ...
- python paramiko外部传参和内部调用命令的方法
学习了很久的python,但在工作中使用的时候,却发现不知道怎么传参进入到python中执行,所以这两天就研究 了python args怎么将外部参数传入到python中执行 1.首先使用python ...
- C++函数中,两个自动释放内存的动态内存申请类
最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if fr ...