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小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...
随机推荐
- elk系列教程:docker中安装配置elk
elasticSearch Docker安装elasticsearch: docker pull docker.io/elasticsearch:7.2.0 启动: docker run -p 920 ...
- apicloud 开发环境搭建
之前做过appcan 手机应用的开发,工作需要切换的apicloud , 开发环境的的搭建是开发的第一步,let's go 1新建应用 step1 注册账号 注册apicloud 账号:https ...
- 转载 | textarea 在浏览器中固定大小和禁止拖动
HTML 标签 textarea 在大部分浏览器中只要指定行(rows)和列(cols)属性,就可以规定 textarea 的尺寸,大小就不会改变,不过更好的办法是使用 CSS 的 height 和 ...
- Opengl_入门学习分享和记录_03_渲染管线(二)再谈顶点着色器以及顶点属性以及属性链接
---恢复内容开始--- 写在前面的废话:岂可修!感觉最近好忙啊,本来今天还有同学约我出去玩的.(小声bb) 正文开始:之前已经编译好的着色器中还有一些问题,比如 layout(location=0) ...
- python环境的安装 环境变量和系统变量
一.python 的安装 python 2.7 和 python 3.6的安装(一路点点点就行) 在安装的时候注意一下红框的内容,意思代表将其添加到环境变量中 环境变量是在操作系统中一个具有特定名字的 ...
- F#周报2019年第33期
新闻 宣告.NET Core 3.0预览版8 新的fable.io站点伴随着更多文档发布 正在努力使你的团队相信F#的益处?Compositional IT能够提供帮助 提名2019年度F#社区英雄 ...
- 如何在logback.xml中自定义动态属性
当使用logback来记录Web应用的日志时,我们通过在logback.xml中配置appender来指定日志输出格式及输出文件路径,这在一台主机或一个文件系统上部署单个实例没有问题,但是如果部署多个 ...
- Python 列表深浅复制详解
在文章<Python 数据类型>里边介绍了列表的用法,其中列表有个 copy() 方法,意思是复制一个相同的列表.例如 names = ["小明", "小红& ...
- POST提交数据方式
application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了.浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 app ...
- Liunx软件安装之JDK
在安装 jdk 之前我们需要先了解下 openjdk 跟 oracle jdk 的区别. OpenJDK 是 JDK 的开源码版本,以 GP L 协议的形式发布.在 JDK7 的时候,OpenJDK ...