簡單路徑查詢

應(yīng)用場景

? ? ? ? ? 棋盤類的路徑選擇。? ? ?

作用效果??

? ? ? ? 從棋盤上隨機或指定位置中選擇一個起點,按照規(guī)定好的數(shù)量和方向(例如:上、下、左、右)去隨機的選擇相鄰的模塊,每個模塊只會選擇一次,如果數(shù)量未達(dá)到指定要求時返回找到的最大的路線。

實現(xiàn)原理

? ? ? ? 主要用棧的方法實現(xiàn)

? ? ? ? 選擇好第一個節(jié)點后,節(jié)點進(jìn)棧,

????????按照規(guī)定好的方向去搜索下一個節(jié)點,

????????????????找到后進(jìn)棧,刪除來時方向,標(biāo)記為不可選,加入到備選返回隊列中

? ? ? ? ? ? ? ? 未找到,棧內(nèi)元素出棧,檢查棧是否為空,

? ? ? ? ? ? ? ? ? ? ? ? 不為空,棧頂元素搜索下一節(jié)點

? ? ? ? ? ? ? ? ? ? ? ? 空,將此次遍歷的所有節(jié)點置為不可選,從新選擇開始節(jié)點,如無開始節(jié)點結(jié)束查找。


?代碼實現(xiàn)

var Utils = require('geoUtils');

/**

* createMap函數(shù)將返回這樣的數(shù)據(jù)類型的二維數(shù)組

* @param {*} item

* @param {*} canSelect

* @param {*} directions //此數(shù)據(jù)將在選擇路徑時再賦值? ? createMap時不進(jìn)行賦值

*/

function MapInformation(item, canSelect, position, directions) {

? ? this.item = item;

? ? this.canSelect = canSelect;

? ? this.position = position;

? ? this.directions = directions;

}

