我有一个充满对象的数组,其中每个对象都有"退出"导致数组中的其他对象。我想知道如何遍历这些项目"关注"每个出口。
基本思路是创建一个" map"数组中的对象。
基本上,每个对象都是(减少只显示重要部分):
{
id: 0,
name: "stary sobor",
n: -1,
s: 3,
e: 1,
w: -1,
u: -1,
d: -1,
}
基本上,我希望算法能够遵循大于-1
的任何方向(n,s,e,w,u,d)。
我已经尝试将其映射出来,但是当对象有多个退出时,我对非常感到困惑。
这是我的小提琴:http://jsfiddle.net/8kxrp/2/
基本上我想遍历数组并在画布上为每个区域输出一个正方形 - 所以,如果area1有一个"退出"那么我想在area1等的右边显示一个正方形。
答案 0 :(得分:2)
您正在遍历图表。这里的关键点是:
一种简单的方法是使用递归来访问所有出口,同时在已经访问过的房间中存储一些标志:
var visitRoom = function(rooms, roomId) {
if (roomId === -1)
return;
var room = rooms[roomId];
if (room.visited)
return;
room.visited = true;
doSomethingWithRoom(room);
visitRoom(rooms, room.n);
visitRoom(rooms, room.e);
visitRoom(rooms, room.s);
visitRoom(rooms, room.w);
visitRoom(rooms, room.u);
visitRoom(rooms, room.d);
};
visitRoom(rooms, 0); // assuming you're starting at the first room
这里的问题是:
存储room.visited
有点乱,因为它会以遍历算法所需的中间状态污染原始数据。
此代码假设每个房间的ID等于其在数组中的索引。如果不是这种情况,您可能希望找到一种通过其ID获取房间的方法。房间ID和房间对象之间的地图在这种情况下比数组更有用。
递归方法会耗尽大量映射中的堆栈内存。这可以通过使用迭代方法来补救,而不是通过递归访问房间,而是将其ID添加到要访问的房间列表中,然后连续访问列表中的第一个房间,直到它为空。保留未访问的房间列表比为递归调用存储堆栈帧花费更少的内存。
这是解决这些问题的另一种方法:
var visitAll = function(rooms) {
var toVisit = [0];
var visited = {};
while (toVisit.length > 0) {
var roomId = toVisit.pop();
var room = findRoomById(rooms, roomId);
doSomethingWithRoom(room);
visited[roomId] = true;
["n", "s", "e", "w", "u", "d"].forEach(function(exit) {
var exitId = room[exit];
if (exitId !== -1 && !visited[exitId])
toVisit.push(exitId);
});
}
}
var findRoomById = function(rooms, roomId) {
// do whatever you need to find the room with the correct ID
return rooms[roomId];
}
var doSomethingWithRoom = function(room) {
// do what you want here; this will be called once per visited room
}
visitAll(rooms);
如果您还想跟踪每个房间的空间坐标,您也可以根据前一个房间的坐标和出口的方向,在每个房间第一次遇到房间时为其指定位置。紧随其后。
答案 1 :(得分:0)
这实际上取决于您希望如何处理多个退出。
var dirs = ["n", "e", "s", "w", "u", "d"];
var visited = {};
for(var i = 0; i < Areas.length; i++){
for (var j = 0; j < dirs.length; j++) {
if(Areas[i][dirs[j]] > -1){
doSomething(array[i].id, dirs[j], array[i][dirs[j]);
}
};
}
function doSomething(roomID, exitDirection, exitID){
//Called for every exit for every room.
if(visited[exitID]!== true){
visited[exitID] = true;
//Do whatever unique stuff you want to do here.
//This will get called for every new exit room but you may not want that if you're building doors or something.
}
}
答案 2 :(得分:0)
这将为每个元素增加一个&#34;其他&#34; field,带有所有可到达元素的结构化多维对象,以及带有可到达元素的简单列表的allothers数组。
var Chernarus = [
{
id: 0,
name: "stary sobor",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:-1,s:3,e:1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 1,
name: "novy sobor",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:-1,s:2,e:-1,w:0,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 2,
name: "mogilevka",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:1,s:3,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 3,
name: "dubky",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:2,s:4,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 4,
name: "novo selky",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:3,s:5,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 5,
name: "chernogorsk",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:4,s:-1,e:-1,w:6,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
}
];
var toCheck=["n","s","e","w"];
var maxSteps=100;
function getOthers(element,recursion,alreadyDone,alreadyArr) {
if(recursion>maxSteps) return "TOO MANY:INFINITE?";
if(Chernarus[element]==undefined) return "NOT FOUND: "+element;
var item=Chernarus[element];
if(alreadyDone[element]!=undefined) return element+" ALREADY DONE";
alreadyDone[element]=true;
alreadyArr.push(element);
var out={};
for (var ch=0;ch<4;ch++) {
var tc=toCheck[ch];
var dir=item[toCheck[ch]];
if(dir>0) {
out[tc]={pos:dir,others:getOthers(dir,recursion+1,alreadyDone,alreadyArr)};
}
}
return out;
}
for (var i=0;i<Chernarus.length;i++) {
var allothers=[]
Chernarus[i]['others']=getOthers(i,1,[],allothers);
Chernarus[i]['allothers']=allothers;
}
alert(dump(Chernarus,""));
function dump(obj,spc) {
if(obj==undefined) return "<undefined>";
if((typeof obj)=="object") { // obj instanceof Array || obj.toString()=="[object Object]"
var out="";
for(var it in obj) if(obj.hasOwnProperty(it)) {
out+=spc+it+"= {\n";
out+= dump(obj[it],spc+" ");
out+=spc+"}\n";
}
return out;
} else return spc+(obj.toString())+"\n";
}