|
|
@ -1,3 +1,5 @@ |
|
|
|
|
|
|
|
use std::collections::{HashMap, HashSet}; |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Hash, PartialEq, Eq, Clone, Debug, Copy)] |
|
|
|
#[derive(Hash, PartialEq, Eq, Clone, Debug, Copy)] |
|
|
|
pub struct Point(pub i32, pub i32); |
|
|
|
pub struct Point(pub i32, pub i32); |
|
|
|
|
|
|
|
|
|
|
@ -11,3 +13,75 @@ impl Point { |
|
|
|
] |
|
|
|
] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn manhattan(c1: &Point, c2: &Point) -> i32 { |
|
|
|
|
|
|
|
return (c2.0 - c1.0).abs() + (c2.1 - c1.1).abs(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn astar(start: &Point, goal: &Point) -> Vec<Point> { |
|
|
|
|
|
|
|
let mut open_set : HashSet<Point> = HashSet::new(); |
|
|
|
|
|
|
|
open_set.insert(*start); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut came_from: HashMap<Point, Point> = HashMap::new(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut gscore: HashMap<Point, i32> = HashMap::new(); |
|
|
|
|
|
|
|
gscore.insert(*start, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut fscore: HashMap<Point, i32> = HashMap::new(); |
|
|
|
|
|
|
|
fscore.insert(*start, manhattan(&start, &goal)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut answer = Vec::new(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut current: Point = *start; |
|
|
|
|
|
|
|
while !open_set.is_empty() { |
|
|
|
|
|
|
|
let mut min_score = i32::MAX; |
|
|
|
|
|
|
|
for c in open_set.iter() { |
|
|
|
|
|
|
|
let val = fscore[c]; |
|
|
|
|
|
|
|
current = if val < min_score { c.clone() } else { current }; |
|
|
|
|
|
|
|
min_score = if val < min_score { val } else { min_score }; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if current == *goal { |
|
|
|
|
|
|
|
answer.push(current.clone()); |
|
|
|
|
|
|
|
while came_from.contains_key(¤t) { |
|
|
|
|
|
|
|
current = came_from[¤t].clone(); |
|
|
|
|
|
|
|
answer.push(current.clone()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
open_set.remove(¤t); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let current_gscore = gscore[¤t]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let all_neighbors: Vec<Point> = current.get_neighbors(); |
|
|
|
|
|
|
|
for neighbor in all_neighbors.iter() { |
|
|
|
|
|
|
|
let neighbor_score = if gscore.contains_key(&neighbor) { |
|
|
|
|
|
|
|
gscore[neighbor] |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
i32::MAX |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
let score = current_gscore + 1; |
|
|
|
|
|
|
|
if score < neighbor_score { |
|
|
|
|
|
|
|
gscore.insert(neighbor.clone(), score); |
|
|
|
|
|
|
|
fscore.insert(neighbor.clone(), score + manhattan(&neighbor, &goal)); |
|
|
|
|
|
|
|
came_from.insert(neighbor.clone(), current.clone()); |
|
|
|
|
|
|
|
open_set.insert(neighbor.clone()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
answer |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
|
|
|
fn test_astar() { |
|
|
|
|
|
|
|
let start = Point(0, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let goal = Point(10, 10); |
|
|
|
|
|
|
|
let answers: Vec<Point> = astar(&start, &goal); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for a in answers.iter() { |
|
|
|
|
|
|
|
println!("{:?}", &a); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|