vue3+uniapp在微信小程序实现一个2048小游戏

news/2024/7/20 3:46:06 标签: uni-app, 微信小程序, 小程序

一、效果展示

二、代码

<template>
	<view class="page">
		<view class="top">
			<view class="score">
				得分:{{total}}
			</view>
			<view class="time">
				用时:{{allTime}}s
			</view>
		</view>
		<view class="center">
			<view class="mainBox">
				<view class="row" v-for="(row, rowIndex) in gameBoard" :key="rowIndex">
					<view class="cell" v-for="(cell, cellIndex) in row" :key="cellIndex">
						<!-- 	<view :class="cell!==0?'cellBox':''"> -->
						<view
							:class="cellIndex==newArr[0][1]&&rowIndex==newArr[0][0]||cellIndex==newArr[1][1]&&rowIndex==newArr[1][0]?'newBox':cell!==0?'cellBox':''">
							<view class="colorBox"
								:style="{backgroundColor:cell==2?'#ff3a3a':cell==4?'#ff9b29':cell==8?'#ebff31':cell==16?'#34ff31':cell==32?'#369083':cell==64?'#2e3cff':cell==128?'#c12fff':cell==256?'#ff77ed':cell==512?'#ffe9fe':cell==1024?'#fffcd4':cell==2048?'#04010b':''}">
								<text v-show=" cell!==0&&cell!==1">{{ cell }}</text>
							</view>

						</view>

					</view>
				</view>
			</view>
		</view>
		<view class="bottom">
			<view class="kaishi" v-show="gameStatus==false">
				<view class="flexBox"> <button @click="gameStart()"> 游戏开始</button></view>
			</view>
			<view class="jinxing" v-show="gameStatus==true">
				<view class="flexBox">
					<view class="gameOver">
						<view class="gameOverButton" @click="gameOver()">
							结束
						</view>
					</view>
					<view class="contorl">
						<view class="shang" @click="shang()">

						</view>
						<view class="xia" @click="xia()">

						</view>
						<view class="zuo" @click="zuo()">

						</view>
						<view class="you" @click="you()">

						</view>
					</view>

				</view>

			</view>
		</view>
	</view>
</template>

