Flex版的2048游戏

     最近2048游戏好像挺火,在公交,吃饭,甚至在路上走路都有人拿着手机在玩,之前我看同事玩,觉得很幼稚,移来移去太无聊了吧

到后面自己也下了,发现确实挺无聊的,也就是在无聊的时候打发无聊的时间,后来就想用flex写

下这个游戏, 移动的逻辑借鉴了这个安卓的实现:http://www.jikexueyuan.com/study/index/cid/43/lid/9.html

    上个周末实现了上下左右移动的逻辑,今天晚上把界面和一些样式加上一些小BUG解决了下,基本上玩是没问题了

先看几张我刚刚玩的截图:

 


下面就看看代码吧,代码中有相关注释,这里就不啰嗦了

首先新建一个组件 NumberTile.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%">
	<fx:Declarations>
		<!-- 布丰(Bufoon)-->
	</fx:Declarations>
	
	<fx:Script>
		<![CDATA[
			[Bindable]
			public var text:String;
			[Bindable]
			public var textColor:uint;
			[Bindable]
			public var bacolor:uint
			[Bindable]
			public var textSize:uint = 40;
		]]>
	</fx:Script>
	
	<s:BorderContainer width="100%" height="100%" cornerRadius="1" borderVisible="false" backgroundColor="{bacolor}">
		<s:Label text="{text}" color="{textColor}" verticalCenter="0" fontWeight="bold" fontFamily="Microsoft YaHei" fontSize="{textSize}" horizontalCenter="0"/>
	</s:BorderContainer>
</s:Group>

