c语言a 寻路算法,JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例

本文实例讲述了JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法。分享给大家供大家参考,具体如下:

完整实例代码如下:

A*寻路算法

#stage {

border: 1px solid lightgray;

}

window.onload = function () {

var stage = document.querySelector('#stage'),

ctx = stage.getContext('2d');

stage.width = 600;

stage.height = 600;

var row = 7, column = 7, r = 40;

//取区域随机数x>=min && x

function randInt(min, max) {

max = max || 0;

min = min || 0;

var step = Math.abs(max - min);

var st = (arguments.length < 2) ? 0 : min;//参数只有一个的时候,st = 0;

var result;

result = st + (Math.ceil(Math.random() * step)) - 1;

return result;

}

//普里姆算法生成连通图的二维数组 row 行 column 列

function primMaze(r, c) {

//初始化数组

function init(r, c) {

var a = new Array(2 * r + 1);

//全部置1

for (let i = 0, len = a.length; i < len; i++) {

var cols = 2 * c + 1;

a[i] = new Array(cols);

for (let j = 0, len1 = a[i].length; j < len1; j++) {

a[i][j] = 1;

}

}

//中间格子为0

for (let i = 0; i < r; i++)

for (let j = 0; j < c; j++) {

a[2 * i + 1][2 * j + 1] = 0;

}

return a;

}

//处理数组,产生最终的数组

function process(arr) {

//acc存放已访问队列,noacc存放没有访问队列

var acc = [], noacc = [];

var r = arr.length >> 1, c = arr[0].length >> 1;

var count = r * c;

for (var i = 0; i < count; i++) {

noacc[i] = 0;

}

//定义空单元上下左右偏移

var offs = [-c, c, -1, 1], offR = [-1, 1, 0, 0], offC = [0, 0, -1, 1];

//随机从noacc取出一个位置

var pos = randInt(count);

noacc[pos] = 1;

acc.push(pos);

while (acc.length < count) {

var ls = -1, offPos = -1;

offPos = -1;

//找出pos位置在二维数组中的坐标

var pr = pos / c | 0, pc = pos % c, co = 0, o = 0;

//随机取上下左右四个单元

while (++co < 5) {

o = randInt(0, 5);

ls = offs[o] + pos;

var tpr = pr + offR[o];

var tpc = pc + offC[o];

if (tpr >= 0 && tpc >= 0 && tpr <= r - 1 && tpc <= c - 1 && noacc[ls] == 0) {

offPos = o;

break;

}

}

if (offPos < 0) {

pos = acc[randInt(acc.length)];

}

else {

pr = 2 * pr + 1;

pc = 2 * pc + 1;

//相邻空单元中间的位置置0

arr[pr + offR[offPos]][pc + offC[offPos]] = 0;

pos = ls;

noacc[pos] = 1;

acc.push(pos);

}

}

}

var a = init(r, c);

process(a);

return a;

//返回一个二维数组,行的数据为2r+1个,列的数据为2c+1个

}

//栅格线条

function drawGrid(context, color, stepx, stepy) {

context.strokeStyle = color;

context.lineWidth = 0.5;

for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {

context.beginPath();

context.moveTo(i, 0);

context.lineTo(i, context.canvas.height);

context.stroke();

}

for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {

context.beginPath();

context.moveTo(0, i);

context.lineTo(context.canvas.width, i);

context.stroke();

}

}

//方块创造方法

function createRect(x, y, r, c) {

ctx.beginPath();

ctx.fillStyle = c;

ctx.rect(x, y, r, r);

ctx.fill();

}

//定义点对象【a*点对象】

function Point(x, y) {

this.x = x;

this.y = y;

this.parent = null;

this.f = 0;

this.g = 0;

this.h = 0;

//当前点状态,0:表示在openlist 1:表示closelist,-1表示还没处理

this.state = -1;

//flag表明该点是否可通过

this.flag = 0;

}

//把普通二维数组(全部由1,0表示)的转换成a*所需要的点数组

function convertArrToAS(arr) {

var r = arr.length, c = arr[0].length;

var a = new Array(r);

for (var i = 0; i < r; i++) {

a[i] = new Array(c);

for (var j = 0; j < c; j++) {

var pos = new Point(i, j);

pos.flag = arr[i][j];

a[i][j] = pos;

}

}

return a;

}

//A*算法,pathArr表示最后返回的路径

function findPathA(pathArr, start, end, row, col) {

//添加数据到排序数组中

function addArrSort(descSortedArr, element, compare) {

var left = 0;

var right = descSortedArr.length - 1;

var mid = (left + right) >> 1;

while (left <= right) {

var mid = (left + right) >> 1;

if (compare(descSortedArr[mid], element) == 1) {

left = mid + 1;

}

else if (compare(descSortedArr[mid], element) == -1) {

right = mid - 1;

}

else {

break;

}

}

for (var i = descSortedArr.length - 1; i >= left; i--) {

descSortedArr[i + 1] = descSortedArr[i];

}

descSortedArr[left] = element;

}

//判断两个点是否相同

function pEqual(p1, p2) {

return p1.x == p2.x && p1.y == p2.y;

}

//获取两个点距离,采用曼哈顿方法

function posDist(pos, pos1) {

return (Math.abs(pos1.x - pos.x) + Math.abs(pos1.y - pos.y));

}

function between(val, min, max) {

return (val >= min && val <= max)

}

//比较两个点f值大小

function compPointF(pt1, pt2) {

return pt1.f - pt2.f;

}

//处理当前节点

function processCurrpoint(arr, openList, row, col, currPoint, destPoint) {

//get up,down,left,right direct

var ltx = currPoint.x - 1;

var lty = currPoint.y - 1;

for (var i = 0; i < 3; i++){

for (var j = 0; j < 3; j++) {

var cx = ltx + i;

var cy = lty + j;

if ((cx === currPoint.x || cy === currPoint.y) && between(ltx, 0, row - 1) && between(lty, 0, col - 1)) {

var tp = arr[cx][cy];

if (tp.flag === 0 && tp.state !== 1) {

if (pEqual(tp, destPoint)) {

tp.parent = currPoint;

return true;

}

if (tp.state === -1) {

tp.parent = currPoint;

tp.g = 1 + currPoint.g;

tp.h = posDist(tp, destPoint);

tp.f = tp.h + tp.f;

tp.state = 0;

addArrSort(openList, tp, compPointF);

}

else {

var g = 1 + currPoint.g;

if (g < tp.g) {

tp.parent = currPoint;

tp.g = g;

tp.f = tp.g + tp.h;

openList.quickSort(compPointF);

}

}

}

}

}

}

return false;

}

//定义openList

var openList = [];

//定义closeList

var closeList = [];

start = pathArr[start[0]][start[1]];

end = pathArr[end[0]][end[1]];

//添加开始节点到openList;

addArrSort(openList, start, compPointF);

var finded = false;

while ((openList.length > 0)) {

var currPoint = openList.pop();

currPoint.state = 1;

closeList.push(currPoint);

finded = processCurrpoint(pathArr, openList, row, col, currPoint, end);

if (finded) {

break;

}

}

if (finded) {

var farr = [];

var tp = end.parent;

farr.push(end);

while (tp != null) {

farr.push(tp);

tp = tp.parent;

}

return farr;

}

else {

return null;

}

}

//定位屏幕坐标到数组位置

function mapSCPos(i, j) {

return [i / r | 0, j / r | 0];

}

//检测数组中的位置是否存在方块

function mapHasRect(map, i, j) {

return (map[i][j]);

}

var mapArr = primMaze(row, column);

var startRect = {

x: function () {

for (var i = 0, len = mapArr.length; i < len; i++) {

for (var j = 0, len1 = mapArr[i].length; j < len1; j++) {

if (!mapArr[i][j]) {

return j * r;

break;

}

}

}

}(),

y: function () {

for (var i = 0, len = mapArr.length; i < len; i++) {

for (var j = 0, len1 = mapArr[i].length; j < len1; j++) {

if (!mapArr[i][j]) {

return i * r;

break;

}

}

}

}(),

pos: function () {

return [this.x, this.y];

}

},

endRect = {

hasCreate:false,

x:null,

y:null,

pos: function () {

return [this.x, this.y];

}

},

startPoint = mapSCPos(startRect.pos()[1], startRect.pos()[0]),

endPoint,

path = null,

next = null;

//计算路经

function update() {

ctx.clearRect(0, 0, 600, 600);

drawGrid(ctx, 'lightgray', r, r);

//根据地图二维数组创建色块

for (var i = 0, len = mapArr.length; i < len; i++) {

for (var j = 0, len1 = mapArr[i].length; j < len1; j++) {

if (mapArr[i][j]) {

createRect(j * r, i * r, r, "black");

}

}

}

//绘制开始方块

createRect(startRect.x, startRect.y, r, "red");

if (endRect.hasCreate) {

//绘制跟随方块

createRect(endRect.pos()[0], endRect.pos()[1], r, "blue");

endPoint = mapSCPos(endRect.pos()[1], endRect.pos()[0]);

if(path === null){

var ASmap = convertArrToAS(mapArr);

path = findPathA(ASmap, startPoint, endPoint, ASmap.length, ASmap.length);

}else{

next = path.pop();

startRect.y = next.x * r;

startRect.x = next.y * r;

if(path.length===0){

startPoint = mapSCPos(startRect.pos()[1], startRect.pos()[0]);

path = null;

endRect.hasCreate = false;

}

}

}

requestAnimationFrame(update);

}

update();

stage.addEventListener('click', function () {

//标准的获取鼠标点击相对于canvas画布的坐标公式

var x = event.clientX - stage.getBoundingClientRect().left,

y = event.clientY - stage.getBoundingClientRect().top;

var endRectPos = mapSCPos(y, x);//[i,j]

endRect.x = endRectPos[1]*r;

endRect.y = endRectPos[0]*r;

if (mapHasRect(mapArr, endRectPos[0], endRectPos[1])) {

console.log('这个位置已经有方块啦!');

} else {

endRect.pos();

endRect.hasCreate = true;

}

})

};

