2048小游戏项目总结
2048小游戏项目总结
最近有在玩2048,所以写了个2048的代码
话不多说,先上截图和代码
游戏截图
HTML代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1, minimum-scale=1.0, user-scalable=no"><title>2048小游戏</title><link rel="stylesheet" href="css/normalize.css"><link rel="stylesheet" href="css/style.css"><script src="js/2048.js" type="text/javascript" charset="utf-8"></script>
</head>
<body><div class="score"><div class="current-score"><strong>当前得分:</strong><span id="current-score">0</span></div><div class="most-score"><strong>最高得分:</strong><span id="most-score">0</span></div></div><div class="contain"><div class="line-1"><div id="cd-11" class="n0"></div><div id="cd-12" class="n0"></div><div id="cd-13" class="n0"></div><div id="cd-14" class="n0"></div></div><div class="line-2"><div id="cd-21" class="n0"></div><div id="cd-22" class="n0"></div><div id="cd-23" class="n0"></div><div id="cd-24" class="n0"></div></div><div class="line-3"><div id="cd-31"class="n0"></div><div id="cd-32"class="n0"></div><div id="cd-33"class="n0"></div><div id="cd-34"class="n0"></div></div><div class="line-4"><div id="cd-41" class="n0"></div><div id="cd-42" class="n0"></div><div id="cd-43" class="n0"></div><div id="cd-44" class="n0"></div></div></div><div class="controlButton"><input type="button" value="开始" id="start" onclick="start()"><input type="button" value="重新开始" id="newstart" disabled="disabled" onclick="newstart()"></div><div class="information"><p>温馨提示:该游戏在PC端通过键盘上的方向键进行,在移动端通过滑动屏幕进行!</p></div><div class="number"><div class="line-1"><div id="cd-00" class="n2 n0">2</div><div id="cd-01" class="n4 n0">4</div><div id="cd-02" class="n8 n0">8</div><div id="cd-03" class="n16 n0">16</div></div><div class="line-2"><div id="cd-10" class="n32 n0">32</div><div id="cd-11" class="n64 n0">64</div><div id="cd-12" class="n128 n0">128</div><div id="cd-13" class="n256 n0">256</div></div><div class="line-3"><div id="cd-20" class="n512 n0">512</div><div id="cd-21" class="n1024 n0">1024</div><div id="cd-22" class="n2048 n0">2048</div><div id="cd-23" class="n4096 n0">4096</div></div><div class="line-4"><div id="cd-30" class="n8192 n0">8192</div><div id="cd-31" class="n0"></div><div id="cd-32" class="n0"></div><div id="cd-33" class="n0"></div></div></div>
</body>
</html>
HTML代码中存在下方的代码是为了禁止该网页在移动端进行缩放操作(当然,安卓系统下的UC浏览器貌似不起作用)。其中,initial-scale表示初始缩放比例,maximum-scale表示允许最大的缩放比例,minimum-scale表示允许最小的缩放比例,user-scalable表示是否可手动缩放。一行代码解决手机浏览器禁止缩放的问题。
<meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1, minimum-scale=1.0, user-scalable=no">
CSS代码
.information {position: fixed;top: 30px;left: 50px;
}
.information p {color: red;width: 200px;line-height: 24px;
}
.score {font-size: 20px;margin: 30px auto 0; width: 400px;height: 8px;
}
.current-score,.most-score{width: 200px;float: left;text-align: center;
}
.current-score span {color: blue;
}
.most-score span {color: red;
}
.contain {clear: both;height: 400px;width: 400px;background-color: #ccc;margin: 40px auto 20px;padding: 5px;
}
.n0,.n2,.n4,.n8,.n16,.n32,.n64,.n128,.n256,.n512,.n1024,.n2048,.n4096,.n8192 {height: 90px;width: 90px;background-color: gray;float: left;margin: 5px;font-size: 30px;text-align: center;line-height: 90px;color: #fff;
}
.controlButton {width: 400px;height: 50px;margin: 0 auto;text-align: center;
}
#newstart {color: graytext;
}
/*设置每个数字的样式*/
.n2{background-color: #fff;color: black;}
.n4{background-color: #ede0c8;color: black;}
.n8{background-color: #f2b179;}
.n16{background-color: #f59563;}
.n32{background-color: #f67c5f;}
.n64{background-color: #f65e3b;}
.n128{background-color: #edcf72;}
.n256{background-color: #fec716;}
.n512{background-color: #ddc190;}
.n1024{background-color: #9f8963;}
.n2048{background-color: #cc8100;}
.n4096{background-color: #5d4d32;}
.n8192{background-color: #93c;}
.number{display: none;}
/*当屏幕宽度小于1080px时的样式*/
@media screen and (max-width: 1080px) {.information{position: relative;top: 0;left: 0;text-align: center;}.information p {width: auto;}
}
通过上方的css代码对游戏界面进行布局和配色,其中代码块
@media screen and (max-width: 1080px) {
………………
}
是响应式布局的css写法,表示当屏幕的宽度小于1080px时相应的样式
JS代码
var score,mostScore;
var c=[];
//初始化二维数组,0号,5号单位置为0
for(var i=0;i<=5;i++){c[i]=[];for(var j=0;j<=5;j++)c[i][j] = 0;
}
function start() {controlButton();//控制按钮的可用性score = mostScore = 0;//初始化分数//开始时随机生成两块randomDemo();randomDemo();
}function newstart() {if (confirm("确定要重新开始游戏吗?") == true) {// 将二维数组及当前分数清零for(var i=0;i<=5;i++){c[i]=[];for(var j=0;j<=5;j++){c[i][j] = 0;if(i>0&&j>0&&i<5&&j<5){document.getElementById("cd-"+i+j).innerText = "";document.getElementById("cd-"+i+j).className = "n0";}}}score = 0;document.getElementById("current-score").innerText = score;//重新随机生成两块randomDemo();randomDemo();}
}
//按钮的控制方法
function controlButton() {var s1 = document.getElementById("start");var ns = document.getElementById("newstart");//禁用开始按钮s1.setAttribute("disabled" ,"disabled");s1.style.color="graytext";//解禁重新开始按钮ns.removeAttribute("disabled");ns.style.color="inherit";
}
//随机生成方块
function randomDemo() {var randomnum,i,j;//随机产生坐标i = Math.floor(Math.random() * 4)+1;j = Math.floor(Math.random() * 4)+1;//生成新的方块if(c[i][j]==0){randomnum = Math.random()<0.75 ? 2:4;c[i][j] = randomnum;document.getElementById("cd-"+i+j).innerText = randomnum;document.getElementById("cd-"+i+j).className = "n"+randomnum;return true;}else return randomDemo();
}
//界面的更新方法
function update() {for(var i=1;i<=4;i++){for(var j=1;j<=4;j++){var pre = document.getElementById("cd-"+i+j);//当前对象if(c[i][j] != 0){pre.className = "n"+c[i][j];pre.innerText = c[i][j];}else {pre.className = "n0";pre.innerText = "";}}}
}
//判断是否可以左移
function canLeft() {for(var i=1;i<=4;i++){if(c[i][2]+c[i][3]+c[i][4]!=0){if(c[i][1]==0)return true;else if(c[i][2]==0)return true;else if(c[i][2]==c[i][1]||c[i][2]==c[i][3]||(c[i][4]!=0&&c[i][3]==c[i][4])||(c[i][3]==0&&c[i][4])!=0)return true;} }return false;
}
//判断是否可以右移
function canRight() {for(var i=1;i<=4;i++){if(c[i][2]+c[i][3]+c[i][1]!=0){if(c[i][4]==0)return true;else if(c[i][3]==0)return true;else if(c[i][3]==c[i][4]||c[i][3]==c[i][2]||(c[i][1]!=0&&c[i][1]==c[i][2])||(c[i][2]==0&&c[i][1])!=0)return true;}}return false;
}
//判断是否可以上移
function canUp() {for(var i=1;i<=4;i++){if(c[2][i]+c[3][i]+c[4][i]!=0){if(c[1][i]==0)return true;else if(c[2][i]==0)return true;else if(c[3][i]==0 && c[4][i]!=0)return true;else if((c[3][i]!=0&&c[3][i]==c[4][i])||c[3][i]==c[2][i]||(c[1][i]==c[2][i]))return true;}}return false;
}
//判断是否可以下移
function canDown() {for(var i=1;i<=4;i++){if(c[2][i]+c[3][i]+c[1][i]!=0){if(c[4][i]==0)return true;else if(c[3][i]==0)return true;else if(c[2][i]==0 && c[1][i]!=0)return true;else if((c[1][i]!=0&&c[1][i]==c[2][i])||c[3][i]==c[2][i]||(c[3][i]==c[4][i]))return true;} }return false;
}
//左移方法
function left() {var l = canLeft();for(var i=1;i<=4;i++){//1.先将一行内的元素以0为界排列好,如2020排成2200for(var j=4;j>1;j--){if(c[i][j-1] == 0){c[i][j-1]+=c[i][j];k=j;while(k<5){c[i][k] = c[i][k+1];k++;}}}//2.合并相同且相邻的方块并更新数组for(var j=1;j<4;j++){if(c[i][j]==c[i][j+1] && c[i][j]!=0){c[i][j]*=2;switch(c[i][j]){case 512:alert("恭喜您合并成512方块!");break;case 1024:alert("恭喜您合并成1024方块!");break;case 2048:alert("恭喜您合并成2048方块!");break;case 4096:alert("恭喜您合并成4096方块!");break;case 8192:alert("恭喜您合并成8192方块!");}score+=c[i][j];//更新分数document.getElementById("current-score").innerText = score;//判断是否破纪录if(score>mostScore){mostScore = score;document.getElementById("most-score").innerText = score;}k=j+1;//左移数组while(k<5){c[i][k] = c[i][k+1];k++;}}}}update();//更新界面//判断是否可以左移,能则生成方块if(l) randomDemo();
}
//右移方法
function right() {var r = canRight();for(var i=1;i<=4;i++){//1.先将一行内的元素以0为界排列好,如2020排成0022for(var j=1;j<4;j++){if(c[i][j+1] == 0){c[i][j+1]+=c[i][j];k=j;while(k>0){c[i][k] = c[i][k-1];k--;}}}//2.合并相同且相邻的方块并更新数组for(var j=4;j>0;j--){if(c[i][j]==c[i][j-1] && c[i][j]!=0){c[i][j]*=2;switch(c[i][j]){case 512:alert("恭喜您合并成512方块!");break;case 1024:alert("恭喜您合并成1024方块!");break;case 2048:alert("恭喜您合并成2048方块!");break;case 4096:alert("恭喜您合并成4096方块!");break;case 8192:alert("恭喜您合并成8192方块!");}score+=c[i][j];//更新分数document.getElementById("current-score").innerText = score;//判断是否破纪录if(score>mostScore){mostScore = score;document.getElementById("most-score").innerText = score;}k=j-1;//数组右移while(k>0){c[i][k] = c[i][k-1];k--;}}}}update();//更新界面//判断是否可以右移,能则生成方块if(r) randomDemo();
}
//上移方法
function up() {var u = canUp();for(var j=1;j<=4;j++){//1.先将一列内的元素以0为界排列好,如2202排成2220for(var i=4;i>1;i--){if(c[i-1][j] == 0){c[i-1][j]+=c[i][j];k=i;while(k<5){c[k][j] = c[k+1][j];k++;}}}//2.合并相同且相邻的方块并更新数组for(var i=1;i<4;i++){if(c[i][j]==c[i+1][j] && c[i][j]!=0){c[i][j]*=2;switch(c[i][j]){case 512:alert("恭喜您合并成512方块!");break;case 1024:alert("恭喜您合并成1024方块!");break;case 2048:alert("恭喜您合并成2048方块!");break;case 4096:alert("恭喜您合并成4096方块!");break;case 8192:alert("恭喜您合并成8192方块!");}score+=c[i][j];//更新分数document.getElementById("current-score").innerText = score;//判断是否破纪录if(score>mostScore){mostScore = score;document.getElementById("most-score").innerText = score;}k=i+1;//数组上移while(k<5){c[k][j] = c[k+1][j];k++;}}}}update();//更新界面//判断是否可以上移,能则生成方块if(u) randomDemo();
}
//下移方法
function down() {var d = canDown();for(var j=1;j<=4;j++){//1.先将一列内的元素以0为界排列好,如2202排成0222for(var i=1;i<4;i++){if(c[i+1][j] == 0){c[i+1][j]=c[i][j];k=i;while(k>0){c[k][j] = c[k-1][j];k--;}}}//2.合并相同且相邻的方块并更新数组for(var i=4;i>0;i--){if(c[i][j]==c[i-1][j] && c[i][j]!=0){c[i][j]*=2;switch(c[i][j]){case 512:alert("恭喜您合并成512方块!");break;case 1024:alert("恭喜您合并成1024方块!");break;case 2048:alert("恭喜您合并成2048方块!");break;case 4096:alert("恭喜您合并成4096方块!");break;case 8192:alert("恭喜您合并成8192方块!");}score+=c[i][j];//更新分数document.getElementById("current-score").innerText = score;//判断是否破纪录if(score>mostScore){mostScore = score;document.getElementById("most-score").innerText = score;}k=i-1;//数组下移while(k>0){c[k][j] = c[k-1][j];k--;}}}}update();//更新界面//判断是否可以下移,能则生成方块if(d) randomDemo();
}
//判断游戏是否结束,即上下左右都不能移动
function over() {if((!(canLeft()||canRight()||canUp()||canDown()))&&document.getElementById("start").disabled)alert("游戏结束,本局分数为"+score+",游戏的最高分数为"+mostScore);
}
//键盘事件的第一种写法
window.addEventListener("keydown",function(e) {if(e.keyCode == 37){e.preventDefault();left();over();}if(e.keyCode == 38){e.preventDefault();up();over();}if(e.keyCode == 39){e.preventDefault();right();over();}if(e.keyCode == 40){e.preventDefault();down();over();}
});
/*
//键盘事件的第二种写法
window.onkeydown = function (e) {if(e.keyCode == 37){e.preventDefault();left();over();}if(e.keyCode == 38){e.preventDefault();up();over();}if(e.keyCode == 39){e.preventDefault();right();over();}if(e.keyCode == 40){e.preventDefault();down();over();}
}*/
//监听移动设备的触摸开始
document.addEventListener('touchstart',function (event) {startx = event.touches[0].pageX;starty = event.touches[0].pageY;
});
//监听移动设备的触摸移动
document.addEventListener('touchmove',function (evnet) {event.preventDefault();
});
//监听移动设备的触摸结束
document.addEventListener('touchend',function (event) {endx = event.changedTouches[0].pageX;endy = event.changedTouches[0].pageY;var x = endx - startx;var y = endy - starty;//xif(Math.abs(x) > Math.abs(y)){if(x > 0){//向右移动if (canRight()){right();}over();} else {//向左移动if (canLeft()){left();}over();}} else if(Math.abs(x) < Math.abs(y)) { //yif (y < 0){//向上移动if (canUp()){up();}over();} else { //向下移动if (canDown()){down();}over();}}});
JS中,用一个二维数组来存放每个方块的数值,其中适当地留空了某些空间以备数组的移动和变化
- JS随机函数
代码 | 含义 |
---|---|
Math.random() | 表示返回【0,1)之间的随机数 |
Math.floor(Math.random()*10) | 表示返回0至9之间的整数 |
Math.floor(Math.random()*11) | 表示返回0至10之间的整数 |
合并方块的思路
(1)当想要往某个方向移动时,先判断是否可往该方向移动,可移动时先将一行(列)中的数组元素以0位界排列好,如当下移时,某列的元素分别是2202,则排列成0222;当右移时,某行的元素分别是2020,则排成0022。不可移动时不生成也不合并不移动方块。
(2)合并相同且相邻的方块并更新数组、分数和界面。
(3)判断往某个方向移动时是否可以再生成新的方块移动端JS触摸touch
(1) 4个监听事件
事件 | 触发时刻 |
---|---|
touchstart | 触摸屏幕上时触发 |
touchmove | 触摸屏幕中滑动时触发 |
touchend | 离开屏幕时触发 |
touchcancel | 系统取消触摸事件的时候触发 |
(2) 监听触摸后触摸事件会实现一个event对象,这个对象里面包括3个触摸函数列表。
函数 | 触发函数列表 |
---|---|
touches | 屏幕上所有手指列表 |
targetTouches | 在当前DOM标签上手指的列表 |
changedTouches | 涉及当前事件的手指的列表 |
(3)触摸函数的属性,用于获取坐标
属性 | 获取的坐标 |
---|---|
clientX | 触摸目标在浏览器中的x坐标 |
clientY | 触摸目标在浏览器中的y坐标 |
identifier | 标识触摸的唯一ID |
pageX | 触摸目标在当前DOM中的x坐标 |
pageY | 触摸目标在当前DOM中的y坐标 |
screenX | 触摸目标在屏幕中的x坐标 |
screenY | 触摸目标在屏幕中的y坐标 |
target | 触摸的DOM节点目标 |
- 键盘事件
对于键盘事件,我在网上找了个链接,大家可以参考一下
键盘事件讲解链接
Ending
在JS中我的算法思路不是很灵活也不是很高效,但基本还是实现了2048游戏的规则。另外还有一些操作也运用的比较陌生。倘若在阅读的过程中大家有发现错误的或者有更好的建议的,欢迎向我提出,我将感激不尽。
2048小游戏项目总结相关推荐
- 2048小游戏项目开发代码
2048项目开发小游戏(C++) 前言:2048小游戏是我们经常接触的益智小游戏,那么如何完成这个简单游戏的代码操作呢? 代码解析 头文件: #include<stdio.h> #incl ...
- 2048小游戏项目招标书(简易版)
小组成员:胡一铭,陈纪新 立项依据: 2048作为火爆一时的益智小游戏,玩法有创意,操作简易而不简单,在移动游戏盛行的时代,这样一个消磨时间.随时随地可享受的小游戏必然会在游戏市场中独树一帜,受到大众 ...
- 2048小游戏----嵌入式系统实训
嵌入式系统设计实训 引言 本次嵌入式系统实训式设计一款2048小游戏,在Linux编译环境下及ARM Cortex-A8开发平台下的,实现2048游戏的开发,且对其进行性能分析.<2048> ...
- 一文梳理2048小游戏从开发到上云全流程
摘要:本文主要以Cocos2d Web项目2048小游戏的开发上云为例,介绍DevOps开发实践的全流程 前言 本文主要以Cocos2d Web项目2048小游戏的开发上云为例,介绍DevOps开发实 ...
- python游戏代码五子棋_用20行Python代码实现2048小游戏,你会吗?
前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...
- python秒表游戏代码_用20行Python代码实现2048小游戏,你会吗?
前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...
- 我的名片能运行Linux和Python,还能玩2048小游戏,成本只要20元
晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI 猜猜它是什么?印着姓名.职位和邮箱,看起来是个名片.可是右下角有芯片,看起来又像是个PCB电路板. 其实它是一台超迷你的ARM计算机,不仅 ...
- python里graphics的使用_使用graphics.py实现2048小游戏
1.过年的时候在手机上下载了2048玩了几天,心血来潮决定用py写一个,刚开始的时候想用QT实现,发现依赖有点大.正好看到graphics.py是基于tkinter做的封装就拿来练手,并借用了CSDN ...
- html css js实现快递单打印_JS与HTML、CSS实现2048小游戏(六)
在前面的五篇文章中,小编带大家完成了网页版2048小游戏的基本游戏逻辑.但是在游戏结束的gameover()方法中咱们只是简单的通过alert来弹出一些信息,这样的话只能出现下图的效果.这样的游戏,不 ...
最新文章
- 现在很火的答题赢钱游戏,让我来简单教你怎么做自动答题器
- boost::hana::int_c用法的测试程序
- Github 移动端上架!把世界最大同性交友社区装进口袋
- java比较equlse_java基础知识要点
- 在yuv域如何降低画面亮度_家庭影院投影机错误地调节了亮度和对比度会得到怎么样的画面?...
- 为你的APK进行数字签名
- MATLAB挠曲线方程,挠曲线方程.PPT
- 高斯滤波 c++实现
- 实在小店在B2C平台具有一定的知名度
- 【小程序】rpx(responsive pixel)自适应像素浅析
- 目前最完美的魔兽世界服务端AzerothCore,Centos系统docker编译教程
- R语言 在R中实现vlookup的功能
- 网络服务器未运行是什么原因是,Win7系统网络诊断提示诊断策略服务未运行怎么办?...
- 计算机操作系统实验之进程调度(一)轮转调度法(C语言)
- GTD时间管理简洁做法
- Cadence OrCAD Capture 原理图设计过程产生的文件总结与说明
- Vector为什么是线程安全的呢?Vector为什么是线程不安全的呢?
- 航空专场 | 无人机设计仿真流程讲解与案例实操
- 压力传感器/压力变送器分类
- 逻辑回归三部曲——逻辑回归项目实战(信贷数据+Python代码实现)
热门文章
- 炉石传说酒馆战棋一键拔线(windows)
- 罗永浩 AR 创业公司估值 10 亿;​苹果宣布加大 AppStore 广告推送量;​Node.js 19 发布|极客头条...
- 掌上游戏机开发指南——GBA程序开发入门
- 全球及中国二手车贷款行业运行分析及项目动态研究报告2021年版
- python (语音)信号拆分为数据块,计算短期能量和过零率
- Linux系统的历史发展演绎
- MySQL8高级优化,持续更新......
- java实现顺时针螺旋填入
- 小米手机便签怎么看写了多少字 小米手机便签统计字数方法
- 村淘是什么,农村淘宝有什么用?如何知道宝贝是否加入村淘