Показать сообщение отдельно
Старый 20.08.2008, 13:02
Котяра вне форума Посмотреть профиль Отправить личное сообщение для Котяра Посетить домашнюю страницу Котяра Найти все сообщения от Котяра
  № 12  
Ответить с цитированием
Котяра
буду краток
 
Аватар для Котяра

модератор форума
Регистрация: Sep 2003
Адрес: Ближайшее Замкадье
Сообщений: 3,110
Записей в блоге: 28
Отправить сообщение для Котяра с помощью ICQ Отправить сообщение для Котяра с помощью Skype™
во вложении astar.zipтестовая флэшка по Badim'овскому алгоритму - переделан в класс Astra
Собственно сам класс (AS2)
Код:
// Поиск кратчайшего пути по алгоритму A*

class Astar 
{	

	var map:Array;
	var mapStatus:Array;
	var openList:Array;
		
	var mapH:Number;
	var mapW:Number;
	
	// подсчет времени выполнения
	var startFind:Number;
	var stopFind:Number;
	
	 // Constants/configuration - change here as needed! --------------------------------
	var HV_COST = 10; // "Movement cost" for horizontal/vertical moves
	var D_COST = 14; // "Movement cost" for diagonal moves
	
	var log='';
	
	function Astar(_map)
	{
		map = _map;
	}
	
		  
		  
	function  isOpen(y, x) {
			// Return TRUE if the point is on the open list, false if otherwise
			return mapStatus[y][x].open;
		  }
	
	function isClosed(y, x) {
			// Return TRUE if the point is on the closed list, false if otherwise
			return mapStatus[y][x].closed;
		  }
		  
	function nearerSquare() {
			// Returns the square with a lower movementCost + heuristic distance
			// from the open list
			var minimum = 999999;
			var indexFound = 0;
			var thisF = undefined;
			var thisSquare = undefined;
			var i = openList.length;
			// Finds lowest
			while (i-->0) {
			  thisSquare = mapStatus[openList[i][0]][openList[i][1]];
			  thisF = thisSquare.heuristic + thisSquare.movementCost;
			  if (thisF <= minimum) {
				minimum = thisF;
				indexFound = i;
			  }
			}
			// Returns lowest
			return indexFound;
		  }
		  
		  
	function  closeSquare(y, x) {
			// Drop from the open list
			var len = openList.length;
			for (var i=0; i < len; i++) {
			  if (openList[i][0] == y) {
				if (openList[i][1] == x) {
				  openList.splice(i, 1);
				  break;
				}
			  }
			}
			// Closes an open square
			mapStatus[y][x].open = false;
			mapStatus[y][x].closed = true;
		  }
		  
		  
	function  openSquare(y, x, parent, movementCost, heuristic, replacing) {
			// Opens a square
			if (!replacing) {
			  openList.push([y,x]);
			  mapStatus[y][x] = {heuristic:heuristic, open:true, closed:false};
			}
			mapStatus[y][x].parent = parent;
			mapStatus[y][x].movementCost = movementCost;
		  }
		  
		  
		  
	
	function findPath( startX, startY, endX, endY) {
		startFind = new Date().getTime().valueOf();
			
		if (startY == undefined || startX == undefined) return null; // Error: no starting point
		if (endY == undefined || endX == undefined) return null; // Error: no ending point
		
			// Error: Closed start/end point
		
		if (map[startY][startX]==0 || map[endY][endX]==0) 
		{
			log = "Closed start/end point: " + map[startY][startX] + "," + map[endY][endX];
			trace(log);
			return null;
		
		}
		
	

		
		
			// Caches dimensions
			mapH = map.length;
			mapW = map[0].length;
			
			//trace (map);
			// New status arrays
			mapStatus = [];
			for (var i=0; i<mapH; i++){
				mapStatus[i] = [];
				for (var j=0; j<mapW; j++){
					mapStatus[i][j]={};
				}
			}
			// Finds the way given a certain path
			// Ok, now go back to our regular schedule. Find the path! 
			
			// Now really starts
			openList = new Array();
			openSquare (startY, startX, undefined, 0);
		  
			// Loops until there's no other way to go OR found the exit
			while (openList.length > 0 && !isClosed(endY, endX)) {
				// Browse through open squares
				var i = nearerSquare();
				
				var nowY = openList[i][0]/1;
				var nowX = openList[i][1]/1;
				
				// Closes current square as it has done its purpose...
				closeSquare (nowY, nowX);
				// Opens all nearby squares, ONLY if:
				//trace('__now:['+nowX+","+nowY+"]");
				for (var j=nowY-1; j<(nowY+2); j++) {
				for (var k=nowX-1; k<(nowX+2); k++) {
					if (j >= 0 && j < mapH && k >= 0 && k < mapW && map[j][k] != 0) 
					{

					// If not outside the boundaries or at the same point or a diagonal (if disabled) or a diagonal (with a wall next to it)...
					// And if not a wall...
							if (!isClosed(j,k)) {
								// And if not closed... THEN open.

								var movementCost = mapStatus[nowY][nowX].movementCost + ((j==nowY || k==nowX ? HV_COST : D_COST) * map[j][k]);
									if (isOpen(j,k)) {
										// Already opened: check if it's ok to re-open (cheaper)
										if (movementCost < mapStatus[j][k].movementCost) {
										  // Cheaper: simply replaces with new cost and parent.
										  //trace('__replace:('+k+','+j+') for ('+nowX+','+nowY+")");
										  openSquare (j, k, [nowY, nowX], movementCost, undefined, true); // heuristic not passed: faster, not needed 'cause it's already set
										}
									} 
									else 
									{
										// Empty: open.
										var heuristic = (Math.abs (j - endY) + Math.abs (k - endX)) * 10;
										openSquare (j, k, [nowY, nowX], movementCost, heuristic, false);
									}
							} else {
								// Already closed, ignore.
							}
					}
				}
			}
		}
			//Ended
			var pFound = isClosed(endY, endX); // Was the path found?
		  if (pFound) {
			// Ended with path found; generates return path
			var returnPath = [];
			var nowY = endY;
			var nowX = endX;
			var movCost=mapStatus[nowY][nowX].movementCost;
			while ((nowY != startY || nowX != startX)) {
			  returnPath.push([nowX,nowY,movCost]);
			  var newY = mapStatus[nowY][nowX].parent[0];
			  var newX = mapStatus[nowY][nowX].parent[1];
			  nowY = newY;
			  nowX = newX;
			  movCost=mapStatus[nowY][nowX].movementCost;
			}
			returnPath.push([startX,startY,0]);
			var path_xy=[];
			for(var i=returnPath.length-1;i>-1;i--){
				path_xy.push(returnPath[i]);
			}
			stopFind = new Date().getTime().valueOf();
			log="finding time:" + (stopFind - startFind)+"\npath:" + path_xy.join('|');
			trace (log);
			return path_xy;
		  } 
		  else 
		  {
			log="Ended with 0 open squares; ran out of squares, path NOT found";
			trace (log);
			return null;
		  }
		}

}
__________________
Отряд Котовскага