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二级联动购物车,Android实现二级购物车的全选加反选、总价功能

本文实例为大家分享了Android实现二级购物车的全选加反选、总价的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下MainActivityimport android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.LinearLayoutManager;imp…

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安全检测报告

1.高危 Intent Scheme URL攻击详情&#xff1a;恶意页面可以通过Intent scheme URL执行基于Intent的攻击建议&#xff1a;将Intent的component/selector设置为null2.高危 WebView应用克隆风险详情&#xff1a;APP使用WebView访问网络&#xff0c;当开启了允许JS脚本访问本地文件…

android定时循环,Android AlarmManager实现定时循环后台任务

这篇文章使用AlarmManager实现了Android定时后台循环任务。使用场景&#xff1a;项目需要app每隔一段时间就去服务端请求一次接口&#xff0c;从而更新本地保存的信息。AlarmManager简介AlarmManager是Android中常用的一种系统级别的提示服务&#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的源…

android 全局 窗口,miui12全局自由窗口app

miui12全局自由窗口app是小米最新更新的系统引用了全局自由窗口功能&#xff0c;在你玩游戏或者是追剧的时候&#xff0c;都可以直接在一个页面上聊天&#xff0c;无需切换那么麻烦&#xff0c;支持多种机型进行使用这个功能&#xff0c;多种模式你可以自由的切换使用&#xff…

LeetCode - Medium - 264. Ugly Number II

Topic MathDynamic ProgrammingHeap Description https://leetcode.com/problems/ugly-number-ii/ Analysis 方法一&#xff1a;遍历自然数&#xff0c;逐个判断是否是丑数。这方法很低效。 方法二&#xff1a;动态数组。 We have an array k of first n ugly number. W…

signature=4abdf782f13579fc1b57d94a0c6ce95c,β-lactam-associated eosinophilic colitis

摘要&#xff1a;A 42-year-old man with a history of childhood asthma presented with a 2-week history of watery diarrhoea and marked peripheral eosinophilia in the setting of recent use of cephalexin. His colonoscopy revealed patchy colitis. Biopsies were c…

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 以及更早的版本支持替代的 …

swift解析html数据类型,ios-Swift:以标签或textVi显示HTML数据

ios-Swift&#xff1a;以标签或textVi显示HTML数据我有一些HTML数据&#xff0c;其中包含标题&#xff0c;段落&#xff0c;图像和列表标签。有没有一种方法可以在一个UITextView或UILabel中显示此数据&#xff1f;12个解决方案146 votes对于Swift 4&#xff1a;extension Stri…

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;想要了解同学可以…

html 5 笔记,HTML5总笔记(一)

一、p、hn、br标签1&#xff0e;2&#xff0e; &#xff1a;注释。3&#xff0e; &#xff1a;一行&#xff0c;一段(在文字后面直接加)。4&#xff0e;&#xff1a;文字中的最大字符(自动换行)。5&#xff0e; &#xff1a;文字中的最大字符(自动换行)。二、b、i、u、s、su…

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

教学视频来源 ----第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…