以最低的成本找到矩阵中的方式

时间:2015-03-21 17:47:12

标签: path-finding

HEL-LO! 有一个10x10的方阵,其中包含从A市到B市的旅行费用。 找到一条路线,以最低的成本提供从城镇到城镇的旅行(将任务实施为HTML + javascript)“。

您能告诉我如何在JavaScript上编写它吗?我不希望动画像FindPath.js一样。表(10x10)并在其他DOM元素中输出结果就足够了。 如果有人遇到这个,请帮帮我。我找到了插件,但没有人允许输入我自己的费用。


确定。我试着这样做(http://experiments.hertzen.com/pathfinding/index.html,第二个变种)。我介绍了自己的费用:

/* 
 * @author Niklas von Hertzen <niklas at hertzen.com>
 */


PathFinding = function(){
    this.nodes = [];    
    this.nodeCounter = 0;
    return this;
};



PathFinding.prototype.addNode = function(x, y){   
    var  node = new PathFinding.Node(x, y);
    node.id = this.nodeCounter++;
    this.nodes.push(node);
    return node;
    
};

PathFinding.Vertex = function(dest, cost) { 
    this.cost = cost || 1;
    this.dest = dest;   
};


PathFinding.prototype.Solver = function(from, to, solver){
    
    if (solver === undefined){
        solver = "astar";
    }
    
    switch(solver.toLowerCase()){
        case "astar":
            return this.AStarSolver(from, to);
            break;
        default:
            alert("Unknown solver "+solver);
    }
    
};

PathFinding.prototype.AStarSolver = function(from, to, startCount){

    var closedset = []; // The set of nodes already evaluated.
    var openset = []; // The set of tentative nodes to be evaluated, initially containing the start node
    var came_from = []; // The map of navigated nodes.
    var goal = to;
    
    openset.push(from);
   
    var route = [];
    var reconstruct_path = function(fromNode){
        
        if (fromNode !== from){
            route.push(fromNode);
            reconstruct_path(came_from[fromNode.id]);
        }else{
            route.push(from);
        }
        return route;
    };
        
    var heurestic_cost_estimate = function(from, to){
        var xDist = Math.abs(from.x - to.x);
        var yDist = Math.abs(from.y - to.y);
        return Math.sqrt(Math.pow(xDist,2) + Math.pow(yDist,2));
        
    };
    
    var start = from.id, g_score = [],  h_score = [], f_score = []; 
    g_score[start] = +startCount;
    h_score[start] = heurestic_cost_estimate(from, to);
    f_score[start] = h_score[start];
	
    
    
    
    while (openset.length > 0){
        var x = null; // current node
        
        for (var i = 0, openset_len = openset.length; i < openset_len; i++){          
            if (x === null || f_score[openset[i].id] < f_score[x.id]){
                x = openset[i];
            }       
        }
        
        // we have reached the goal
        if (x === goal) {
            route.push(goal);
            reconstruct_path(came_from[x.id]);
            return route.reverse();
        }
        
        // delete openset[0];
        openset.splice(openset.indexOf(x),1);
        
        closedset.push(x);
        for(var y = 0, neighbors = x.vertices, neighbor_len = neighbors.length; y < neighbor_len; y++){
		
            var tentative_is_better = false;
            
            var yd = neighbors[y].dest;
            if (closedset.indexOf(yd) > -1){
                continue;
            }
            var tentative_g_score = g_score[x.id] + neighbors[y].cost;
            if (openset.indexOf(yd) === -1){
                openset.push(yd);
                tentative_is_better = true;
            } else if (tentative_g_score < g_score[yd.id]){
                tentative_is_better = true;
            } 
            
            if (tentative_is_better){
                came_from[yd.id] = x;
                g_score[yd.id] = tentative_g_score;
                h_score[yd.id] = heurestic_cost_estimate(yd, to);
                f_score[yd.id] = g_score[yd.id] + h_score[yd.id];
                
            }
        }
    }
    return false;
    
};


PathFinding.Node = function(x, y){
    this.x = x;
    this.y = y;
    this.vertices = [];
    
    return this;  
};


PathFinding.Node.prototype.addVertex = function(dest, cost, oneWay){
    
    var vertex = new PathFinding.Vertex(dest, cost);
    this.vertices.push(vertex);        
    if (oneWay === undefined || oneWay === false){
        var vertex2 = new PathFinding.Vertex(this, cost);
        dest.vertices.push(vertex2);       
    }

    return vertex;
    
};
td{
                width:10px;
                height:10px;
                border:1px solid black;
                cursor:pointer;
            }
            .current{
                border-color:red;
            }
<!DOCTYPE html>
<html><head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>  
        <script type="text/javascript">
            $(function(){
             //output table with my own costs
                function addTable (table){
                    var PathFinder = new PathFinding();
					table = $('#table2');
					tableRowsLen = $('#table2 tr').length;
					tableColLen = $('#table2 tr')[0].cells.length;
       
                    var nodes = [];
         
                    for (var r = 0; r < tableRowsLen; r++){
                        nodes[r] = [];
                    
                        for (var c = 0; c < tableColLen; c++){
                             	
                            // add walls
                            if ((c==3 && r == 3) || (c==4 && r == 3) || (c==5 && r == 3) || (c==6 && r == 3) || (c==6 && r == 4) || (c==6 && r == 5)){
                                $('#table2').children('tbody').children('tr').eq(r).children('td').eq(c).css('background','black');  
															
                            }else{
                                // add nodes
                                nodes[r][c] = PathFinder.addNode(c, r);
                                // add verticies between nodes
                                if (nodes[r][c-1] !== undefined){
                                    nodes[r][c].addVertex(nodes[r][c-1], $('#table2').children('tbody').children('tr').eq(r).children('td').eq(c-1).html());
                                }
                            
                                if (nodes[r-1] !== undefined && nodes[r-1][c] !== undefined){
                                    nodes[r][c].addVertex(nodes[r-1][c], $('#table2').children('tbody').children('tr').eq(r-1).children('td').eq(c).html());
                                }
                            }
                        }
                    }
                

                    table.delegate("td","click",function(){
                        var current = table.find('.current').removeClass('current'); //from this place path starts
                        $(this).addClass('current');

                        var route = PathFinder.AStarSolver(nodes[current.parent().index()][current.index()],nodes[$(this).parent().index()][$(this).index()], current.html()); //value of cur. elem. Need for considering the cost
                
                        (function(i, route){
						var $a, $b = 0;
                            function timer(){
							
								
                                if (i < route.length){
                                    window.setTimeout(function(){
                                        $a = table.find('tr').eq(route[i].y).find("td").eq([route[i].x]).css('background','green').html();
										$a = +$a; //just for total sum of costs
										$b += $a;
                                
                                        (function(i,route){
                                            window.setTimeout(function(){                               
                                                table.find('tr').eq(route[i].y).find("td").eq([route[i].x]).css('background','transparent');                                                  
                                            },1000);
                                        })(i, route);
                            
                                        i++;
                                        timer();
                                    },40);
                                }
                            }
                            timer();   
                        })(0, route);            
                    
                    });
                    table.find("tr").eq(8).find("td").eq(1).addClass('current');
                    table.find("tr").eq(6).find("td").eq(8).trigger('click');
                
              
                }
                              
                addTable($('#table2')); 
            });        
        </script>
</head>
    <body>
        <h2>Without diagonal movement</h2>
        <table id="table2">
			<tbody>
				<tr>
					<td>1</td>
					<td>2</td>
					<td>3</td>
					<td class="" style="background: transparent;">4</td>
					<td>5</td>
					<td>6</td>
					<td>7</td>
					<td>8</td>
					<td>9</td>
					<td>10</td>
				</tr>
				<tr>
					<td>1</td>
					<td>2</td>
					<td>3</td>
					<td style="background: transparent;">8</td>
					<td style="background: transparent;">9</td>
					<td style="background: transparent;">54</td>
					<td class="" style="background: transparent;">7</td>
					<td>4</td>
					<td>40</td>
					<td>9</td>
				</tr>
				<tr>
					<td>8</td>
					<td>9</td>
					<td style="background: transparent;">10</td>
					<td style="background: transparent;">9</td>
					<td style="background: transparent;">3</td>
					<td class="" style="background: transparent;">5</td>
					<td style="background: transparent;">9</td>
					<td style="background: transparent;">15</td>
					<td>54</td>
					<td>54</td>
				</tr>
				<tr>
					<td>89</td>
					<td>1</td>
					<td style="background: transparent;">5</td>
					<td>9</td>
					<td>2</td>
					<td>78</td>
					<td>25</td>
					<td style="background: transparent;">45</td>
					<td style="background: transparent;">4</td>
					<td>8</td>
				</tr>
				<tr>
					<td>8</td>
					<td style="background: transparent;">9</td>
					<td style="background: transparent;">9</td>
					<td>8</td>
					<td>7</td>
					<td>7</td>
					<td>9</td>
					<td style="background: transparent;">6</td>
					<td class="" style="background: transparent;">7</td>
					<td>9</td>
				</tr>
				<tr>
					<td>8</td>
					<td class="" style="background: transparent;">4</td>
					<td style="background: transparent;">1</td>
					<td style="background: transparent;">9</td>
					<td class="" style="background: transparent;">3</td>
					<td style="background: transparent;">5</td>
					<td>7</td>
					<td style="background: transparent;">3</td>
					<td style="background: transparent;">4</td>
					<td>10</td>
				</tr>
				<tr>
					<td>4</td>
					<td style="background: transparent;">15</td>
					<td class="" style="background: transparent;">9</td>
					<td style="background: transparent;">8</td>
					<td style="background: transparent;">7</td>
					<td style="background: transparent;">6</td>
					<td style="background: transparent;" class="">5</td>
					<td style="background: transparent;">7</td>
					<td class="" style="background: transparent;">3</td>
					<td>9</td>
				</tr>
				<tr>
					<td style="background: transparent;">7</td>
					<td style="background: transparent;">1</td>
					<td>6</td>
					<td>1</td>
					<td>7</td>
					<td>9</td>
					<td style="background: transparent;">8</td>
					<td style="background: transparent;">9</td>
					<td>4</td>
					<td>3</td>
				</tr>
				<tr>
					<td class="current" style="background: transparent;">8</td>
					<td class="" style="background: transparent;">3</td>
					<td style="background: transparent;">2</td>
					<td style="background: transparent;">9</td>
					<td style="background: transparent;">1</td>
					<td style="background: transparent;">4</td>
					<td style="background: transparent;">5</td>
					<td>8</td>
					<td>9</td>
					<td>7</td>
				</tr>
				<tr>
					<td>4</td>
					<td>9</td>
					<td>6</td>
					<td>3</td>
					<td>5</td>
					<td>4</td>
					<td>7</td>
					<td>9</td>
					<td>6</td>
					<td>3</td>
				</tr>
			</tbody>
		</table>
</body></html>

但代码的行为并不是我所期望的。请帮忙。错误在哪里?

Link to playground here

或者这里:http://jsbin.com/ninolufiqa/1/edit?html,css,js,output

1 个答案:

答案 0 :(得分:0)

我对JavaScript知之甚少,但您描述的问题听起来像Dijkstra's algorithm

希望有所帮助。