主应用Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="initApp(event)"
			   addedToStage="stage.addEventListener(KeyboardEvent.KEY_DOWN,appKeyDown)" >
	<fx:Declarations>
		<!-- 布丰(Bufoon)-->
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.events.CloseEvent;
			import mx.events.FlexEvent;
			//存放方格的Vector
			private var tileVector:Vector.<NumberTile> = new Vector.<NumberTile>();
			[Bindable]
			private var score:int = 0; //得分
			private var winContinue:Boolean = true; //赢了是否继续
			protected function initApp(event:FlexEvent):void
			{
				// 游戏初始化
				// 添加16个方格
				for(var i:int = 0; i < 16; i++){
					//自定义的方格组件
					var bcChild:NumberTile = new NumberTile();
					bcChild.bacolor = 0xCDC0B4; //设置背景色
					bcChild.name = i + ""; //添加组件名称
					tileVector.push(bcChild); //将创建的组件添加到Vector
					bcc.addElement(bcChild); //添加到容器中
				}
				//添加键盘事件
				this.addEventListener(KeyboardEvent.KEY_DOWN, appKeyDown);
			}
			[Bindable]
			private var isStart:Boolean = true;
			protected function start_clickHandler(event:MouseEvent):void
			{
				//随机生成两个方格的数字
				this.get2or4(this.getNullTileIndex());
				this.get2or4(this.getNullTileIndex());
				isStart = false;
			}
			protected function restart_clickHandler(event:MouseEvent):void
			{
				isStart = false;
				//随机生成两个方格的数字
				for(var i:int = 0; i < tileVector.length; i++){
					tileVector[i].text = null;
					tileVector[i].bacolor = 0xCDC0B4;
				}
				score = 0;
				this.get2or4(this.getNullTileIndex());
				this.get2or4(this.getNullTileIndex());
			}
			
			//随机产生方格的数字 num:随机产生的空方格索引
			private function get2or4(num:int):void{
				if(num == -1){
					return;
				}
				var str:String = "2"; //方格数字
				var bacolor:uint = 0xEEE4DA; //数字对应的背景颜色
				var randonNum:int = Math.round(Math.random()*10); //随机数
				var nt:NumberTile = tileVector[num]; //获取方格对象
				if(randonNum > 8){ //如果随机数大于8 就是4,相当于概率在20%左右
					str = "4"; //更改方格数字
					bacolor = 0xEDE0C8; //设置数字对应的方格背景颜色
				}
				//更改生成的方格数字,背景色和文字颜色
				nt.text = str;
				nt.textColor = 0x776E65;
				nt.bacolor = bacolor;
			}
			
			//随机获取空的方格的索引
			private function getNullTileIndex():Number{
				//空方格 数组
				var nullArray:Array = new Array();
				for(var i:int = 0; i < tileVector.length; i++){
					if(tileVector[i].text == null){
						nullArray.push(tileVector[i].name);
					}
				}
				//如果没有空的方格返回-1 对应get2or4方法里面的为-1,就不生成方格
				if(nullArray.length == 0){
					return -1;
				}
				var num:Number = Math.round(Math.random()*(nullArray.length - 1));
				return Number(nullArray[num]);
			}
			
			//键盘上下左右方向键处理
			protected function appKeyDown(event:KeyboardEvent):void
			{
				// TODO Auto-generated method stub
				switch(event.keyCode.toString())
				{
					case "37": //left
					{
						this.leftMoveHandle();
						break;
					}
					case "38": //top
					{
						this.upMoveHandle();
						break;
					}
					case "39": //right
					{
						this.rightMoveHandle();
						break;
					}
					case "40":
					{
						this.downMoveHandle();
						break; //bottom
					}
				}
			}
			/**
			 * 上下左右按键的操作逻辑,由于flex中没有二维数组,不过也可以模拟二维数组,就是用下标表示
			 * 但是这里没有模拟而是直接就操作Vecotr容器
			 * 因为总共是16个方格,4*4矩阵,添加两个循环
			 * 如下矩阵:
			 *     0   1   2   3
			 *     4   5   6   7
			 *     8   9   10  11
			 *     12  13  14  15
			 * 
			 * 看下面两组公式 :
			 * 【4*i+j】和【4*i+j1】获取行索引--左右
			 * 【4*j+i】和【4*j1+i】获取列索引--上下
			 *  
			 * 上下左右逻辑都差不多,就是循环的比较两个相邻方格,然后做操作
			 **/
			private function leftMoveHandle():void{
				this.checkComplete(); //检测游戏是否结束
				var moveFlag:Boolean = false; //移动标记,用来判断是否生成方格数字
				var count:Number = 0; //用来判断中间是否有相隔的数字,如 242这样
				for(var i:int = 0; i < 4; i++){
					for(var j:int = 0; j < 4; j++){
						for(var j1:int = j + 1; j1 < 4; j1++){
							if(tileVector[4*i+j1].text != null){
								if(tileVector[4*i+j].text == null){
									this.setTileStyle(i,j,j1,0,0);
									j--; //继续本行的循环
									moveFlag = true;
									break;
								} else if(tileVector[4*i+j].text == tileVector[4*i+j1].text){
									if(count == 0){
										score = score + int(tileVector[4*i+j].text)*2;
										this.setTileStyle(i,j,j1,0,1);
										moveFlag = true;
										break;	
									}
								} else{
									count++;
								}
							}
						}
						count = 0;
					}
				}
				isWin();
				if(moveFlag){
					this.get2or4(this.getNullTileIndex());
				}
			}
			
			private function rightMoveHandle():void{
				this.checkComplete();
				var moveFlag:Boolean = false;
				var count:Number = 0;
				for(var i:int = 0; i < 4; i++){
					for(var j:int = 3; j >= 0; j--){
						for(var j1:int = j - 1; j1 >= 0; j1--){
							if(tileVector[4*i+j1].text != null){
								if(tileVector[4*i+j].text == null){
									this.setTileStyle(i,j,j1,0,0);
									j++;
									moveFlag = true;
									break;
								} else if(tileVector[4*i+j].text == tileVector[4*i+j1].text){
									if(count == 0){
										score = score + int(tileVector[4*i+j].text)*2;
										this.setTileStyle(i,j,j1,0,1);
										moveFlag = true;
										break;
									}
								} else{
									count++;
								}
							}
						}
						count = 0;
					}
				}
				isWin();
				if(moveFlag){
					this.get2or4(this.getNullTileIndex());
				}
			}
			
			
			private function upMoveHandle():void{
				this.checkComplete();
				var moveFlag:Boolean = false;
				var count:Number = 0;
				for(var i:int = 0; i < 4; i++){
					for(var j:int = 0; j < 4; j++){
						for(var j1:int = j + 1; j1 < 4; j1++){
							if(tileVector[4*j1+i].text != null){
								if(tileVector[4*j+i].text == null){
									this.setTileStyle(i,j,j1,1,0);
									j--;
									moveFlag = true;
									break;
								} else if(tileVector[4*j+i].text == tileVector[4*j1+i].text){
									if(count == 0){
										score = score + int(tileVector[4*j+i].text)*2;
										this.setTileStyle(i,j,j1,1,1);
										moveFlag = true;
										break;
									}
								} else{
									count++;
								}
							}
						}
						count = 0;
					}
				}
				isWin();
				if(moveFlag){
					this.get2or4(this.getNullTileIndex());
				}
			}
			
			private function downMoveHandle():void{
				this.checkComplete();
				var moveFlag:Boolean = false;
				var count:Number = 0;
				for(var i:int = 0; i < 4; i++){
					for(var j:int = 3; j >= 0; j--){
						for(var j1:int = j - 1; j1 >= 0; j1--){
							if(tileVector[4*j1+i].text != null){
								if(tileVector[4*j+i].text == null){
									this.setTileStyle(i,j,j1,1,0);
									j++;
									moveFlag = true;
									break;
								} else if(tileVector[4*j+i].text == tileVector[4*j1+i].text){
									if(count == 0){
										score = score + int(tileVector[4*j+i].text)*2;
										this.setTileStyle(i,j,j1,1,1);
										moveFlag = true;
										break;
									}
								} else{
									count++;
								}
							}
						}
						count = 0
					}
				}
				isWin();
				if(moveFlag){
					this.get2or4(this.getNullTileIndex());
				}
			}
			
			//移动 方格属性更替
			private function setTileStyle(i:int, j:int, j1:int, rFlag:int, cFlag:int):void{
				var tile1:NumberTile = null;
				var tile2:NumberTile = null;
				if(rFlag == 0){ //left right
					tile1 = tileVector[4*i+j];
					tile2 = tileVector[4*i+j1]
				}else{ //up down
					tile1 = tileVector[4*j+i];
					tile2 = tileVector[4*j1 + i]
				}
				
				if(cFlag == 0){ //null
					tile1.text = tile2.text;
					var arr1:Array = this.getStyleArrayByNum(int(tile1.text));
					tile1.textSize = arr1[0];
					tile1.textColor = arr1[1];
					tile1.bacolor = arr1[2];
					tile2.text = null;
					tile2.bacolor = 0xcdc0b4;
				} else{ // plus
					tile1.text = (int(tile2.text) * 2) + "";
					var arr2:Array = this.getStyleArrayByNum(int(tile1.text));
					tile1.textSize = arr2[0];
					tile1.textColor = arr2[1];
					tile1.bacolor = arr2[2];
					tile2.text = null;
					tile2.bacolor = 0xcdc0b4;
				}
			}
			
			//根据数字获取对应的相关属性值
			private function getStyleArrayByNum(num:Number):Array{
				var arr:Array = new Array();
				var textColor:uint;
				var baColor:uint;
				var textSize:uint;
				if(num == 2){
					textColor = 0x776E65;
					baColor = 0xEEE4DA;
					textSize = 40;
				}else if(num == 4){
					textColor = 0x776E65;
					baColor = 0xEDE0C8;
					textSize = 40;
				}else if(num == 8){
					textColor = 0xF9F6F3;
					baColor = 0xF2B179;
					textSize = 40;
				}else if(num == 16){
					textColor = 0xF9F6F3;
					baColor = 0xF59563;
					textSize = 40;
				}else if(num == 32){
					textColor = 0xF9F6F3;
					baColor = 0xF67C5F;
					textSize = 40;
				}else if(num == 64){
					textColor = 0xF9F6F3;
					baColor = 0xF6653E;
					textSize = 40;
				}else if(num >= 128){
					textColor = 0xF9F6F3;
					baColor = 0xEDC951;
					textSize = 36;
					if(num > 1000){
						textSize = 26;
					}
				}
				
				arr.push(textSize)
				arr.push(textColor);
				arr.push(baColor);
				return arr;
			}
			private var alertFlag:Boolean = false;
			private function checkComplete():void{
				var flag:Boolean = true;
				out:for(var i:int = 0; i < 4; i++){
					for(var j:int = 0; j < 4; j++){
						if(tileVector[4*i + j].text == null ||
							(j > 0 && tileVector[4*i + j].text == tileVector[4*i + j - 1].text) ||
							(j < 3 && tileVector[4*i + j].text == tileVector[4*i + j + 1].text) ||
							(j > 0 && tileVector[4*j + i].text == tileVector[4*j + i - 4].text) ||
							(j < 3 && tileVector[4*j + i].text == tileVector[4*j + i + 4].text) 
						){
							flag = false;
							break out;
						}
					}
				}
				
				if(flag && !alertFlag){
					Alert.yesLabel = "Restart";
					Alert.cancelLabel = "No";
					Alert.show("GAME OVER","STATUS",9,this,gameOverHandle);
					alertFlag = true;
				}
			}
			private function gameOverHandle(event:CloseEvent):void{
				alertFlag = false;
				isStart = false;
				if(event.detail == Alert.YES)
				{
					for(var i:int = 0; i < tileVector.length; i++){
						tileVector[i].text = null;
						tileVector[i].bacolor = 0xCDC0B4;
					}
					this.start_clickHandler(null);
					this.setFocus();
					score = 0;
				}
			}
			//判断是否赢了
			private function isWin():Boolean{
				var flag:Boolean = false;
				for(var i:int = 0; i < tileVector.length; i++){
					if(tileVector[i].text == "2048"){
						flag = true;
					}
				}
				if(flag && !alertFlag){
					alertFlag = true;
					Alert.yesLabel = "Continue";
					Alert.cancelLabel = "No";
					Alert.show("you Win! is Continue?","win",9,this,winHandle);
				}
				return flag;
			}
			private function winHandle(event:CloseEvent):void{
				alertFlag = false;
				isStart = false;
				if(event.detail == Alert.NO)
				{
					for(var i:int = 0; i < tileVector.length; i++){
						tileVector[i].text = null;
						tileVector[i].bacolor = 0xCDC0B4;
					}
					score = 0;
				}
			}
		]]>
	</fx:Script>
	<s:BorderContainer width="400" height="580" verticalCenter="0" horizontalCenter="0" backgroundColor="0xDEDEDE" borderColor="0x666666">
		<s:BorderContainer borderVisible="false" backgroundColor="0xff7f17" width="100%" height="60">
			<s:Label text="2048" fontFamily="Microsoft YaHei" fontSize="40" horizontalCenter="0" verticalCenter="0" fontWeight="bold"/>
		</s:BorderContainer>
		<s:HGroup y="80" right="0" verticalAlign="middle" width="130">
			<s:Label text="Score:"  fontFamily="Microsoft YaHei" fontSize="20" color="0xB704DD" fontWeight="bold"/>
			<s:Label text="{score}" fontFamily="Microsoft YaHei" fontSize="20" color="0xB704DD" fontWeight="bold"/>
		</s:HGroup>
		<s:HGroup y="120" horizontalCenter="0" horizontalAlign="center" verticalAlign="middle">
			<s:BorderContainer enabled="{isStart}" width="100" height="50" backgroundColor="0x6FCDCD" borderVisible="false" click="start_clickHandler(event)" buttonMode="true">
				<s:Label text="Start" fontWeight="bold" color="0xEEEEEE" fontFamily="Microsoft YaHei" fontSize="28"
						 horizontalCenter="0" verticalCenter="0"/>
			</s:BorderContainer>
			<s:BorderContainer width="100" height="50" backgroundColor="0x79B900" borderVisible="false" click="restart_clickHandler(event)" buttonMode="true">
				<s:Label text="Retart" fontWeight="bold" color="0xEEEEEE" fontFamily="Microsoft YaHei" fontSize="28"
						 horizontalCenter="0" verticalCenter="0"/>
			</s:BorderContainer>
		</s:HGroup>
		<s:BorderContainer id="bcc" x="20" y="180" cornerRadius="4" backgroundColor="0xBBADA0" width="360" height="360" borderColor="0xDEDEDE">
			<s:layout>
				<s:TileLayout requestedColumnCount="4" requestedRowCount="4" columnAlign="justifyUsingWidth" rowAlign="justifyUsingHeight"
							  verticalGap="10" horizontalGap="10" paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"/>
			</s:layout>
		</s:BorderContainer>
		<s:Label text="By布丰(Bufoon)" fontFamily="Microsoft YaHei" fontSize="13" fontWeight="bold" bottom="1" horizontalCenter="0"/>
	</s:BorderContainer>
