日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

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

發布時間:2023/12/13 HTML 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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,測試運行上述代碼,可得到如下運行效果:

希望本文所述對大家JavaScript程序設計有所幫助。

總結

以上是生活随笔為你收集整理的c语言a 寻路算法,JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。