基本信息
源码名称:自动贪吃蛇.html
源码大小:0.01M
文件格式:.html
开发语言:CSS
更新时间:2020-08-03
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
自动贪吃蛇.html
自动贪吃蛇.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> 自动贪吃蛇游戏</TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> <style> html, body { overflow: hidden; touch-action: none; content-zooming: none; position: absolute; margin: 0; padding: 0; width: 100%; height: 100%; background: #111; } canvas { position: absolute; width: 100vh; height: 100vh; margin: auto; top: 0; bottom: 0; left: 0; right: 0; user-select: none; background: #000; cursor: pointer; } </style> </HEAD> <BODY> <canvas id="c"></canvas> <script> var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // Adapted from https://johnflux.com/2015/05/02/nokia-6110-part-3-algorithms/ { // init map var init = function init() { snake.body.length = 0; map.init(10, 10); map.generate_r(-1, -1, 0, 0); map.generateTourNumber(); snake.addHead(0, 0); snake.addHead(1, 0); snake.addHead(2, 0); food.add(); if (!running) { running = true; run(); } }; // main loop var run = function run() { if (snake.body.length < map.size) requestAnimationFrame(run);else running = false; if (fullcpgrid || frame % 4 === 0) { snake.move(snake.nextDirection()); ctx.clearRect(0, 0, canvasWidth, canvasHeight); map.draw(); } }; var map = { // init map init: function init(width, height) { var _this = this; this.width = width; this.height = height; this.size = width * height; this.scale = Math.min(canvasWidth, canvasHeight) / Math.max(this.width, this.height); // Hamiltonian Cycle // flags var _array2D = this.array2D(width, height, true); var _array2D2 = _slicedToArray(_array2D, 2); this.tour = _array2D2[0]; this.setTour = _array2D2[1]; var _array2D3 = this.array2D(width / 2, height / 2); var _array2D4 = _slicedToArray(_array2D3, 2); this.isVisited = _array2D4[0]; this.setVisited = _array2D4[1]; var _array2D5 = this.array2D(width / 2, height / 2); var _array2D6 = _slicedToArray(_array2D5, 2); this.canGoRight = _array2D6[0]; this.setGoRight = _array2D6[1]; var _array2D7 = this.array2D(width / 2, height / 2); var _array2D8 = _slicedToArray(_array2D7, 2); this.canGoDown = _array2D8[0]; this.setGoDown = _array2D8[1]; var _array2D9 = this.array2D(width, height); var _array2D10 = _slicedToArray(_array2D9, 2); this.isSnake = _array2D10[0]; this.setSnake = _array2D10[1]; this.canGoLeft = function (x, y) { if (x === 0) return false; return _this.canGoRight(x - 1, y); }; this.canGoUp = function (x, y) { if (y === 0) return false; return _this.canGoDown(x, y - 1); }; }, // directions Left: 1, Up: 2, Right: 3, Down: 4, // flat 2D array array2D: function array2D(width, height, protect) { var data = new Uint16Array(width * height); return [function (x, y) { return data[x width * y]; }, protect ? function (x, y, value) { var i = x width * y; if (!data[i]) data[i] = value; } : function (x, y, value) { data[x width * y] = value; }]; }, // test snake collision collision: function collision(x, y) { if (x < 0 || x >= this.width) return true; if (y < 0 || y >= this.height) return true; return this.isSnake(x, y) !== 0; }, // path distance distance: function distance(a, b) { if (a < b) return b - a - 1;else return b - a - 1 this.size; }, // Hamiltonian Cycle generate_r: function generate_r(fromx, fromy, x, y) { if (x < 0 || y < 0 || x >= this.width / 2 || y >= this.height / 2) return; if (this.isVisited(x, y)) return; this.setVisited(x, y, 1); if (fromx !== -1) { if (fromx < x) this.setGoRight(fromx, fromy, 1);else if (fromx > x) this.setGoRight(x, y, 1);else if (fromy < y) this.setGoDown(fromx, fromy, 1);else if (fromy > y) this.setGoDown(x, y, 1); } for (var i = 0; i < 2; i ) { var r = Math.floor(Math.random() * 4); switch (r) { case 0: this.generate_r(x, y, x - 1, y); break; case 1: this.generate_r(x, y, x 1, y); break; case 2: this.generate_r(x, y, x, y - 1); break; case 3: this.generate_r(x, y, x, y 1); break; } } this.generate_r(x, y, x - 1, y); this.generate_r(x, y, x 1, y); this.generate_r(x, y, x, y 1); this.generate_r(x, y, x, y - 1); }, // find next direction in cycle findNextDir: function findNextDir(x, y, dir) { if (dir === this.Right) { if (this.canGoUp(x, y)) return this.Up; if (this.canGoRight(x, y)) return this.Right; if (this.canGoDown(x, y)) return this.Down; return this.Left; } else if (dir === this.Down) { if (this.canGoRight(x, y)) return this.Right; if (this.canGoDown(x, y)) return this.Down; if (this.canGoLeft(x, y)) return this.Left; return this.Up; } else if (dir === this.Left) { if (this.canGoDown(x, y)) return this.Down; if (this.canGoLeft(x, y)) return this.Left; if (this.canGoUp(x, y)) return this.Up; return this.Right; } else if (dir === this.Up) { if (this.canGoLeft(x, y)) return this.Left; if (this.canGoUp(x, y)) return this.Up; if (this.canGoRight(x, y)) return this.Right; return this.Down; } return -1; //Unreachable }, // generate Hamiltonian Cycle generateTourNumber: function generateTourNumber() { var x = 0; var y = 0; var dir = this.canGoDown(x, y) ? this.Up : this.Left; var number = 0; do { var nextDir = this.findNextDir(x, y, dir); switch (dir) { case this.Right: this.setTour(x * 2, y * 2, number ); if (nextDir === dir || nextDir === this.Down || nextDir === this.Left) this.setTour(x * 2 1, y * 2, number ); if (nextDir === this.Down || nextDir === this.Left) this.setTour(x * 2 1, y * 2 1, number ); if (nextDir === this.Left) this.setTour(x * 2, y * 2 1, number ); break; case this.Down: this.setTour(x * 2 1, y * 2, number ); if (nextDir === dir || nextDir === this.Left || nextDir === this.Up) this.setTour(x * 2 1, y * 2 1, number ); if (nextDir === this.Left || nextDir === this.Up) this.setTour(x * 2, y * 2 1, number ); if (nextDir === this.Up) this.setTour(x * 2, y * 2, number ); break; case this.Left: this.setTour(x * 2 1, y * 2 1, number ); if (nextDir === dir || nextDir === this.Up || nextDir === this.Right) this.setTour(x * 2, y * 2 1, number ); if (nextDir === this.Up || nextDir === this.Right) this.setTour(x * 2, y * 2, number ); if (nextDir === this.Right) this.setTour(x * 2 1, y * 2, number ); break; case this.Up: this.setTour(x * 2, y * 2 1, number ); if (nextDir === dir || nextDir === this.Right || nextDir === this.Down) this.setTour(x * 2, y * 2, number ); if (nextDir === this.Right || nextDir === this.Down) this.setTour(x * 2 1, y * 2, number ); if (nextDir === this.Down) this.setTour(x * 2 1, y * 2 1, number ); break; } dir = nextDir; switch (nextDir) { case this.Right: x; break; case this.Left: --x; break; case this.Down: y; break; case this.Up: --y; break; } } while (number !== this.size); }, // get next node getNext: function getNext(x, y, dir) { switch (dir) { case this.Left: if (x) return { x: x - 1, y: y }; break; case this.Up: if (y) return { x: x, y: y - 1 }; break; case this.Right: return { x: x 1, y: y }; break; case this.Down: return { x: x, y: y 1 }; break; } return { x: x, y: y }; }, // draw map draw: function draw() { ctx.beginPath(); ctx.strokeStyle = "#fff"; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.lineWidth = this.scale * 0.5; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = snake.body[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var b = _step.value; ctx.lineTo(this.scale * 0.5 b.x * this.scale, this.scale * 0.5 b.y * this.scale); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } ctx.stroke(); if (snake.body.length < map.size - 1) { ctx.beginPath(); ctx.fillStyle = "#f80"; ctx.arc(this.scale * 0.5 food.x * this.scale, this.scale * 0.5 food.y * this.scale, 0.4 * this.scale, 0, 2 * Math.PI); ctx.fill(); } } }; // food object var food = { x: 0, y: 0, // add random food add: function add() { var emptyNodes = []; for (var x = 0; x < map.width; x) { for (var y = 0; y < map.height; y) { if (!map.collision(x, y)) emptyNodes.push({ x: x, y: y }); } } if (emptyNodes.length) { var p = emptyNodes[Math.floor(Math.random() * emptyNodes.length)]; this.x = p.x; this.y = p.y; } } }; // the snake var snake = { body: [], head: { x: 0, y: 0 }, removeTail: function removeTail() { var p = this.body.shift(); map.setSnake(p.x, p.y, 0); }, addHead: function addHead(x, y) { this.head.x = x; this.head.y = y; this.body.push({ x: x, y: y }); map.setSnake(x, y, 1); }, move: function move(dir) { var next = map.getNext(this.head.x, this.head.y, dir); this.addHead(next.x, next.y); if (next.x === food.x && next.y === food.y) { food.add(); } else this.removeTail(); }, // snake IA nextDirection: function nextDirection() { var x = this.head.x; var y = this.head.y; var pathNumber = map.tour(x, y); var distanceToFood = map.distance(pathNumber, map.tour(food.x, food.y)); var distanceToTail = map.distance(pathNumber, map.tour(snake.body[0].x, snake.body[0].y)); var cuttingAmountAvailable = distanceToTail - 4; var numEmptySquaresOnBoard = map.size - snake.body.length - 1; if (distanceToFood < distanceToTail) cuttingAmountAvailable -= 1; var cuttingAmountDesired = distanceToFood; if (cuttingAmountDesired < cuttingAmountAvailable) cuttingAmountAvailable = cuttingAmountDesired; if (cuttingAmountAvailable < 0) cuttingAmountAvailable = 0; var canGoRight = !map.collision(x 1, y); var canGoLeft = !map.collision(x - 1, y); var canGoDown = !map.collision(x, y 1); var canGoUp = !map.collision(x, y - 1); var bestDir = -1; var bestDist = -1; var dist = 0; if (canGoRight) { dist = map.distance(pathNumber, map.tour(x 1, y)); if (dist <= cuttingAmountAvailable && dist > bestDist) { bestDir = map.Right; bestDist = dist; } } if (canGoLeft) { dist = map.distance(pathNumber, map.tour(x - 1, y)); if (dist <= cuttingAmountAvailable && dist > bestDist) { bestDir = map.Left; bestDist = dist; } } if (canGoDown) { dist = map.distance(pathNumber, map.tour(x, y 1)); if (dist <= cuttingAmountAvailable && dist > bestDist) { bestDir = map.Down; bestDist = dist; } } if (canGoUp) { dist = map.distance(pathNumber, map.tour(x, y - 1)); if (dist <= cuttingAmountAvailable && dist > bestDist) { bestDir = map.Up; bestDist = dist; } } if (bestDist >= 0) return bestDir; if (canGoUp) return map.Up; if (canGoLeft) return map.Left; if (canGoDown) return map.Down; if (canGoRight) return map.Right; return map.Right; } }; // init canvas var canvas = document.getElementById("c"); var ctx = canvas.getContext('2d'); var canvasWidth = canvas.width = 600; var canvasHeight = canvas.height = 600; canvas.onclick = init; var running = false; var frame = 0; var fullcpgrid = window.location.href.indexOf("fullcpgrid") > -1; init(); } </script> </BODY> </HTML>