JavaScript实现2048小游戏,我终于赢了一把

Posted 编程界明世隐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript实现2048小游戏,我终于赢了一把相关的知识,希望对你有一定的参考价值。

javascript实现2048小游戏

作者简介

作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、JavaScript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!

系列目录

1. JavaScript 贪吃蛇游戏
2. JavaScript 俄罗斯方块
3. JavaScript 扫雷小游戏
4. JavaScript 网红太空人表盘

效果图

实现思路

  1. 编写页面和画布代码。
  2. 绘制背景。
  3. 绘制好全部卡片。
  4. 随机生成一个卡片(2或者4)。
  5. 键盘事件监听(上、下、左、右键监听)。
  6. 根据键盘的方向,处理数字的移动合并。
  7. 加入成功、失败判定。
  8. 处理其他收尾工作。

代码实现

编写页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048</title>
    <style>
        #box{
           width:370px;
           height:370px;
           position:absolute;
           margin:0 auto;
           left:0;
           right:0;
           top:1px;
           bottom:0;
       }

       .rebutton{
        position: absolute;
        top:370px;
        left:38%;
       }
       </style>
</head>
<body>
    <div id='box'></div>
    <button onclick="restart()" class='rebutton'>重开</button>
</body>
<script src="js/util.js"></script>
<script src="js/2048.js"></script>
<script type="text/javascript">

   </script>
</html>

添加画布

在2048.js编写代码

  1. 创建函数
function G2048(){
	this.renderArr=[];//渲染数组
	this.cards=initCardArray();
	//游戏标记
	this.flag='start';
}
//初始化数组
function initCardArray(){
	var cards = new Array();
	for (var i = 0; i < 4; i++) {
		cards[i] = new Array();
		for (var j = 0; j < 4; j++) {
			//cards[i][j]=null;
		}
	}
	return cards;
}
  1. 初始化和绘制背景代码(在2048.js中编写)
//初始化
    G2048.prototype.init=function(el,musicObj){
        if(!el) return ;
		this.el=el;
		var canvas = document.createElement('canvas');//创建画布
		canvas.style.cssText="background:white;";
		var W = canvas.width = 370; //设置宽度
		var H = canvas.height = 370;//设置高度
		
		el.appendChild(canvas);//添加到指定的dom对象中
		this.ctx = canvas.getContext('2d');
		
		this.draw();
	}
    //绘制入口
    G2048.prototype.draw=function(){
		//创建背景
		this.drawGB();

	    //渲染到页面上
		this.render();

	}

	//创建背景
	G2048.prototype.drawGB=function(){
		var bg = new _.Rect({x:0,y:0,width:364,height:364,fill:true,fillStyle:'#428853'});
		this.renderArr.push(bg);
	}

	//渲染图形
	G2048.prototype.render=function(){
		var context=this.ctx;
		this.clearCanvas();	
		_.each(this.renderArr,function(item){
			item && item.render(context);
		});
	}
	//清洗画布
	G2048.prototype.clearCanvas=function() {
		this.ctx.clearRect(0,0,parseInt(this.w),parseInt(this.h));
	}
  1. 在页面代码中加入以下 js 代码
var box = document.getElementById('box');
g2048.init(box);


运行效果:

绘制好全部卡片

  1. 创建Card
//定义Card
function Card(i,j){
	this.i=i;//下标i
	this.j=j;//下标j
	this.x=0;// x坐标
	this.y=0;// y坐标
	this.h=80;//高
	this.w=80;//宽
	this.start=10;//偏移量(固定值)
	this.num=0;//显示数字
	this.merge=false;//当前是否被合并过,如果合并了,则不能继续合并,针对当前轮
	//初始化创建
	this.obj = this.init();
	//创建显示数字对象
	this.numText = this.initNumText();
} 
//初始创建
Card.prototype.init=function(){
	return new _.Rect({x:this.x,y:this.y,width:this.w,height:this.h,fill:true});
}
//根据i j计算x y坐标
Card.prototype.cal=function(){
	this.x = this.start + this.j*this.w + (this.j+1)*5;
	this.y = this.start + this.i*this.h + (this.i+1)*5;
	//更新给obj
	this.obj.x=this.x;
	this.obj.y=this.y;
	//设置填充颜色
	this.obj.fillStyle=this.getColor();

	//更新文字的位置
	this.numText.x = this.x+40;
	this.numText.y = this.y+55;
	this.numText.text=this.num;
}
//初始化显示数字对象
Card.prototype.initNumText=function(){
	var font = "34px 思源宋体";
	var fillStyle = "#7D4E33";
	return new _.Text({x:this.x,y:this.y+50,text:this.num,fill:true,textAlign:'center',font:font,fillStyle:fillStyle});
}
//获取color
Card.prototype.getColor=function(){
	var color;
	//根据num设定颜色
	switch (this.num) {
	case 2:
		color = "#EEF4EA";
		break;
	case 4:
		color = "#DEECC8";
		break;
	case 8:
		color = "#AED582";
		break;
	case 16:
		color = "#8EC94B";
		break;
	case 32:
		color = "#6F9430";
		break;
	case 64:
		color = "#4CAE7C";
		break;
	case 128:
		color = "#3CB490";
		break;
	case 256:
		color = "#2D8278";
		break;
	case 512:
		color = "#09611A";
		break;
	case 1024:
		color = "#F2B179";
		break;
	case 2048:
		color = "#DFB900";
		break;

	default://默认颜色
		color = "#5C9775";
		break;
	}
	
	return color;
}

