IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 小游戏2048 实现思路及代码(vue) -> 正文阅读

[JavaScript知识库]小游戏2048 实现思路及代码(vue)

相信大家都玩过一款经典的小游戏2048,下面我分享一下我实现这款小游戏思路(可能有更好的方法,欢迎大家留言)

数字的表示与更新

  • 用一个长度为16的一维数组来表示数字矩阵,索引表示位置,值表示数字大小。
    例如:在这里插入图片描述

numbers = [4, 2, 4, 4, 0, 0, 2, 2, 0, 0, 0, 2, 4, 0, 0, 0]
值为零的数字隐藏。
每一次滑动后重新对numbers赋一次值。

向上滑动

  • 假如进行一次上滑,效果是这样的(这里先不添加新数字):
    在这里插入图片描述
    我们可以看到:两个相同的数字相撞时,这两个数字相加。要怎么实现呢?

  • 先把长度为16的数组按顺序拆分为4个长度为4的数组并合并组成一个二维数组。

    numbers = [4, 2, 4, 4, 0, 0, 2, 2, 0, 0, 0, 2, 4, 0, 0, 0]
    arr = [[4, 2, 4, 4],[0, 0, 2, 2], [0, 0, 0, 2], [4, 0, 0, 0]]

这样的话,arr的每一元素就表示数字矩阵的每一行(从上到下)。

  • 判断第一行的数字如果和第二行的数字同一列是否相等或者有一个数字为零,如果是则相加,并把相加结果赋值给第一行,最后把第二行相加过的数字清零。
  • 第二行和第三行、第三行和第四行也执行以上操作。

过程大致如下:
在这里插入图片描述

  • 上述过程重复三次:
    在这里插入图片描述
    额。。。和结果不太一样。arr的正确结果应该是:

    [8, 2, 4, 4]
    [0, 0, 2, 4]
    [0, 0, 0, 0]
    [0, 0, 0, 0]

    这是因为同一列的数字只能相加一次,所以

  • 定义一个数组added,在数字相加的时候记录该数字的列数并存到added里,每次数字相加前检查added里面有没有该数字列数,如果有,就不相加了。(上述例子中added = [3])

  • 最后把二维数组arr转为一维数组赋值给numbers,这样就完成了一次数字矩阵的更新了。

    到这里一次上滑动作就完成了。

向下、左、右滑动

有了上滑的思路,其他方向滑动只是大同小异。

我们只需要改变二维数组arr向一位数组numbers取数字的顺序就行了。

在这里插入图片描述在这里插入图片描述
所以滑动的行为可以封装成一个函数,根据参数判断是哪一个方向即可。
function move(direction){

}

增加数字

在游戏开始的时候和一次滑动动作后,向为0的数字中随机选一个变为2

代码(vue)

