初识前端--贪吃蛇练习

初识前端--贪吃蛇练习


基于JS写了个贪吃蛇,记录一下其中的设计思路等等内容

背景

  • 地图:就是一个二维数组,二维数组的下标对就相当于X、Y轴,无论是身体上的元素,还是要被吃掉的点,都可以转化为二维数组的一个坐标
    一个25*25的二维数组
  • 运动:使用时间间隔,每隔一段时间就重新根据方向计算蛇的位置,保持蛇的移动

基础信息

  • 目标点:随机生成在地图上,且不能生成在蛇身上
  • 蛇:一个坐标数组
  • 方向:根据键盘输入获得,如果没有则保持当前方向

总体思路

  • 初始化地图:打印整张地图
  • 初始化蛇:给定一个默认的蛇身和当前运动方向
  • 初始化目标点
  • 异步获取键盘输入,将其赋值给当前运动方向
  • 根据当前方向预计算下一个坐标点
  • 判断下一个坐标点是否在蛇身体中,或超出边界
    • 如果在身体中或超出边界,不符合游戏规则,游戏结束,跳出时间间隔函数(这里面有一个小坑,下文填)
  • 满足游戏规则,判断预坐标点是否为目标点
    • 如果不是,则将预坐标点加入数组第一个,并删除最后一个
    • 如果是,则将预坐标点加入数组第一个

具体实现

这里只写出思路中的方法和其作用,必要时写点伪代码
属性

  • 蛇身数组
  • 随机点坐标
  • 当前运动方向

方法

  • 展示函数(需要被改色的数据):用来改变需要变色的表格
    功能说明
    • 需要判断传入参数为单个点还是数组
    • 如果是单个点,则直接改色
    • 如果是数组,则数组头和身分别改色
  • 随机点坐标生成函数(蛇数组):用来根据蛇的身体计算随机点坐标
    功能说明
    • 生成一个随机点
    • 判断该点是否在蛇数组中
      • 如果不在,返回该随机点坐标
      • 如果在,递归调用自身,再次生成
  • 初识化地图函数
    功能说明
    • 根据地图尺寸,生成对应行、列的表格
    • 对其中的每个格(td),赋一个id值,这个id值是根据当前行列拼接成的
  • id转坐标函数(id)
    功能说明
    • 传入一个字符串的id值,返回对应的坐标数组
  • 坐标转id函数(坐标)
    功能说明
    • 传入一个坐标数组,返回对应的id