<script lang="ts" setup>
	import { ref } from 'vue'
	// 游戏状态
	const gameStatus = ref<boolean>(false);
	// 显示的数组
	let gameBoard = ref<number[][]>(Array.from({ length: 4 }, () => Array(4).fill(0)));
	// 新增的俩
	let newArr = ref<number[][]>(Array.from({ length: 2 }, () => Array(2).fill(null)))
	// 得分
	const total = ref<number>();
	// 用时
	const allTime = ref(0)
	const timer1 = ref()
	// 游戏开始
	const gameStart = () => {
		total.value = 0;
		allTime.value = 0
		gameStatus.value = true;
		gameBoard.value = numInit()
		timer1.value = setInterval(() => {
			allTime.value = allTime.value + 1;
		}, 1000)
	}
	// 游戏结束
	const gameOver = () => {
		gameStatus.value = false;
		clearInterval(timer1.value)
		timer1.value = null;
		newArr.value = Array.from({ length: 2 }, () => Array(2).fill(null));

	}
	// 获取随机数的函数
	const getRandomlet = (min, max) => {
		min = Math.ceil(min);
		max = Math.floor(max);
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}
	// 随机初始化数值
	const numInit = () => {
		const array = Array.from({ length: 4 }, () => Array(4).fill(0));
		const positions = [];
		// 生成一个包含所有可能位置的数组  
		for (let i = 0; i < 4; i++) {
			for (let j = 0; j < 4; j++) {
				positions.push({ x: i, y: j });
			}
		}
		// 随机选择6个位置  
		const selectedPositions = [];
		for (let i = 0; i < 6; i++) {
			const randomIndex = getRandomlet(0, positions.length - 1);
			selectedPositions.push(positions[randomIndex]);
			positions.splice(randomIndex, 1); // 从数组中移除已选位置,避免重复选择  
		}
		// 设置前4个位置为2  
		for (let i = 0; i < 4; i++) {
			const position = selectedPositions[i];
			array[position.x][position.y] = 2;
		}
		// 对于剩下的2个位置,随机设置为4或8  
		for (let i = 4; i < 6; i++) {
			const position = selectedPositions[i];
			const randomValue = getRandomlet(1, 2) === 1 ? 4 : 8;
			array[position.x][position.y] = randomValue;
		}
		return array;
	}
	// 旋转数组
	const rotate90Clockwise = (matrix) => {
		const n = matrix.length;
		let rotatedMatrix = Array.from({ length: n }, () => []);

		// 顺时针旋转90度
		for (let i = 0; i < n; i++) {
			for (let j = 0; j < n; j++) {
				rotatedMatrix[j][n - i - 1] = matrix[i][j];
			}
		}

		return rotatedMatrix;
	}
	// 累计与填入
	const addNum = (arr) => {
		let copiedArray = JSON.parse(JSON.stringify(arr));
		let defen = 0;
		for (let i = 0; i < copiedArray.length; i++) {
			for (let j = 0; j < copiedArray[i].length; j++) {
				// 找到第一个不为0
				if (copiedArray[i][j] !== 0) {
					for (let p = 0; p < j; p++) {
						if (copiedArray[i][p] == copiedArray[i][j]) {
							copiedArray[i][p] = copiedArray[i][j] + copiedArray[i][p];
							defen = defen + copiedArray[i][p] / 2;
							copiedArray[i][j] = 0;
						}
						// 移动到第一个0
						if (copiedArray[i][p] == 0) {
							copiedArray[i][p] = copiedArray[i][j];
							copiedArray[i][j] = 0;
						}
					}
				}

			}
		}
		total.value = total.value + defen
		return copiedArray;
	}
	// 添加新数字
	const addRandomNumbersToZeros = (arr) => {
		let matrix = JSON.parse(JSON.stringify(arr));
		// 存储所有值为0的元素的坐标  
		let zeroIndices = [];

		// 遍历二维数组,找到值为0的元素的坐标  
		for (let i = 0; i < matrix.length; i++) {
			for (let j = 0; j < matrix[i].length; j++) {
				if (matrix[i][j] === 0) {
					zeroIndices.push([i, j]);
				}
			}
		}

		// 如果没有0,则无法添加数字  
		if (zeroIndices.length < 2) {
			gameOver()
			return;
		}

		// 从所有0的坐标中随机选择两个  
		let randomIndices = zeroIndices.sort(() => 0.5 - Math.random()).slice(0, 2);

		// 为这两个坐标对应的元素添加随机数字  
		let randomNumbers = [2, 4, 8];
		for (let index of randomIndices) {
			let [row, col] = index;
			let randomNumber = randomNumbers[Math.floor(Math.random() * randomNumbers.length)];
			matrix[row][col] = randomNumber;
		}
		newArr.value = randomIndices;
		return matrix;
	}

	// 移动
	const moveAndMerge = (dir) => {
		if (dir == 'shang') {
			gameBoard.value = addNum(gameBoard.value)
		}
		else if (dir == 'zuo') {
			let newArr = JSON.parse(JSON.stringify(gameBoard.value));
			newArr = rotate90Clockwise(addNum(rotate90Clockwise(rotate90Clockwise(rotate90Clockwise(newArr)))))
			gameBoard.value = newArr
		} else if (dir == 'you') {
			let newArr = JSON.parse(JSON.stringify(gameBoard.value));
			newArr = rotate90Clockwise(rotate90Clockwise(rotate90Clockwise(addNum(rotate90Clockwise(newArr)))))
			gameBoard.value = newArr
		} else if (dir == 'xia') {
			let newArr = JSON.parse(JSON.stringify(gameBoard.value));
			newArr = rotate90Clockwise(rotate90Clockwise(addNum(rotate90Clockwise(rotate90Clockwise(newArr)))))
			gameBoard.value = newArr
		}
		gameBoard.value = addRandomNumbersToZeros(gameBoard.value)
	}
	// 操作
	const shang = () => {
		moveAndMerge('shang')
	}
	const xia = () => {
		moveAndMerge('xia')
	}
	const zuo = () => {
		moveAndMerge('zuo')
	}
	const you = () => {
		moveAndMerge('you')
	}