使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun,测试运行上述代码,可得到如下运行效果:

2241a3f4cbe0881bdd69f97684d8098b.gif

希望本文所述对大家JavaScript程序设计有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在wsl下运行c语言,在Windows10通过WSL架设linux/gcc c语言学习环境

在Windows10通过WSL架设linux/gcc c语言学习环境零&#xff1a;简单介绍与先决条件中国一般的大学C课程中都使用很过时的编译器来进行教授——比如说什么visual studio 6.0啊&#xff0c;dev c啊。以笔者的眼界所看到的C语言教程中&#xff0c;大多都建议学习者在Linux环境下学…

android studio gradle 自动更新,android studio gradle 两种更新方法更新

又快一年没有使用AS了&#xff0c;正好要查看一个Android项目代码&#xff0c;干脆升级到新版试试看新变化&#xff0c;旧版本为3.1.2&#xff0c;目前最新版本为3.4.2&#xff0c;AS的升级是很简单的直接update等待即可.升级完了&#xff0c;打开GIT下载的项目&#xff0c;启动…

android 线性布局蒙层,Android开发 - 掌握ConstraintLayout(一)传统布局的问题

在传统的Android开发中&#xff0c;页面布局占用了我们很多的开发时间&#xff0c;而且面对复杂页面的时候&#xff0c;传统的一些布局会显得非常复杂&#xff0c;每种布局都有特定的应用场景&#xff0c;我们通常需要各种布局结合起来使用来实现复杂的页面。随着ConstraintLay…

