html版贪吃蛇的项目计划书,自动贪吃蛇.html
【实例简介】自动贪吃蛇.html
【实例截图】
【核心代码】
自动贪吃蛇游戏
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;
}
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();
}
html版贪吃蛇的项目计划书,自动贪吃蛇.html相关推荐
- C语言项目@我的贪吃蛇
我的贪吃蛇 一.选择框架 二.输出与输入 1.输出 2.输入 三.蛇移动实现 1.一个点的移动 1)单方向移动 2)多方向移动 2.定长蛇的移动 3.增长蛇的移动 4.移动速度 四.食物的生成 1.随 ...
- 实验项目二:贪吃蛇游戏开发
贪吃蛇游戏开发 一.前言 二.基本流程 三.游戏界面设计 1. 界面构造 2. 蛇的构造 3. 食物构造 四.游戏过程 1. 蛇的移动 2. 蛇吃食物与碰撞检测 五.游戏结束 1. 结束界面 六.扩展 ...
- 数据结构与算法-项目实训-贪吃蛇
目录 一.编译环境 二.知识储备 1.必备函数 2.循环数组 3.发牌算法 4.二维数组的转化 三.核心代码 1.结构体的介绍 2.蛇的产生以及移动 3.食物的产生 四.运行截图 五.总结 一.编 ...
- 软件实习项目二:贪吃蛇的游戏开发
目录 一.实验内容: 二.实验准备 三.程序代码 四.成果展示 一.实验内容: 1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子.玩家能利用上下左右键控制" ...
- 贪吃蛇java 暂停_Java实现贪吃蛇小游戏
三月份的时候用Java写了一个贪吃蛇的小游戏,写完的时候颇有成就感,现在在这里做一下总结. 先把需要用到的图片资源放在这里,分别为上.下.左.右方向的蛇头,蛇身,食物,标题,可以通过右击另存为的方式下 ...
- 门禁管理系统 项目计划书
门禁管理系统 项目计划书 1.背景和意义 随着数据业务和多媒体业务的快速增加,人们对定位与导航的需求日益增大,尤其在集居住场所.办公场所.娱乐场所于一体的大型社区内,人员,车辆多且乱,并且工作性质各不 ...
- 软件测试项目计划书总结,软件测试项目计划书.doc
PAGE PAGE 11 HM项目计划书 项目组长:王菁菁 项目组成员:李应琴 张桦 李小兰 张力芳 1概述 产品简介 为加强中国光大银行零售业务基础性建设.提升客户群体规模,借助近年来房地产市场蓬勃 ...
- 学生宿舍管理项目开发计划书_学生宿舍管理系统项目计划书.doc
学生宿舍管理系统项目计划书.doc 学生宿舍管理系统项目计划书组长张宾成员安长冬刘李阳郭振海张远航学校河南商业高等专科学校专业软件开发和项目管理时间2010年9月28日引言111编写目的112开发背景 ...
- 【项目篇- 项目计划书封面如何设计?(千字图文总结建议)】创新创业竞赛项目计划书
目录 适用范围 1 总体建议 2 简单设计 2.1 形状背景 2.2 图片背景 3 复杂设计 3.1 项目内容展现 3.2 计划书整体设计风格定调 4 互联网+.挑战杯等高等级比赛封面设计 本篇结合了 ...
- 项目计划书、规划文档模板
项目计划书.规划文档模板 最近通过项目实践经历,整理出的一套项目计划书(仅供自己参考梳理思路使用)有喜欢的文末加VX 辛苦码字如有转载请标明出处谢谢!--木研 更新的简版项目规划文档! 原版文件请+v ...
最新文章
- 【干货】南京大学《模式识别》PPT
- 初学Java Web开发,请远离各种框架,从Servlet开发
- WINCE5.0和WINCE6.0的内存与系统架构
- Cambridge Website in a page
- 【numpy求和】numpy.sum()求和
- 倪文迪陪你学蓝桥杯2021寒假每日一题:1.11日(2017省赛A第9题)
- 目前支持DDR3-1600(包括主板超频)最强的CPU是哪个?
- OpenCV源码解析之动态内存管理CvMemStorage与CvSeq
- java tcp连接硬件_SocketTool工具(模拟开发板)和基于socket的java服务器(TCP/IP协议)开发...
- STM32F107+LWIP+FreeRTOS
- Kali 利用setoolkit制作钓鱼网站
- 个人邮箱怎么在微信里登陆?
- 计算机是uefi启动 不能装win7,UEFI模式安装Win7系统方法_Win7 Uefi下安装详细教程
- 用python提取发票扫描件常用的10多个发票信息保存到excel表
- Map接口、HashMap、LinkedHashMap
- 从普通类的角度理解java的enum类型,用自定义类来模拟实现enum类的功能
- 【HDU5984】Pocky(数学)
- 51单片机之DS18B20温度传感器实验
- 2345 好压软件评价
- 基于Labview的信号发生器的设计 [转】
热门文章
- 多线程基础之设计模式Guarded Suspension模式
- 如何实现 1 小时内完成千万级数据运算
- DeepLearning论文阅读笔记(一):Cyclical Learning Rates for Training Neural Networks(CLR)
- 一个国企老兵给后辈们的忠告:三十岁之前远离国企
- python远程监控_Python实现远程端口监控实例
- 基于图像传感器的可见光通信的优缺点分析
- WebSocket对象的“readyState”属性记录连接过程中的状态值
- 如何改变hr标签的颜色
- Mac 苹果电脑创建一个新的管理员账号
- Docker安装mysql:Error starting userland proxy: listen tcp4 0.0.0.0:3306: bind: address already in use