</script>

<style lang="scss" scoped>
	.page {
		width: 100vw;
		overflow: hidden;
		height: 100vh;
		background-color: #c6ffe6;
		display: flex;
		flex-direction: column;
		font-family: cuteFont;

		.top {
			width: 80%;
			height: 20vw;
			display: flex;
			align-items: center;
			margin-left: 10%;
			font-size: 2rem;

			.score {
				flex: 1;

			}

			.time {
				flex: 1;

			}
		}

		.center {
			width: 100vw;
			height: 100vw;


			.mainBox {
				width: 80%;
				margin: 10% 10%;
				height: 80%;
				border-radius: 15px;
				display: flex;

				.row {
					flex: 1;
					display: flex;
					flex-direction: column;
				}

				.cell {
					flex: 1;
					border: 1px solid #ff80c2;
					background-color: #b5f2ff;
					display: flex;
					justify-content: center;
					align-items: center;
					color: #ffffff;
					font-size: 2rem;

					.newBox {
						width: 90%;
						height: 90%;
						background-color: #9d6fff;
						border-radius: 15px;
						display: flex;
						justify-content: center;
						align-items: center;
						animation: newBox 0.5s;
					}

					.cellBox {
						width: 90%;
						height: 90%;
						background-color: #9d6fff;
						border-radius: 15px;

					}

					.colorBox {
						width: 100%;
						border-radius: 15px;
						height: 100%;
						display: flex;
						justify-content: center;
						align-items: center;
					}
				}
			}
		}

		.bottom {
			flex: 1;
			position: relative;

			.kaishi {
				width: 100%;
				height: 100%;
				background-color: #86ff61;
				position: absolute;
				.flexBox {
					width: inherit;
					height: inherit;
					display: flex;
					justify-content: center;
					align-items: center;
				}
			}

			.jinxing {
				width: 100%;
				height: 100%;
				position: absolute;

				.flexBox {
					width: inherit;
					height: inherit;
					display: flex;
					flex-direction: row;

					.contorl {
						flex: 1;


						.shang {
							width: 40px;
							height: 40%;
							position: absolute;
							left: 50%;
							background-color: #ff0777;
							clip-path: polygon(0% 50%, 50% 0%, 100% 50%, 80% 50%, 80% 100%, 20% 100%, 20% 50%);
						}

						.shang:hover {
							border: 1px solid #3d37ff;
						}

						.xia {
							width: 40px;
							height: 40%;
							position: absolute;
							top: 50%;
							left: 50%;
							background-color: #ff0777;
							clip-path: polygon(20% 0%, 80% 0%, 80% 50%, 100% 50%, 50% 100%, 0% 50%, 20% 50%);
						}

						.xia:hover {
							border: 1px solid #3d37ff;
						}

						.zuo {
							width: 120px;
							height: 40px;
							position: absolute;
							top: calc(50% - 30px);
							left: calc(50% - 120px);
							background-color: #ff0777;
							clip-path: polygon(0% 50%, 50% 0%, 50% 20%, 100% 20%, 100% 80%, 50% 80%, 50% 100%);
						}

						.zuo:hover {
							border: 1px solid #3d37ff;
						}

						.you {
							width: 120px;
							height: 40px;
							position: absolute;
							top: calc(50% - 30px);
							left: calc(50% + 40px);
							background-color: #ff0777;
							clip-path: polygon(0% 20%, 50% 20%, 50% 0%, 100% 50%, 50% 100%, 50% 80%, 0% 80%);
						}

						.you:hover {
							border: 1px solid #3d37ff;
						}
					}

					.gameOver {
						.gameOverButton {
							width: 50px;
							height: 100%;
							font-size: 2rem;
							display: flex;
							justify-content: center;
							align-items: center;
							background-color: #fff;
							border-radius: 0 15px 0 0;
							border: 1px solid #a860ff;
						}

					}

				}

			}
		}
	}

	@keyframes newBox {
		0% {
			width: 0%;
			height: 0%;
		}

		100% {
			width: 90%;
			height: 90%;
		}
	}
