相信很多人都玩过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. Java中的魔法类-Unsafe

    Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别.不安全操作的方法,如直接访问系统内存资源.自主管理内存资源等,这些方法在提升Java运行效率.增强Java语言底层资源操作能 ...

  2. 为何你还不懂得如何使用Python协程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  3. spark读取pg数据库报错操作符不存在

    代码: Properties connectionProperties = new Properties(); connectionProperties.put("user", C ...

  4. net core 3.0 之Grpc新特性小试牛刀

      相信微服务大家伙都有听说和知道,好处弊端咱也不多说了,Grpc算是一个比较全面的微服务框架,也得到微软的支持 总结下来就是,跨平台,可靠,通信快,扩展性强,网络消耗小,模板多语言通用 光说好处,没 ...

  5. C语言的输入

    %*2d%d 去掉前面两位 新旧函数 scanf和scanf_s 去掉安全检查 整型 scanf(“%d”,&x); scanf_s(“%d”,&x); 字符型 char ch; sc ...

  6. java 判断 string 转 integer 判断

    NumberUtils.isDigits("1") NumberUtils.isDigits("/") 根据返回 true false 再确定是否转换即可 需要 ...

  7. ASP.NET Core on K8S深入学习(7)Dashboard知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 在第二篇<部署过程解析与Dashboard>中介绍了如何部署Das ...

  8. Okhttp3源码解析(4)-拦截器与设计模式

    ### 前言 回顾: [Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [Okhttp3源码解析(1)-OkHttpClient分析](htt ...

  9. Vue中 父子传值 数据丢失问题

    在Vue中,父子组件传值,子组件通过props接收父组件传递的数据 父组件 questionList  : 传递数据参数 questionsLists: 传递数据源 子组件 porps 接收父组件方式 ...

  10. DNS域名解析服务及其配置

    一.背景 到 20 世纪 70 年代末,ARPAnet 是一个拥有几百台主机的很小很友好的网络.仅需要一个名为 HOSTS.TXT 的文件就能容纳所有需要了解的主机信息:它包含了所有连接到 ARPAn ...