想实现2048游戏书写代码时可以分为三个步骤
先书写HTML把游戏结构搭建出来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<!--最外部的大框-->
<div class="outermost"> //包裹游戏全局的大盒子
<!--title-->
<span class="top"><b>SCORE:<span id="score01"></span></b></span>//顶部实时显示的游戏分数
<!--游戏大框框-->
<div class="big">//2048游戏为四行四列因此需要16个div盒子
<div class="cell" id="c00"></div>
<div class="cell" id="c01"></div>
<div class="cell" id="c02"></div>
<div class="cell" id="c03"></div>
<div class="cell" id="c10"></div>
<div class="cell" id="c11"></div>
<div class="cell" id="c12"></div>
<div class="cell" id="c13"></div>
<div class="cell" id="c20"></div>
<div class="cell" id="c21"></div>
<div class="cell" id="c22"></div>
<div class="cell" id="c23"></div>
<div class="cell" id="c30"></div>
<div class="cell" id="c31"></div>
<div class="cell" id="c32"></div>
<div class="cell" id="c33"></div>
//游戏结束时会弹出的提示框
</div>
<!--提示框-->
<div class="tips" id="gameover">
<p>GAME OVER!!! <br>
SCORE: <span id="score02">0</span><br>
<button class="startbtn">重新开始</button>
</p>
</div>
<!--重玩一遍-->
<div class="foot">
<button class="replay"><a>重玩一遍</a></button>
</div>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
经过了第一步的搭建游戏框架,第二部就是给游戏添加样式,使它能显示出来
*{
padding: 0px;
margin: 0px auto;
font-family: Arial;
}
/*最外部的大框*/
.outermost{
width: 480px;
height: 600px;
font-size: 40px;
margin-top: 120px;
}
/*title*/
<!--顶部显示分数的样式-->
.top{
margin: auto;
}
.top span{
color: red;
}
/*游戏大框框*/
.big{
width: 480px;
height: 480px;
background:pink;
border-radius: 8px;
}
<!--给每一个盒子包裹的小框子添加样式-->
.cell{
list-style: none;
float: left;
display: inline-block;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
background-color: #fbf8cd;
margin-left: 16px;
margin-top: 16px;
border-radius: 6px;
}
<!--提前把出现的数2、4、8、16等的数所在的格子给添加好样式增加游戏体验感-->
.n2{background-color:#f65e3b;color:#776e65}
.n4{background-color:#33b5e5;color:#776e65}
.n8{background-color:#f2b179;color:#776e65}
.n16{background-color:#f59563;color:#776e65}
.n32{background-color:#f67c5f;color:#776e65}
.n64{background-color:#f65e3b;color:#776e65}
.n128{background-color:#edcf72;color:#776e65}
.n256{background-color:#edcc61;color:#776e65}
.n512{background-color:#9c0;color:#776e65}
.n1024{background-color:#33b5e5;color:#776e65;font-size:40px}
.n2048{background-color:#09c;color:#776e65;font-size:40px}
/*提示框样式*/
.tips{
border: 1px solid #cccccc;
background: #FFFFFF;
width: 400px;
height: 200px;
border-radius: 10px;
color: #ff4456;
text-align: center;
line-height: 60px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -200px;
margin-top: -100px;
display: none;
}
.tips .startbtn{
height: 50px;
width: 200px;
color: #FFFFFF;
font-size: 20px;
line-height: 50px;
border-radius: 10px;
background: cornflowerblue;
border: none;
}
/*重玩一遍*/
.foot{
width: 200px;
height: 50px;
}
.foot>.replay{
width: 200px;
height: 50px;
background: aquamarine;
margin-top: 60px;
color: lightpink;
border:0;
font-size: 24px;
font-weight: bold;
border-radius: 6px;
}
书写好了HTML+CSS部分游戏的模样也就出来了,如下图所示:
下面就到了最后也是最关键的一步----添加行为,也就是JS部分的书写,给其添加效果
//创建一个对象,里面存储所有的游戏数据及游戏方法
var game={
data : [], //定义一个数组,用来存所有的游戏的数据
score : 0, //定义一个分数的属性
gamerunning : 1, //定义一个游戏运行的状态,将其设置为1与其他状态区分开
gameover : 0, //定义一个游戏结束的状态
status : 0, //这个是目前游戏的状态,时刻的跟上面两个状态做比较,确定游戏处于运行或者结束
start : function(){ //游戏开始时候的方法
// 游戏开始的时候肯定是要把游戏的状态设置成游戏运行的状态
// this==game
this.status=this.gamerunning;
// 游戏开始的时候分数清空
this.score=0;
// 数组中的所有元素全部设置成0
this.data=[
[0,0,0,0],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]
];
this.randomNum();//调用下面自定义的随机函数,可以在移动和开始的时候随机出来一个数
this.randomNum();//调用两次是因为这是游戏开始时的方法,开局随机出现两个数和位置,因此需要调用两次
this.dataView();//调用下面所写的更新视图的方法
},
// 随机数的函数,开始的时候随机生成,移动的时候随机生成
randomNum: function(){
while(true){
// 随机生成行和列 0 - 3随机整数
var r=Math.floor( Math.random() * 4 ); //随机生成一个行
var c=Math.floor( Math.random() * 4 ); //随机生成一个列
if(this.data[r][c]==0){
var num=Math.random() > 0.5 ? 2 : 4;//随机出现2或4
this.data[r][c]=num;
break;
}
}
},
// 更新试图的方法
dataView: function(){
// 大的循环,然后把所有的元素全部遍历一遍
for(var r=0; r < 4; r++){
for(var c=0; c < 4; c++){
// 找到对应的div
var div=document.getElementById("c" + r + c); //字符串拼接
if(this.data[r][c] !=0){
// 数组中对应的内容放到格子上面去
div.innerHTML=this.data[r][c];
// 样式也写成对应的
div.className="cell n" + this.data[r][c];
}else{
div.innerHTML="";
div.className="cell"
}
}
}
// 更新分数
document.getElementById("score01").innerHTML=this.score;
//游戏没有结束的时候 弹出层时刻都是隐藏的
if(this.status==this.gamerunning){
document.getElementById("gameover").style.display="none";
}else{
document.getElementById("gameover").style.display="block";
document.getElementById("score02").innerHTML=this.score;
}
},
// 判断游戏是否结束的方法
isgameover: function(){
for(var r=0; r < 4; r++){
for(var c=0; c < 4; c++){
if(this.data[r][c]==0){ //里面有空格子的时候,游戏还是可以运行
return false; //表示游戏还没有结束
}
if(c < 3){//判断左右是否有相同的
if(this.data[r][c]==this.data[r][c+1]){
return false;
}
}
if(r < 3){
if(this.data[r][c]==this.data[r+1][c]){
return false;
}
}
}
}
return true;
},
//移动的方法,左 右 上 下四个部分
// 左 右 上 下
// 左移的方法
moveLeft: function(){
var before=String(this.data); //之前做一次转换
// 具体的移动需要处理的逻辑,直接处理好每一行即可
for(var r=0;r < 4;r ++){
this.moveLeftInRow(r);
}
var after=String(this.data); //移动之后再做一次转换
// 如果说移动之前不等于移动之后,肯定是发生了移动
if(before !=after){
this.randomNum(); //生成随机数
// 生成的随机数可能会造成游戏的gameover
if(this.isgameover()){
// 改变游戏的状态
this.status=this.gameover
}
// 更新视图
this.dataView();
}
},
moveLeftInRow: function(r){ //只去做处理每一行的逻辑
for(var c=0; c < 3; c++){
var nextc=this.getNextinRow(r,c);
if(nextc !=-1){
if(this.data[r][c]==0){
// 如果等于0,直接替换
this.data[r][c]=this.data[r][nextc];
this.data[r][nextc]=0; //位置恢复成0
c --; //要让位置恢复到原地
}else if(this.data[r][c]==this.data[r][nextc]){
this.data[r][c] *=2; //位置直接翻一倍
this.data[r][nextc]=0;
this.score +=this.data[r][c]; //更新分数
}
}else{ //没有找到
break; //直接退出循环
}
}
},
getNextinRow: function(r,c){
for(var i=c + 1; i < 4; i++){
if(this.data[r][i] !=0){
return i; //表示已经找到位置,并且把位置返回出来
}
}
return -1; //返回一个标识符
},
// 右移的方法
moveRight: function(){
var before=String(this.data);
for(var r=0; r < 4; r++){
this.moveRightInRow(r);
}
var after=String(this.data);
if(before !=after){
this.randomNum();
if(this.isgameover()){
this.status=this.gameover;
}
this.dataView();
}
},
moveRightInRow: function(r){
for(var c=4; c > 0; c--){
var prevc=this.getPrevInRow(r,c);
if(prevc !=-1){
if(this.data[r][c]==0){
this.data[r][c]=this.data[r][prevc];
this.data[r][prevc]=0;
c ++
}else if(this.data[r][c]==this.data[r][prevc]){
this.data[r][c] *=2;
this.data[r][prevc]=0;
this.score +=this.data[r][c];
}
}else{
break;
}
}
},
getPrevInRow: function(r,c){
for(var i=c - 1; i >=0; i--){
if(this.data[r][i] !=0){
return i;
}
}
return -1;
},
// 上移
moveUp: function(){
var before=String(this.data);
for(var c=0; c < 4; c++){
this.moveUpInCol(c);
}
var after=String(this.data);
if(before !=after){
this.randomNum();
if(this.isgameover()){
this.status=this.gameover;
}
this.dataView();
}
},
moveUpInCol: function(c){
for(var r=0;r < 4; r++){
var nextr=this.getNextInCol(r,c);
if(nextr !=-1){
if(this.data[r][c]==0){
this.data[r][c]=this.data[nextr][c];
this.data[nextr][c]=0;
r -- ;
}else if(this.data[r][c]==this.data[nextr][c]){
this.data[r][c] *=2;
this.data[nextr][c]=0;
this.score +=this.data[r][c];
}
}else{
break;
}
}
},
getNextInCol: function(r,c){
for(var i=r + 1; i < 4; i++){
if(this.data[i][c] !=0){
return i;
}
}
return -1;
},
// 下移的方法
moveDown: function(){
var before=String(this.data);
for(var c=0;c < 4; c++){
this.moveDownInCol(c);
}
var after=String(this.data);
if(before !=after){
this.randomNum();
if(this.isgameover()){
this.status=this.gameover;
}
this.dataView();
}
},
moveDownInCol: function(c){
for(var r=3; r > 0; r--){
var prev=this.getPrevIncol(r,c);
if(prev !=-1){
if(this.data[r][c]==0){
this.data[r][c]=this.data[prev][c];
this.data[prev][c]=0;
r -- ;
}else if(this.data[r][c]==this.data[prev][c]){
this.data[r][c] *=2;
this.data[prev][c]=0;
this.score +=this.data[r][c];
}
}else{
break;
}
}
},
getPrevIncol: function(r,c){
for(var i=r - 1; i >=0; i--){
if(this.data[i][c] !=0){
return i;
}
}
return -1;
},
}
game.start();
console.log(game.data)
console.log(game.status);
console.log(game.score);
//键盘事件
document.onkeydown=function(){
if(event.keyCode==37){
//console.log("左")
game.moveLeft();
}else if(event.keyCode==38){
//console.log("上")
game.moveUp()
}else if(event.keyCode==39){
//console.log("右")
game.moveRight()
}else if(event.keyCode==40){
//console.log("下")
game.moveDown()
}
}
//touch事件
//手指按下
var startX;//设定开始起始位置的x坐标
var startY;//设定开始起始位置的y坐标
var endX;//设定结束滑动位置的x坐标
var endY;//设定结束滑动位置的y坐标
document.addEventListener('touchstart',function(){
// console.log("手指按下了屏幕")
console.log(event);
startX=event.touches[0].pageX;
startY=event.touches[0].pageY;
})
//手指移动
//document.addEventListener('touchmove',function(){
// console.log("手指的移动")
//})
//手指松开
document.addEventListener("touchend",function(){
// console.log("手指松开")
console.log(event);
endX=event.changedTouches[0].pageX;//如何获取结束时的位置x
endY=event.changedTouches[0].pageY;
var X=endX - startX;
var Y=endY - startY
var absX=Math.abs(X) > Math.abs(Y);
var absY=Math.abs(Y) > Math.abs(X);
if(X > 0 && absX){
console.log("右滑动")
game.moveRight()
}else if(X < 0 && absX){
console.log("左滑动")
game.moveLeft()
}if(Y > 0 && absY){
console.log("下滑动")
game.moveDown()
}if(Y < 0 && absY){
console.log("上滑动")
game.moveUp()
}
})
就这样一个简单的2048游戏就完成啦~
非常感谢您能看到这里~
关注我~带给你更多惊喜~
imulink中的Shift Arithmetic 模块可以移动输入信号中的数位和/或二进制小数点。今天主要是实例讲解Simulink的Shift Arithmetic移位模块。
1.Shift Arithmetic 模块
模块功能:Shift Arithmetic 模块可以移动输入信号中的数位和
/或二进制小数点。
库:
Simulink / Logic and Bit Operations
HDL Coder / Logic and Bit Operations
双击模块可以查看模块的参数设置:
参数1:二进制位移位数:源 — 要移位的位的源 Source
对话框 (默认) | 输入端口
指定是直接在对话框中输入要移动的位数,还是从输入端口继承值。
编程用法
模块参数:BitShiftNumberSource
类型:字符向量、字符串
值:'Dialog' | 'Input port'
默认值:'Dialog'
参数2:二进制位移位数:数量 — 二进制位移位数
8 (默认) | 标量
指定标量、向量或移位值数组。当二进制位移位数:源为对话框时,此参数才可用。
如果方向为... 则...
左侧或右侧 使用正整数指定移位。
双向 使用正整数表示右移,使用负整数表示左移。
编程用法
模块参数:BitShiftNumber
类型:字符向量、字符串
值:scalar
默认值:'9'
参数3:二进制位移位数:方向 — 移位的方向
左侧 (默认) | 右侧 | 双向
指定移位的方向:向左、向右或双向。
编程用法
模块参数:BitShiftDirection
类型:字符向量、字符串
值:'Left' | 'Right' | 'Bidrectional'
默认值:'Bidrectional'
参数4:二进制小数点移位数:数量 — 二进制小数点移位的位数
0 (默认) | scalar
指定将输入信号中的二进制小数点移动的整数位数。正值表示右移,负值表示左移。
编程用法
模块参数:BinPtShiftNumber
类型:字符向量、字符串
值:'Dialog' | 'Input port'
默认值:'Dialog'
参数5:超范围移位值的诊断 — 诊断操作
无 (默认) | 警告 | 错误
指定当模块包含超出范围的移位值时,是否在仿真过程中生成警告或错误消
息。选项包括:
None - 不执行任何 Simulink操作。
Warning - Simulink 显示警告并继续进行仿真。
Error - Simulink 终止仿真并显示错误。
编程用法
模块参数:DiagnosticForOORShift
类型:字符向量、字符串
值:'None' | 'Warning' | 'Error'
默认值:'None'
参数6:检查生成代码中是否有超出范围的 '二进制位移位数' — 检查生成代码中是
否有超出范围的二进制位移位数
off (默认) | on
如果选中此复选框,将在生成的代码中包含条件语句,以防移位值超出范围。
当二进制位移位数:源为输入端口时,此复选框才可用。
编程用法
模块参数:CheckOORBitShift
类型:字符向量、字符串
值:'on' | 'off'
默认值:'off'
2.实例
实例1
3转换成二进制得到"0011",将"0011"左移3位变成"0001 1000",再将"0001 1000"转换成十进制就变成了24,移位其实就是乘以2的n次方,所以out=3*2^3=3*8=24。
参数设置:
实例2
参数设置:
实例3
5的二进制是101,此时向右移动2位变成1.01,小数部分值为1,两位二进制有4种,小数部分为0.25。5的二进制是101,此时向右移动1位变成10.1,小数部分值为1,1位二进制有2种,小数部分为0.5。
具体转换:
5的二进制101=1*2^2+0*2^1+1*2^0=5
1.01的二进制 1.01=1*2^0+0*2^(-1)+1*2^(-2)=1+0+0.25=1.25
10.1的二进制 10.1=1*2^1+0*2^0+1*2^(-1)=2.5
模块参数:
实例4
模块参数:
实例5
3.参考内容
[1]https://ww2.mathworks.cn/help/simulink/slref/shiftarithmetic.html#bstdjf8_head
[2] CSDN作者chhttty的文章《Simulink建模:位运算》,文章链接为:
https://blog.csdn.net/u013288925/article/details/127520692
本文内容来源于网络,仅供参考学习,如内容、图片有任何版权问题,请联系处理,24小时内删除。
作 者 | 郭志龙
编 辑 | 郭志龙
校 对 | 郭志龙
果提供了 alpha 值,则将颜色代码转换为rgb()或 rgba() 字符串。
JavaScript
const hexToRGB=hex=> {
let alpha=false,
h=hex.slice(hex.startsWith('#') ? 1 : 0);
if (h.length===3) h=[...h].map(x=> x + x).join('');
else if (h.length===8) alpha=true;
h=parseInt(h, 16);
return (
'rgb' +
(alpha ? 'a' : '') +
'(' +
(h >>> (alpha ? 24 : 16)) +
', ' +
((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
', ' +
((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
(alpha ? `, ${h & 0x000000ff}` : '') +
')'
);
};
示例:
hexToRGB('#27ae60ff'); // 'rgba(39, 174, 96, 255)'
hexToRGB('27ae60'); // 'rgb(39, 174, 96)'
hexToRGB('#fff'); // 'rgb(255, 255, 255)'
更多内容请访问我的网站:https://www.icoderoad.com
*请认真填写需求信息,我们会在24小时内与您取得联系。