写不动了,懒得写了,直接传代码吧,有问题评论区沟通。。。

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>贪吃蛇练习</title>
		<style type="text/css">
			table {
				margin: auto;
				border: 1px solid white;
			}
			
			td {
				border: 1px solid white;
				border-right-color: 1px solid black;
				border-bottom-color: 1px solid black;
				
				background-color: gainsboro;
				height: 20px;
				width: 20px;
			}
		</style>
	</head>

	<body onkeydown="changeSnakeDirection(event);">
		<table border="1" id="mapTable" cellspacing="1" cellpadding="">
		</table>
	</body>
	<script type="text/javascript">
		//函数起始区
		var MAP_ROWS = 20;
		var MAP_COLS = 20;
		var runTime = 200;

		//定义默认蛇数组
		var snake = ['0_3', '0_2', '0_1', '0_0'];
		//定义随机点的ID
		var randomCellId;
		//定义默认方向
		var nowDirection = 40;
		var inputDirection;

		window.onload = function() {
			//初始化地图表格
			//声明图像区 //定义地图的行数和列数 
			initMapTable();

			//1.显示内容
			//显示随机点和蛇数组
			randomCellId = createRandomCell(snake);
			changeTableColor(snake);

			alert("点击确定开始游戏");

			//开始间隔执行
			var gameStartId = window.setInterval(function() {
				//显示蛇数组
				//changeTableColor(snake);
				//2.获取方向,生成预期坐标点
				//定义初始方向为下,根据键盘事件改变方向,且同方向的正反值无效
				nowDirection = calcSnakeDirection(nowDirection, inputDirection);
//				获取蛇头坐标
				var snakeHeadCoordinate = changeCellIdToCoordinate(snake[0]);
				var nextHeadCoordinate = calcNextHeadCoordinate(snakeHeadCoordinate, nowDirection);
				//3.判断坐标点是否出界或撞到自身
				var gameResult = jundgeGameRule(nextHeadCoordinate);
				if(gameResult) { //4.满足游戏规则,进行蛇数组运动计算
					calcSnakeMove(nextHeadCoordinate, randomCellId);
				} else { //5.游戏结束,提示,重启
					clearInterval(gameStartId);
					userResult = window.confirm("游戏结束,点击确定重新开始");
					if(userResult) {
						location.reload();
					}
				}
			}, runTime);

		}

		//计算蛇数组的运动,根据预落点将其写入蛇数组
		//如果吃掉随机点,将随机点增加到蛇数组
		function calcSnakeMove(nextHeadCoordinate, randomCellId) {
			var nextHeadId = changeRandNumToId(nextHeadCoordinate[0], nextHeadCoordinate[1]);
			var snakeLength = snake.length;
			var snakeLastCell = snake[(snakeLength - 1)];
			snake.unshift(nextHeadId);
			if(nextHeadId != randomCellId) {
				snake.length = snakeLength;
				changeTableColor(snakeLastCell, "gainsboro");
			} else {
				randomCellId = createRandomCell(snake);
			}
			changeTableColor(snake);
			return null;
		}

		//判断游戏规则,满足规则返回True,失败返回False
		function jundgeGameRule(nextHeadCoordinate) {
			//判断是否出界
			nextHeadId = changeRandNumToId(nextHeadCoordinate[0], nextHeadCoordinate[1]);
			if(nextHeadCoordinate[0] < 0 ||
				nextHeadCoordinate[1] < 0 ||
				nextHeadCoordinate[0] >= MAP_COLS ||
				nextHeadCoordinate[1] >= MAP_ROWS
			) {
				return false;
			} else if((!jundgeRandomCellInSnake(nextHeadId)) && !(jundgeRandomCellInSnakeLast(nextHeadId))) { //判断是否撞到自身
				return false;
			} else {
				return true;
			}
		}

		//根据当前蛇头坐标、当前方向计算下一步的坐标
		function calcNextHeadCoordinate(snakeHeadCoordinate, nowDirection) {
			switch(nowDirection) {
				case 37:
					snakeHeadCoordinate[0] = parseInt(snakeHeadCoordinate[0]) - 1;
					break;
				case 39:
					snakeHeadCoordinate[0] = parseInt(snakeHeadCoordinate[0]) + 1;
					break;
				case 38:
					snakeHeadCoordinate[1] = parseInt(snakeHeadCoordinate[1]) - 1;
					break;
				case 40:
					snakeHeadCoordinate[1] = parseInt(snakeHeadCoordinate[1]) + 1;
					break;
				default:
					break;
			}
			return snakeHeadCoordinate;
		}
		//根据键盘按键获取方向
		function changeSnakeDirection(event) {
			//获取按键对象
			var eve = window.event || event;
			//获取用户按键值
			inputDirection = eve.keyCode;
			if(typeof(inputDirection) == "number") {
				return inputDirection;
			} else {
				return null;
			}
		}

		function calcSnakeDirection(nowDirection, inputDirection) {
			//判断有效按键
			if(inputDirection != null &&
				inputDirection >= 37 &&
				inputDirection <= 40) {
				//判断反方向按键失效
				if(Math.abs(nowDirection - inputDirection) != 2) {
					nowDirection = inputDirection;
				}
			}
			return nowDirection;
		}

		//生成随机点
		function createRandomCell(snake) {
			var flagIndex = false;
			while(!flagIndex) {
				//生成map范围内的随机点
				var randomNumX = createRandomNum(MAP_COLS);
				var randomNumY = createRandomNum(MAP_ROWS);
				//将随机点转成id
				randomCellId = changeRandNumToId(randomNumX, randomNumY);
				//判断是否在蛇数组中
				flagIndex = jundgeRandomCellInSnake(randomCellId, flagIndex);
			}
			changeTableColor(randomCellId, "red");
			return randomCellId;
		}

		//判断目标点是否在蛇数组中,如果不存在返回true
		function jundgeRandomCellInSnake(targetCellId, flagIndex) {
			targetCellIdIndex = snake.indexOf(targetCellId);
			if(targetCellIdIndex < 0) {
				flagIndex = true;
			}
			return flagIndex;
		}
		//判断目标点是否在蛇数组的最后一位,如果存在返回true
		function jundgeRandomCellInSnakeLast(targetCellId) {
			targetCellIdIndex = snake.indexOf(targetCellId);
			snakeLastIndex = snake.length - 1;
			if(targetCellIdIndex == snakeLastIndex) {
				return true;
			} else {
				return false;
			}
		}

		//将随机点坐标转成id,返回字符串的id
		function changeRandNumToId(randomNumX, randomNumY) {
			var randCellId = randomNumX + "_" + randomNumY;
			return randCellId;
		}

		//将id转成坐标,返回坐标数组
		function changeCellIdToCoordinate(cellId) {
			cellCoordinate = cellId.split("_");
			return cellCoordinate;
		}

		//生成0到最大值范围内的随机整数
		function createRandomNum(max) {
			var randomNum = parseInt(Math.random() * (max));
			return randomNum;
		}

		//给定坐标或数组,改变对应坐标的颜色
		function changeTableColor(targetCell, col) {
			targetCellType = typeof(targetCell);
			//判断是单个点,还是蛇数组
			if(targetCellType == null) {
				alert('打印图形参数异常!');
				return null;
			} else if(targetCellType == "string") { //判断为单个点
				changeColor(targetCell, col);
			} else { //蛇数组
				changeColor(targetCell[0], "red");
				for(var i = 1; i < targetCell.length; i++) {
					changeColor(targetCell[i], "pink");
				}
			}
		}

		//改变某个坐标的颜色
		function changeColor(targetCell, color) {
			document.getElementById(targetCell).style.backgroundColor = color;
		}

		/**
		 * 初始化地图表格
		 */
		function initMapTable() {
			//获取到table对象
			var mapTable = document.getElementById("mapTable");
			//循环创建行和列
			for(var i = 0; i < MAP_ROWS; i++) {
				//创建行
				var row = mapTable.insertRow(mapTable.rows.length);
				for(var j = 0; j < MAP_COLS; j++) {
					//创建列
					var td = row.insertCell();
					//为每一个td设计一个id
					td.id = j + "_" + i;
				}
			}
		}

		function getElementStyle(obj, attr) {
			if(obj.currentStyle) {
				return obj.currentStyle[attr];
			} else {
				return getComputedStyle(obj, false)[attr];
			}
		}

		/**
		 * 根据给定方向计算下一个预落点是否撞身
		 * @param {Object} nowDirection
		 */
		function jundgeCollision(nowDirection) {
			//获取蛇头坐标
			var snakeHeadCoordinate = changeCellIdToCoordinate(snake[0]);
			var nextHeadCoordinate = calcNextHeadCoordinate(snakeHeadCoordinate, nowDirection);
			//3.判断坐标点是否出界或撞到自身
			var collisionResult = jundgeGameRule(nextHeadCoordinate);
			return collisionResult;
		}
	</script>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值