</s:Application>

By 布丰(Bufoon) http://blog.csdn.net/songanling/article/details/26012645


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于 JavaScript 的 2048 游戏的示例代码: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>2048 Game</title> <style> body { margin: 0; padding: 0; font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif; } h1 { text-align: center; margin-top: 50px; } .container { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; height: 400px; width: 400px; margin: 0 auto; } .box { display: flex; justify-content: center; align-items: center; height: 100px; width: 100px; border: 1px solid #ccc; font-size: 36px; font-weight: bold; background-color: #eee; margin: 5px; } .box-2 { background-color: #eee4da; } .box-4 { background-color: #ede0c8; } .box-8 { background-color: #f2b179; } .box-16 { background-color: #f59563; } .box-32 { background-color: #f67c5f; } .box-64 { background-color: #f65e3b; } .box-128 { background-color: #edcf72; } .box-256 { background-color: #edcc61; } .box-512 { background-color: #edc850; } .box-1024 { background-color: #edc53f; } .box-2048 { background-color: #edc22e; } .box-empty { background-color: #ccc0b3; } </style> </head> <body> <h1>2048 Game</h1> <div class="container"></div> <script> // 初始化游戏 var board = []; var score = 0; function init() { for (var i = 0; i < 4; i++) { board[i] = []; for (var j = 0; j < 4; j++) { board[i][j] = 0; } } score = 0; generateNumber(); generateNumber(); updateBoard(); } // 生成随机数 function generateNumber() { var emptyCells = []; for (var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { if (board[i][j] === 0) { emptyCells.push([i, j]); } } } if (emptyCells.length === 0) { return false; } var randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]; var randomNumber = Math.random() < 0.5 ? 2 : 4; board[randomCell[0]][randomCell[1]] = randomNumber; return true; } // 更新游戏面板 function updateBoard() { var container = document.querySelector('.container'); container.innerHTML = ''; for (var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { var box = document.createElement('div'); box.classList.add('box'); box.classList.add('box-' + board[i][j]); box.innerText = board[i][j] > 0 ? board[i][j] : ''; container.appendChild(box); } } document.querySelector('#score').innerText = score; } // 向左移动 function moveLeft() { var hasMoved = false; for (var i = 0; i < 4; i++) { for (var j = 1; j < 4; j++) { if (board[i][j] !== 0) { for (var k = 0; k < j; k++) { if (board[i][k] === 0 && noBlockHorizontal(i, k, j, board)) { board[i][k] = board[i][j]; board[i][j] = 0; hasMoved = true; break; } else if (board[i][k] === board[i][j] && noBlockHorizontal(i, k, j, board)) { board[i][k] *= 2; board[i][j] = 0; score += board[i][k]; hasMoved = true; break; } } } } } if (hasMoved) { generateNumber(); updateBoard(); } } // 向右移动 function moveRight() { var hasMoved = false; for (var i = 0; i < 4; i++) { for (var j = 2; j >= 0; j--) { if (board[i][j] !== 0) { for (var k = 3; k > j; k--) { if (board[i][k] === 0 && noBlockHorizontal(i, j, k, board)) { board[i][k] = board[i][j]; board[i][j] = 0; hasMoved = true; break; } else if (board[i][k] === board[i][j] && noBlockHorizontal(i, j, k, board)) { board[i][k] *= 2; board[i][j] = 0; score += board[i][k]; hasMoved = true; break; } } } } } if (hasMoved) { generateNumber(); updateBoard(); } } // 向上移动 function moveUp() { var hasMoved = false; for (var i = 1; i < 4; i++) { for (var j = 0; j < 4; j++) { if (board[i][j] !== 0) { for (var k = 0; k < i; k++) { if (board[k][j] === 0 && noBlockVertical(j, k, i, board)) { board[k][j] = board[i][j]; board[i][j] = 0; hasMoved = true; break; } else if (board[k][j] === board[i][j] && noBlockVertical(j, k, i, board)) { board[k][j] *= 2; board[i][j] = 0; score += board[k][j]; hasMoved = true; break; } } } } } if (hasMoved) { generateNumber(); updateBoard(); } } // 向下移动 function moveDown() { var hasMoved = false; for (var i = 2; i >= 0; i--) { for (var j = 0; j < 4; j++) { if (board[i][j] !== 0) { for (var k = 3; k > i; k--) { if (board[k][j] === 0 && noBlockVertical(j, i, k, board)) { board[k][j] = board[i][j]; board[i][j] = 0; hasMoved = true; break; } else if (board[k][j] === board[i][j] && noBlockVertical(j, i, k, board)) { board[k][j] *= 2; board[i][j] = 0; score += board[k][j]; hasMoved = true; break; } } } } } if (hasMoved) { generateNumber(); updateBoard(); } } // 判断水平方向上是否有障碍物 function noBlockHorizontal(row, col1, col2, board) { for (var i = col1 + 1; i < col2; i++) { if (board[row][i] !== 0) { return false; } } return true; } // 判断垂直方向上是否有障碍物 function noBlockVertical(col, row1, row2, board) { for (var i = row1 + 1; i < row2; i++) { if (board[i][col] !== 0) { return false; } } return true; } // 监听键盘事件 window.addEventListener('keydown', function(event) { switch (event.keyCode) { case 37: // 左箭头 event.preventDefault(); moveLeft(); break; case 38: // 上箭头 event.preventDefault(); moveUp(); break; case 39: // 右箭头 event.preventDefault(); moveRight(); break; case 40: // 下箭头 event.preventDefault(); moveDown(); break; } }); // 初始化游戏 init(); </script> </body> </html> ``` 在这个示例中,我们使用了 HTML、CSS 和 JavaScript 来构建一个简单的 2048 游戏游戏面板是一个 4x4 的网格,每个格子里可以显示一个数字。游戏的目标是通过移动数字,使得相同数字的格子合并成一个更大的数字,直到达到 2048 为止。 在代码中,我们定义了一个 `board` 数组来存储游戏面板上每个格子的数字,以及一个 `score` 变量来记录当前得分。我们还定义了一些函数来初始化游戏、生成随机数、更新游戏面板、移动数字等。 在 `moveLeft`、`moveRight`、`moveUp` 和 `moveDown` 函数中,我们使用了 `noBlockHorizontal` 和 `noBlockVertical` 函数来判断水平方向和垂直方向上是否有障碍物。这些函数用于判断当前位置是否可以移动数字,以及数字是否可以合并。 最后,在页面加载完成后,我们调用 `init` 函数来初始化游戏。我们还监听了键盘事件,当用户按下左、右、上、下箭头键时,分别调用相应的移动函数来移动数字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值