Card.prototype.render=function(context){
	//计算坐标等
	this.cal();
	//执行绘制
	this.obj.render(context);
	//是否绘制文字的处理
	if(this.num!=0){
		this.numText.render(context);
	}
}

}
  1. 创建卡片
	//创建卡片
	G2048.prototype.drawCard=function(){
		var that=this;
		var card;
		for (var i = 0; i < 4; i++) {
			for (var j = 0; j < 4; j++) {
				card = new Card(i,j);
				that.cards[i][j]=card;
				that.renderArr.push(card);
			}
		}
	}
  1. 调用绘制代码

    运行效果:
  2. 修改一下卡片的默认数字

随机生成一个卡片,2或者4

  1. 先把Card中 num 默认改成0
  2. 因为2跟4出现的比例是1:4,所以采用随机出1-5的数字,当是1的时候就表示,当得到2、3、4、5的时候就表示要出现数字2.
  3. 随机获取i,j 就可以得到卡片的位置,割接i,j取到card实例,如果卡片没有数字,就表示可以,否则就递归继续取,取到为止。
  4. 把刚才取到的数字,设置到card实例对象中就好了。

代码如下:

//随机创建一个卡片
	G2048.prototype.createRandomNumber=function(){
		var num = 0;
		var index = _.getRandom(1,6);//这样取出来的就是1-5 之间的随机数
		//因为2和4出现的概率是1比4,所以如果index是1,则创建数字4,否则创建数字2(1被随机出来的概率就是1/5,而其他就是4/5 就是1:4的关系)
		console.log('index==='+index)
		if(index==1){
			num = 4;
		}else {
			num = 2;
		}
		//判断如果格子已经满了,则不再获取,退出
		if(this.cardFull()){
			return ;
		}
		//获取随机卡片,不为空的
		var card = this.getRandomCard();
		//给card对象设置数字
		if(card!=null){
			card.num=num;
		}
	}
	//获取随机卡片,不为空的
	G2048.prototype.getRandomCard=function(){
		var i = _.getRandom(0,4);
		var j = _.getRandom(0,4);
		var card = this.cards[i][j];
		if(card.num==0){//如果是空白的卡片,则找到了,直接返回
			return card;
		}
		//没找到空白的,就递归,继续寻找
		return this.getRandomCard();
	}
	//判断格子满了
	G2048.prototype.cardFull=function() {
		var card;
		for (var i = 0; i < 4; i++) {
			for (var j = 0; j < 4; j++) {
				card = this.cards[i][j];
				if(card.num==0){//有一个为空,则没满
					return false;
				}
			}
		}		
		return true;
	}

draw方法中调用,表示打开游戏默认一个数字

运行效果:

加入键盘事件

同样要在draw方法中调用哦

	//按键的控制
	G2048.prototype.control=function(){
		var that=this;
		global.addEventListener('keydown',function(e){
			console.log(that.flag)
			if(that.flag!='start') return ;
			var dir;
			switch (e.keyCode){
				case 87://w
				case 38://上
					dir=1;//上移动
					break;
				case 68://d
				case 39://右
					dir=2;//右移动
					break;
				case 83://s
				case 40://下
					dir=3;//下移动
					break;
				case 65://a
				case 37://左
					dir=4;//左移动
					break;
			}
			//卡片移动的方法
			that.moveCard(dir);
		});
	}
  1. 加入移动逻辑处理代码
//卡片移动的方法
	G2048.prototype.moveCard=function(dir) {
		//将卡片清理一遍,因为每轮移动会设定合并标记,需重置
		this.clearCard();
		
		if(dir==1){//向上移动
			this.moveCardTop(true);
		}else if(dir==2){//向右移动
			this.moveCardRight(true);
		}else if(dir==3){//向下移动
			this.moveCardBottom(true);
		}else if(dir==4){//向左移动
			this.moveCardLeft(true);
		}
		//移动后要创建新的卡片
		this.createRandomNumber();
		//重绘
		this.render();
		//判断游戏是否结束
		this.gameOverOrNot();
	}

	//将卡片清理一遍,因为每轮移动会设定合并标记,需重置
	G2048.prototype.clearCard=function() {
		var card;
		for (var i = 0; i < 4; i++) {//i从1开始,因为i=0不需要移动
			for (var j = 0; j < 4; j++) {
				card = this.cards[i][j];
				card.merge=false;
			}
		}
	}
  1. 加入上下左右处理逻辑
//

以上是关于JavaScript实现2048小游戏,我终于赢了一把的主要内容,如果未能解决你的问题,请参考以下文章

Java实现2048小游戏,我竟然一盘都没赢,你们说我到底行不行?

javascript 2048游戏

JavaScript小游戏--2048(PC端)

JavaScript小游戏--2048(移动端)

大大维的游戏机计划3--2048v1

js实现2048小游戏二维数组更新算法