android sdk 4.4.4,4.4.4 not in Android SDK manager

问题I need to do some testing with 4.4.4 and it isnt available in my Android SDK Manager?Any ideas on what Im doing wrong?回答1:There is no problem at you Android SDK Manager, you just have to download the API 19.The API 19 is used by all the KitKat devi…

android7.0提示定位,解决android7.0上某些PopuWindow显示位置不正确的问题

网上关于android系统7.0的popupwindow适配的解决方案&#xff0c;基本都是一样的&#xff0c;就是重写PopupWindow里面的方法但是如何进行重写&#xff0c;对于一个初次接触的人来说&#xff0c;是个很头疼的问题。一来是涉及到java基础&#xff0c;二来是涉及到popupwindow的源…

html文档定义层标记是,jsp练习题目201312

《JSP商务网站设计》复习综合题型一、单项选择题1. 关于分页显示&#xff0c;下列的叙述哪一项是不正确的&#xff1f;()A)只编制一个页面是不可能实现分页显示的B)采用一至三个页面都可以实现分页显示C)分页显示中&#xff0c;记录集不必在页面跳转后重新生成D)分页显示中页面…

html一个页面同时加载多个饼图,Html5饼图绘制实现统计图的方法

Html5提供了强大的绘图API&#xff0c;让我们能够使用javascript轻松绘制各种图形。本文将主要讲解使用HTML5绘制饼图(统计图)的方法。先看一下饼图效果&#xff1a;这个图是动态生成的&#xff0c;根据传入的比例参数(数组)&#xff0c;来动态绘制饼图。饼图的大小也是根据高度…

html中半透明效果,CSS半透明效果的属性和场景

在CSS中与半透明效果相关的属性有两个&#xff1a;opacity和rgba。opacity属性的值规定透明度。从 0.0 (完全透明)到 1.0(完全不透明)。设置opacity元素的所有后代元素会随着一起具有透明性&#xff0c;一般用于调整图片或者模块的整体不透明度。IE8 以及更早的版本支持替代的 …

HTML5新增的video标签,HTML5中video标签的使用方法

HTML5中video标签的使用方法发布时间&#xff1a;2020-08-27 11:33:56来源&#xff1a;亿速云阅读&#xff1a;100作者&#xff1a;小新这篇文章将为大家详细讲解有关HTML5中video标签的使用方法&#xff0c;小编觉得挺实用的&#xff0c;因此分享给大家做个参考&#xff0c;希…

开封高级高考2021成绩查询,2021开封市地区高考成绩排名查询,开封市高考各高中成绩喜报榜单...