<template>
	<div class="play">
		<div class="content" @touchstart="start" @touchend="end">
			<div class="item" v-for="(item,index) in numbers" :key='index'>
				<div :class="item===0?numberZeroClass:'number'"
				:style="itemStyles[Math.log2(item)]">{{item}}</div>
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				numbers: [],
				numberZeroClass: 'number numberZero', // 格子为零将数字隐藏
				itemStyles:'color:#000; background:', // 根据数字大小设置颜色
				startX: '', //开始触摸的x坐标
				startY: '', //开始触摸的y坐标
			}
		},
		onLoad() {
			this.numbers = [8, 2, 4, 4, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0]
			this.itemStyles = [
				'color:#000; background:#FFF3EE',
				'color:#000; background:#FFDAC8',
				'color:#000; background:#FFBD9D',
				'color:#000; background:#FF9D6F',
				'color:#000; background:#FF5809',
				'color:#000; background:#FF8040',
				'color:#fff; background:#F75000',
				'color:#fff; background:#BB3D00',
				'color:#fff; background:#842B00',
				'color:#fff; background:#424200',
				'color:#fff; background:#000079',
				'color:#fff; background:#2F0000',
			]
			// this.fristNumber()
		},
		methods: {
			fristNumber(){
				this.numbers[Math.floor(Math.random()*16)] = 2
			},
			move(direction){
				let arr = []
				let numbers = this.numbers.slice(0) // 深拷贝
				let arrItem = []
				switch(direction){
					case 'up':{
						console.log('up');
						// 从上到下每一行生成一个数组
						numbers.forEach((item, index) => {
							for (let i = 0; i < this.numbers.length / 4; i++) {
								arrItem.push(numbers.shift(index))
							}
							arr.push(arrItem)
							arrItem = []
						})
					}break
					case 'down':{
						// 从下到上每一行生成一个数组
						numbers.forEach((item, index) => {
							for (let i = 0; i < this.numbers.length / 4; i++) {
								arrItem.push(numbers.shift(index))
							}
							arr.unshift(arrItem)
							arrItem = []
						})
					}break
					case 'left':{
						// 从左到右每一列生成一个数组
						let c0 = [],c1 = [],c2 = [],c3 = []
						numbers.forEach((item, index) => {
							if(index % 4 === 0){
								c0.push(item)
							}else if(index % 4 === 1){
								c1.push(item)
							}else if(index % 4 === 2){
								c2.push(item)
							}else{
								c3.push(item)
							}
						})
							arr.push(c0,c1,c2,c3)
					}break
					case 'right':{
						// 从右到左每一列生成一个数组
						let c0 = [],c1 = [],c2 = [],c3 = []
						numbers.forEach((item, index) => {
							if(index % 4 === 0){
								c0.push(item)
							}else if(index % 4 === 1){
								c1.push(item)
							}else if(index % 4 === 2){
								c2.push(item)
							}else{
								c3.push(item)
							}
						})
							arr.push(c3,c2,c1,c0)
					}break
					default :
						console.log('move parameter must one of up、down、left and right of sting type');
					}
					let arrItem1
					let arrItem2
					let added = [] //arrItem1相加过的索引
					for (let i = 0; i < 3; i++) { // 循环三次
						arr.forEach((item2, index2) => {
							if (index2 < arr.length - 1) {
								arrItem1 = item2
								arrItem2 = arr[index2 + 1]
								arrItem1.forEach((item, index) => {
									if (arrItem2[index] === 0 || item === 0) {
										arrItem1[index] += arrItem2[index]
										arrItem2[index] = 0
									} else if (item === arrItem2[index] && item * arrItem2[index] !== 0 &&
										added.indexOf(index) == -1) {
										arrItem1[index] += arrItem2[index]
										arrItem2[index] = 0
										added.push(index)
									}
								})
							}
						})
					}
					let startNumber = this.numbers // 记录初始numbers
					if(direction === 'up'){
						this.numbers = arr.flat()				
						
					}else if(direction === 'down'){
						let numbers2 = []
						arr.forEach((item, index)=>{
							numbers2.push(arr[3-index])
						})
						this.numbers = numbers2.flat()
						
					}else if(direction === 'left'){
						let numbers3 = []
						for (let i = 0; i < arr.length; i++) {
							arr.forEach((item, index)=>{
								numbers3.push(item[i])
							})
						}
						this.numbers = numbers3.flat()
						
					}else if(direction === 'right'){
						let numbers4 = []
						for (let i = 0; i < arr.length; i++) {
							for (let k = 0; k < arr.length; k++){
								numbers4.push(arr[3-k][i])
							}
						}
						this.numbers = numbers4.flat()
					}
					
					
					let endNumber = this.numbers // 记录结束numbers
					// 开始和结束的numbers不相等即存在数字的位置都发生变化,增加数字
					if (startNumber.toString() !== endNumber.toString()) {
						this.addNumber()
					}
				
			},
			//随机添加数字
			addNumber() {
				let arrZeros = [] // numbers中值为零的索引
				this.numbers.forEach((item, index) => {
					if (item === 0) arrZeros.push(index)
				})
				//arrZeros数组中随机取一个值
				let randomItem = arrZeros[Math.floor(Math.random() * arrZeros.length)]
				this.numbers[randomItem] = 2
			},
			getNumberColor(){
				
			},
			start(e) {
				this.startX = Math.floor(e.changedTouches[0].clientX)
				this.startY = Math.floor(e.changedTouches[0].clientY)
			},
			end(e) {
				// x,y为滑动的距离
				let x = Math.floor(e.changedTouches[0].clientX) - this.startX
				let y = Math.floor(e.changedTouches[0].clientY) - this.startY

				if (x > 50 && 0 < y < 50) {
					console.log('右滑')
					this.move('right')
				} else if (x < -50 && 0 < y < 50) {
					console.log('左滑')
					this.move('left')
				} else if (0 < x < 50 && y < -50) {
					console.log('上滑')
					this.move('up')
				} else if (0 < x < 50 && y > 50) {
					console.log('下滑');
					this.move('down')
				}

			}
		},
	}
</script>

<style lang="scss">

	
	.play {
		width: 100%;

		.content {
			display: flex;
			justify-content: space-around;
			box-sizing: border-box;
			flex-wrap: wrap;
			width: 750rpx;
			height: 750rpx;
			
			.item {
				width: 23%;
				height: 23%;
				background: #fff;
				.number {
					color: #fff;
					background: #f6ff43;
					border-radius: 10%;
					text-align: center;
					line-height: 180rpx;
					font-size: 25px;
					font-weight: 600;
				}
				.numberZero {
					background: #D1E9E9;
					font-size: 0px;
				}
			}

		}
	}
</style>



  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 11:57:40  更:2021-08-19 12:00:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:43:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码