</style>

三、体验地址

小程序>微信小程序搜索《静远的工具箱》:偶数求和那个功能


http://www.niftyadmin.cn/n/5407064.html

相关文章

Nginx支持的第三方模块概览

Nginx支持的第三方模块众多,涵盖了从安全性增强到性能优化,再到特定功能扩展的多个方面。其中一些知名的第三方模块包括:ngx_http_ssl_module(提供SSL/TLS加密)、ngx_http_gzip_static_module(静态文件压缩)、ngx_http_auth_request_module(基于子请求的身份验证)、ng…

Windows Docker 部署 Jenkins

一、简介 今天介绍一下在 Windows Docker 中部署 Jenkins 软件。在 Windows Docker 中&#xff0c;分为两种情况 Linux 容器和 Windows 容器。Linux 容器是通常大多数使用的方式&#xff0c;Windows 容器用于 CI/CD 依赖 Windows 环境的情况。 二、Linux 容器 Linux 容器内部…

多线程环境中使用UdpClient,适当的同步机制

在多线程环境中使用UdpClient时&#xff0c;适当的同步机制是非常重要的&#xff0c;以防止数据竞争和不一致的状态。以下是一些建议的同步机制&#xff1a; 使用锁&#xff08;Lock&#xff09;&#xff1a; 在C#中&#xff0c;你可以使用lock关键字来确保在给定时间内只有一个…

掌握未来技术:一站式深度学习学习平台体验!

介绍&#xff1a;深度学习是机器学习的一个子领域&#xff0c;它模仿人脑的分析和学习能力&#xff0c;通过构建和训练多层神经网络来学习数据的内在规律和表示层次。 深度学习的核心在于能够自动学习数据中的高层次特征&#xff0c;而无需人工进行复杂的特征工程。这种方法在图…

学习python的地11天,昨天偶遇她失败了

昨天是目标偶遇她的第二次&#xff0c;我猜测是由于没算准时间&#xff0c;故而今日计划8:15那班车。 如果今日没有偶遇上&#xff0c;那就明天呗&#xff0c;后天&#xff0c;大后天&#xff0c;就像随机数一样&#xff0c;总有命中那一刻 昨天&#xff0c;我尝试给我的linu…

苹果电脑专业的Mac垃圾清理工具CleanMyMac X4.14.7

CleanMyMac X是一款专业的Mac清理工具&#xff0c;它具有强大的功能和易用的界面&#xff0c;可以帮助用户快速清理Mac上的无用文件和垃圾&#xff0c;优化系统性能&#xff0c;提升电脑运行速度。 该软件的核心功能包括智能扫描与清理、应用程序管理、隐私保护和系统维护等。…

canvas签名页面跟着滑动bug

记录一个花了两天时间才解决的bug&#xff0c;过程非常难受&#xff0c;需求是一个阅读合同的小程序界面&#xff0c;在阅读完成后弹出遮罩层进行签名 问题&#xff1a;在弹出层签名的时候遮罩层下面的合同也在跟着滑动&#xff0c;安卓端没有这个问题&#xff0c;真机调试的io…

开放签电子签章企业版V1.6(紧急更新)

开放签持续迭代多个版本后&#xff0c;陆陆续续已经有客户在使用&#xff0c;但是在使用过程中发现很多用户体验问题&#xff0c;导致用户不能顺畅、友好的使用系统。因此&#xff0c;本次版本升级主要解决若干用户体验问题&#xff0c;使用户能够更加顺畅的使用开放签。本次升…