距离2018年高考还有不到一个月的时间了&#xff0c;很多人在准备最后冲刺的同时&#xff0c;也在关心高考成绩。2018各地区高考成绩排名查询,高考各高中成绩喜报榜单尚未公布&#xff0c;下面是往年各地区高考成绩排名查询,高考各高中成绩喜报榜单&#xff0c;想要了解同学可以…

【清华大学】《逻辑学概论》笔记

教学视频来源 ----第0讲 概要-0.1 讲师介绍0.2 课程内容--第1讲 什么是逻辑学&#xff1f;-1.1 “逻辑和逻辑学1.2 推理和推理形式1.3 有效推理形式1.4 逻辑学的特点1.5 逻辑学的基本准则1.6 逻辑学和其他学科的关系1.7 关于本课程《逻辑学概论》---第2讲 逻辑学的产生与发展-…

公用计算机管理,如何管理公用计算机和私人计算机的文件访问

如何管理公用计算机和私人计算机的文件访问08/07/2014本文内容适用于&#xff1a; Exchange Server 2007 SP3, Exchange Server 2007 SP2, Exchange Server 2007 SP1, Exchange Server 2007上一次修改主题&#xff1a; 2011-08-01本主题将介绍如何为 Microsoft Exchange Server…

Spring Boot 2 学习笔记(1 / 2)

Spring Boot 2 学习笔记&#xff08;2 / 2&#xff09; ---01、基础入门-SpringBoot2课程介绍02、基础入门-Spring生态圈03、基础入门-SpringBoot的大时代背景04、基础入门-SpringBoot官方文档架构05、基础入门-SpringBoot-HelloWorld06、基础入门-SpringBoot-依赖管理特性07、…

Spring Boot 2 学习笔记(2 / 2)

Spring Boot 2 学习笔记&#xff08;1 / 2&#xff09; ---45、web实验-抽取公共页面46、web实验-遍历数据与页面bug修改47、视图解析-【源码分析】-视图解析器与视图48、拦截器-登录检查与静态资源放行49、拦截器-【源码分析】-拦截器的执行时机和原理50、文件上传-单文件与多…

写出表格的结构html,一个面试题,根据json结构生成html表格

我的输入是{A1: {B1: {C1: {D1: 1233,D2: 11},C2: {D1: 10,D2: 10}},B2: {C1: {D1: 10,D2: 11},C2: {D1: 10,D2: 10},C3: {D1: 10,D2: 10}}}}用什么框架都可以&#xff0c;只要求输出以下table&#xff0c; json的最后一个节点就是table的最后一个column&#xff0c;并且只能占…

足球点球 html5,身为西甲第一点球手,C罗只有5次让点经历,难怪点球破门过百...

当今足坛是C罗和梅西的天下&#xff0c;两人持续不断的刷新创造各种记录&#xff0c;让球迷应接不暇。比梅西大2岁的C罗近期更是开挂&#xff0c;今天说他的点球。C罗现在是西甲历史上的第一点球手本赛季西甲第21轮&#xff0c;皇马客场4-1大胜瓦伦西亚&#xff0c;C罗在比赛中…

Spring Cloud 学习笔记(2 / 3)

Spring Cloud 学习笔记&#xff08;1 / 3&#xff09; Spring Cloud 学习笔记&#xff08;3 / 3&#xff09; ---56_Hystrix之全局服务降级DefaultProperties57_Hystrix之通配服务降级FeignFallback58_Hystrix之服务熔断理论59_Hystrix之服务熔断案例(上)60_Hystrix之服务熔断…

html5的colgroup,HTML colgroup 标签 | 菜鸟教程

HTML 标签实例 和 标签为表格中的三个列设置了背景色&#xff1a;ISBNTitlePrice3476896My first HTML$53尝试一下 浏览器支持所有主流浏览器都支持 标签。标签定义及使用说明 标签用于对表格中的列进行组合&#xff0c;以便对其进行格式化。通过使用 标签&#xff0c;可以向…

Spring Cloud 学习笔记(3 / 3)

Spring Cloud 学习笔记&#xff08;1 / 3&#xff09; Spring Cloud 学习笔记&#xff08;2 / 3&#xff09; ---108_Nacos之Linux版本安装109_Nacos集群配置(上)110_Nacos集群配置(下)111_Sentinel是什么112_Sentinel下载安装运行113_Sentinel初始化监控114_Sentinel流控规则…

普林斯顿计算机科学系,普林斯顿大学计算机科学系

普林斯顿大学计算机科学系研究生阶段开设有以下学位项目&#xff0c;分别是计算机科学博士&#xff1a;为期5年&#xff0c;要求申请者本科毕业&#xff0c;不限专业背景&#xff0c;但通常被录取的学生拥有工程、理科或数学专业背景&#xff0c;未设定本科GPA要求&#xff0c;…