相信很多人都玩过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小游戏的更多相关文章

  1. 【2048小游戏】——CSS/原生js爬坑之纯CSS模态对话框&游戏结束

    引言:2048小游戏的结束界面,使用纯CSS制作模态对话框,一般做模态对话框都会使用BootStrap自带的模态对话框组件方便使用,但在制作要运行在移动端的小项目时,就不能使用BootStrap,因为 ...

  2. jQuery实践-网页版2048小游戏

    ▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...

  3. js、jQuery实现2048小游戏

    2048小游戏 一.游戏简介:  2048是一款休闲益智类的数字叠加小游戏 二. 游戏玩法: 在4*4的16宫格中,您可以选择上.下.左.右四个方向进行操作,数字会按方向移动,相邻的两个数字相同就会合 ...

  4. 使用JS实现2048小游戏

    JS实现2048小游戏源码 效果图: 代码如下,复制即可使用: (适用浏览器:360.FireFox.Chrome.Opera.傲游.搜狗.世界之窗. 不支持Safari.IE8及以下浏览器.) &l ...

  5. 基于jQuery的2048小游戏设计(网页版)

    上周模仿一个2048小游戏,总结一下自己在编写代码的时候遇到的一些坑. 游戏规则:省略,我想大部分人都玩过,不写了 源码地址:https://github.com/xinhua6/2048game.g ...

  6. 【2048小游戏】——原生js爬坑之遍历算法显示二维数组内容

    引言:做2048小游戏会将横纵方向的数字内容,存储在一个二维数组中,要将这个二维数组中的内容显示在页面上,就一定要用遍历算法来实现了. 一.二维数组存储    首先考虑用二维数组存储所有行数,列数   ...

  7. C# 开发2048小游戏

    这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的 ...

  8. Swift实战之2048小游戏

    上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完 ...

  9. 如何在CentOS上安装一个2048小游戏

    如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...

随机推荐

  1. maven的不同版本下载及环境配置

    Maven不同版本下载及环境配置 Maven下载 去到官网 https://maven.apache.org/ 会发现是最新版本,但是一般下载的话,都会下载比最新的版本要低两到三个小版本的,这里就下载 ...

  2. netty源码解解析(4.0)-17 ChannelHandler: IdleStateHandler实现

    io.netty.handler.timeout.IdleStateHandler功能是监测Channel上read, write或者这两者的空闲状态.当Channel超过了指定的空闲时间时,这个Ha ...

  3. EXP查询合集提权后渗透必备

    0x00 整理的一些后渗透提权需要用到的一些漏洞,后渗透提权的时候可以看一下目标机那些补丁没打,再进行下一步渗透提权. 0x01 CVE-2019-0803 [An elevation of priv ...

  4. 中间件增强框架之InterceptFramework

    本文讲解MOF中的InterceptFramework框架.该框架可以在应用启动过程中获取画像信息,实现应用画像数据采集和存储. 一.前言 在智能运维中,应用服务所使用的组件及JAR包等相关信息非常重 ...

  5. Python模块之netmiko

    一.简介 此模块用于简化paramiko与网络设备之间的ssh连接,可在windows与Unix平台使用 二.目前支持的设备 (2019.03.07) Regularly tested Arista ...

  6. spring-boot-plus项目目录结构(六)

    spring-boot-plus项目目录结构 目录结构 bin:启动/重启命令脚本目录 logs:部署后记录日志目录 assembly:maven打包配置文件目录 java:源代码目录 resourc ...

  7. [WPF自定义控件库] 给WPF一个HyperlinkButton

    1. 在WPF怎么在UI上添加超级链接 这篇文章的目的是介绍怎么在WPF里创建自定义的HyperlinkButton控件.很神奇的,WPF居然连HyperlinkButton都没有,不过它提供了另一种 ...

  8. Selenium+java - 手把手一起搭建一个最简单自动化测试框架

    写在前面 我们刚开始做自动化测试,可能写的代码都是基于原生写的代码,看起来特别不美观,而且感觉特别生硬. 来看下面一段代码,如下图所示: 从上面图片代码来看,具体特征如下: driver对象在测试类中 ...

  9. Servlet Cookie、Session

    HTTP不能保持连接,可使用会话保存用户信息. 常用的会话技术有2种:Cookie.Session. Cookie 1.原理 当用户第一次访问某个网站时,服务器设置Cookie,存储用户信息,放在响应 ...

  10. java高并发系列 - 第31天:获取线程执行结果,这6种方法你都知道?

    这是java高并发系列第31篇. 环境:jdk1.8. java高并发系列已经学了不少东西了,本篇文章,我们用前面学的知识来实现一个需求: 在一个线程中需要获取其他线程的执行结果,能想到几种方式?各有 ...