var MapUtils = {

? ? DirectionEnum: {

? ? ? ? UP: { x: -1, y: 0 },

? ? ? ? DOWN: { x: 1, y: 0 },

? ? ? ? LEFT: { x: 0, y: -1 },

? ? ? ? RIGHT: { x: 0, y: 1 },

? ? ? ? UPPER_LEFT: { x: -1, y: -1 },

? ? ? ? UPPER_RIGHT: { x: -1, y: 1 },

? ? ? ? LOWER_LEFT: { x: 1, y: -1 },

? ? ? ? LOWER_RIGHT: { x: 1, y: 1 },

? ? },

? ? /**

? ? * 根據(jù)給定的道具集合,創(chuàng)建二維數(shù)據(jù)集

? ? * @param {*} items 道具集合(1維)

? ? * @param {*} numCols 行數(shù)

? ? * @param {*} numVols 列數(shù)

? ? * @returns 返回包裝了items的二維數(shù)據(jù)集,用于搜索功能。

? ? */

? ? createMap(items, numCols, numVols) {

? ? ? ? //將要返回的對象

? ? ? ? var ret = {

? ? ? ? ? ? //用于探索的二維數(shù)組

? ? ? ? ? ? array: [],

? ? ? ? ? ? //用于記錄步數(shù)不足maxSteps的item的數(shù)組

? ? ? ? ? ? notEnough: [],

? ? ? ? };

? ? ? ? //記錄數(shù)組items當(dāng)前位置的變量

? ? ? ? var index = 0;

? ? ? ? for (var i = 0; i < numCols; i++) {

? ? ? ? ? ? ret.array.push([]);

? ? ? ? ? ? for (var j = 0; j < numVols; j++) {

? ? ? ? ? ? ? ? //獲得item? 同時index更新

? ? ? ? ? ? ? ? var item = items[index++];

? ? ? ? ? ? ? ? var mapObj = new MapInformation(item, true, { x: i, y: j });

? ? ? ? ? ? ? ? ret.array[i].push(mapObj);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return ret;

? ? },

? ? /**

? ? *

? ? * @param {*} map createMap函數(shù)返回的對象

? ? * @param {*} directions 可以選擇的方向

? ? * @param {*} maxSteps 想要走幾步

? ? * @param {*} useStrict 當(dāng)步數(shù)不足maxSteps時是否返回選到的其它的最大步數(shù)

? ? * @param {*} start 起點對象數(shù)組[{col:0,vol:0},{col:1,vol:1}]

? ? * @example

? ? * var result = MapUtils.serachMap(map,

? ? ? ? *? [MapUtils.DirectionEnum.up, MapUtils.DirectionEnum.down],

? ? ? ? *? 2, true);

? ? ? ? */

? ? searchMap(map, directions, maxSteps, useStrict, start) {

? ? ? ? var mapObjArray = this._localSearchMap(map, directions, maxSteps, useStrict, start);

? ? ? ? var itemArray = this._mapObjArrayToItemArray(mapObjArray);

? ? ? ? return itemArray;

? ? },

? ? /**

? ? *

? ? * @param {*} map

? ? * @param {*} PreinstallObjs [{directions:dir,maxSteps:num,useStrict,start:{}},{directions:dir,maxSteps:num,start:{}}]

? ? */

? ? searchMapByPreinstall(map, PreinstallObjs) {

? ? ? ? var pObj = Utils.array.random(PreinstallObjs, 1, true)[0];

? ? ? ? return this.searchMap(map, pObj.directions, pObj.maxSteps, pObj.useStrict, pObj.start);

? ? },

? ? /**

? ? *

? ? * @param {*} map createMap函數(shù)返回的對象

? ? * @param {*} directions 可以選擇的方向

? ? * @param {*} maxSteps 想要走幾步

? ? * @param {*} useStrict 當(dāng)步數(shù)不足maxSteps時是否返回選到的其它的最大步數(shù)

? ? * @example

? ? * var result = MapUtils.serachMap(map,

? ? *? [MapUtils.DirectionEnum.up, MapUtils.DirectionEnum.down],

? ? *? 2, true);

? ? */

? ? _localSearchMap(map, directions, maxSteps, useStrict, start) {

? ? ? ? var ret = [];

? ? ? ? //記錄本次便利未達(dá)到指定步數(shù)的路線

? ? ? ? var notEnough = [];

? ? ? ? //用于判斷item的棧

? ? ? ? var storehouse = new Array(maxSteps);

? ? ? ? //棧指針 指向棧頂元素

? ? ? ? var s = -1;

? ? ? ? //用于記錄當(dāng)前已經(jīng)選擇的mapObj的數(shù)組

? ? ? ? var selectMapObj = [];

? ? ? ? //添加可選擇的方向

? ? ? ? this._addDirections(map.array, directions);

? ? ? ? var canSelectMapObjs = this._getCanSelectObj(map.array, start);

? ? ? ? do {

? ? ? ? ? ? //每次循環(huán)前清空數(shù)組

? ? ? ? ? ? selectMapObj = [];

? ? ? ? ? ? //回復(fù)數(shù)據(jù)記錄

? ? ? ? ? ? this._recoverNotEnough(notEnough);

? ? ? ? ? ? this._addDirections(notEnough, directions);

? ? ? ? ? ? // notEnough = [];

? ? ? ? ? ? //選擇第一個節(jié)點

? ? ? ? ? ? var firstMapObj = this._selectFirstObj(canSelectMapObjs);

? ? ? ? ? ? if (firstMapObj == false)

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? //入棧

? ? ? ? ? ? storehouse[++s] = firstMapObj;

? ? ? ? ? ? //加入選擇隊列

? ? ? ? ? ? selectMapObj.push(firstMapObj);

? ? ? ? ? ? var lastMapObj = firstMapObj;

? ? ? ? ? ? for (var i = 0; i < maxSteps - 1; i++) {

? ? ? ? ? ? ? ? lastMapObj = this._selectNextObj(map.array, lastMapObj);

? ? ? ? ? ? ? ? if (lastMapObj != null) {

? ? ? ? ? ? ? ? ? ? //入棧

? ? ? ? ? ? ? ? ? ? storehouse[++s] = lastMapObj;

? ? ? ? ? ? ? ? ? ? //加入選擇隊列

? ? ? ? ? ? ? ? ? ? selectMapObj.push(lastMapObj);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else {

? ? ? ? ? ? ? ? ? ? //棧內(nèi)元素為空本次尋找結(jié)束? 將當(dāng)前記錄的item數(shù)組添加到notEnough中

? ? ? ? ? ? ? ? ? ? if (--s < 0) {

? ? ? ? ? ? ? ? ? ? ? ? notEnough.push(selectMapObj);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? //棧不為空 棧頂元素出棧 新的棧頂元素繼續(xù)尋找

? ? ? ? ? ? ? ? ? ? lastMapObj = storehouse[s];

? ? ? ? ? ? ? ? ? ? //本次未選到mapObj? i-- 保證總量達(dá)到maxSteps

? ? ? ? ? ? ? ? ? ? i--;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? if (selectMapObj.length == maxSteps) {

? ? ? ? ? ? ? ? ret = selectMapObj;

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? } while (canSelectMapObjs.length > 0);

? ? ? ? if (ret.length == 0 && useStrict == true) {

? ? ? ? ? ? ret = this._findLongestArrayInNotEnough(notEnough);

? ? ? ? }

? ? ? ? this._recoverNotEnough(notEnough);

? ? ? ? return ret;

? ? },

? ? /**

? ? * 撤銷本次查找的不足路線的canSelect

? ? * @param {*} notEnough

? ? */

? ? _recoverNotEnough(notEnough) {

? ? ? ? notEnough.forEach(notEnoughArray => {

? ? ? ? ? ? notEnoughArray.forEach(element => {

? ? ? ? ? ? ? ? element.canSelect = true;

? ? ? ? ? ? });

? ? ? ? });

? ? },

? ? /**

? ? * 添加方向

? ? * @param {*} mapArray

? ? * @param {*} directions

? ? */

? ? _addDirections(mapArray, directions) {

? ? ? ? mapArray.forEach(mapObjArray => {

? ? ? ? ? ? mapObjArray.forEach(mapIns => {

? ? ? ? ? ? ? ? mapIns.directions = directions.concat();

? ? ? ? ? ? });

? ? ? ? });

? ? },

? ? /**

? ? * 獲得map中可以選擇的所有mapObj

? ? * @param {*} mapArray

? ? */

? ? _getCanSelectObj(mapArray, start) {

? ? ? ? //獲得可選擇的obj

? ? ? ? var ret = [];

? ? ? ? if (start == null) {

? ? ? ? ? ? var numCols = mapArray.length;

? ? ? ? ? ? var numVols = mapArray[0].length;

? ? ? ? ? ? for (var i = 0; i < numCols; i++) {

? ? ? ? ? ? ? ? for (var j = 0; j < numVols; j++) {

? ? ? ? ? ? ? ? ? ? var mapObj = mapArray[i][j];

? ? ? ? ? ? ? ? ? ? if (mapObj.canSelect == true) {

? ? ? ? ? ? ? ? ? ? ? ? ret.push(mapObj);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? var mapObj = mapArray[start.col][start.vol];

? ? ? ? ? ? if (mapObj.canSelect == true) {

? ? ? ? ? ? ? ? ret.push(mapObj);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return ret;

? ? },

? ? /**

? ? * 隨機選擇一個item為初始節(jié)點

? ? * @param {*} canSelectMapObjs

? ? */

? ? _selectFirstObj(canSelectMapObjs) {

? ? ? ? if (canSelectMapObjs.length == 0)

? ? ? ? ? ? return false;

? ? ? ? var firstMapObj = Utils.array.random(canSelectMapObjs, 1, true)[0];

? ? ? ? firstMapObj.canSelect = false;

? ? ? ? return firstMapObj;

? ? },

? ? /**

? ? * 根據(jù)lastMapObj中記錄的directions選擇下一個mapObj選擇失敗返回null

? ? * @param {*} mapArray

? ? * @param {*} lastMapObj

? ? */

? ? _selectNextObj(mapArray, lastMapObj) {

? ? ? ? for (var i = 0; i < lastMapObj.directions.length;) {

? ? ? ? ? ? //隨機選擇一個方向并且刪除使用過的方向

? ? ? ? ? ? var d = Utils.array.random(lastMapObj.directions, 1, true)[0];

? ? ? ? ? ? var nextX = lastMapObj.position.x + d.x;

? ? ? ? ? ? var nextY = lastMapObj.position.y + d.y;

? ? ? ? ? ? //判斷是否出界

? ? ? ? ? ? if (nextX >= 0 && nextY >= 0 && nextX < mapArray.length && nextY < mapArray[0].length) {

? ? ? ? ? ? ? ? var mapObj = mapArray[nextX][nextY];

? ? ? ? ? ? ? ? //判斷是否可選

? ? ? ? ? ? ? ? if (mapObj.canSelect == true) {

? ? ? ? ? ? ? ? ? ? mapObj.canSelect = false;

? ? ? ? ? ? ? ? ? ? //刪除來時的方向

? ? ? ? ? ? ? ? ? ? this._removeDirection(mapObj.directions, { x: -d.x, y: -d.y });

? ? ? ? ? ? ? ? ? ? return mapObj;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return null;

? ? },

? ? /**

? ? * 第一個參數(shù)是對象數(shù)組objArray

? ? * 第二個參數(shù)是自己定義的對象obj

? ? * 刪除對象數(shù)組中屬性值等于obj中的屬性值的對象

? ? * 例如? ? objArray[{a:1,b:1,c:1},{a:1,b:2,c:1}]

? ? *? ? ? ? obj{b:1}

? ? * 函數(shù)運行完畢后objArray[{a:1,b:2,c:1}]

? ? * @param {*} directions

? ? * @param {*} dir

? ? */

? ? _removeDirection(directions, dir) {

? ? ? ? for (var i = 0; i < directions.length; i++) {

? ? ? ? ? ? var element = directions[i];

? ? ? ? ? ? var isRemove = true;

? ? ? ? ? ? for (var attr in dir) {

? ? ? ? ? ? ? ? if (element[attr] != dir[attr]) {

? ? ? ? ? ? ? ? ? ? isRemove = false;

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? if (isRemove) {

? ? ? ? ? ? ? ? directions.splice(i, 1);

? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? }

? ? ? ? }

? ? },

? ? /**

? ? * 返回notEnough數(shù)組中的最長的一項

? ? * @param {*} notEnough

? ? */

? ? _findLongestArrayInNotEnough(notEnough) {

? ? ? ? var ret = [];

? ? ? ? for (var i = 0; i < notEnough.length; i++) {

? ? ? ? ? ? if (notEnough[i].length > ret.length) {

? ? ? ? ? ? ? ? ret = notEnough[i];

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? Utils.array.remove(notEnough, ret);

? ? ? ? return ret;

? ? },

? ? _mapObjArrayToItemArray(mapObjArray) {

? ? ? ? var ret = [];

? ? ? ? mapObjArray.forEach(element => {

? ? ? ? ? ? ret.push(element.item);

? ? ? ? });

? ? ? ? return ret;

? ? },

};

module.exports = MapUtils;

? ??????????

? ??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容