Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. use std::collections::{HashMap, BinaryHeap};
  2. use std::ops::{Index, IndexMut};
  3. use std::cmp::{Reverse};
  4.  
  5. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
  6. enum Tile {
  7. Wall,
  8. Ground,
  9. }
  10.  
  11. impl Tile {
  12. pub fn cost(&self) -> u32 {
  13. match self {
  14. Tile::Wall => 0,
  15. Tile::Ground => 1,
  16. }
  17. }
  18. }
  19.  
  20. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
  21. struct Cell {
  22. tile: Tile,
  23. x: usize,
  24. y: usize,
  25. }
  26.  
  27. struct Grid {
  28. data: Vec<Cell>,
  29. size: usize,
  30. }
  31.  
  32. impl Grid {
  33. pub fn new(size: usize) -> Self {
  34. let data = (0..size).map(|x| {
  35. (0..size).map(move |y| {
  36. Cell { tile: Tile::Ground, x, y }
  37. })
  38. }).flatten().collect::<Vec<_>>();
  39. Self {
  40. data,
  41. size: size,
  42. }
  43. }
  44.  
  45. pub fn is_passable(&self, index: (usize, usize)) -> bool {
  46. self.in_bounds(index) && self[index].tile != Tile::Wall
  47. }
  48.  
  49. pub fn in_bounds(&self, index: (usize, usize)) -> bool {
  50. index.0 < self.size && index.1 < self.size
  51. }
  52.  
  53. pub fn neighbors_for(&self, index: (usize, usize)) -> Vec<Cell> {
  54. let direct = [
  55. (index.0 as i32 + 1, index.1 as i32 + 0), // right
  56. (index.0 as i32 + 0, index.1 as i32 + 1), // top
  57. (index.0 as i32 - 1, index.1 as i32 + 0), // left
  58. (index.0 as i32 + 0, index.1 as i32 - 1), // bottom
  59. ];
  60. let direct = direct.iter().filter(|i| {
  61. let i = *i;
  62. i.0 >= 0 && i.1 >= 0
  63. }).map(|i| {
  64. (i.0 as usize, i.1 as usize)
  65. }).filter(|i| {
  66. self.is_passable(*i)
  67. });
  68.  
  69. direct.map(|i| {
  70. self[i]
  71. }).collect()
  72. }
  73. }
  74.  
  75. impl Index<(usize, usize)> for Grid {
  76. type Output = Cell;
  77. fn index<'a>(&'a self, i: (usize, usize)) -> &'a Self::Output {
  78. &self.data[i.0 + self.size * i.1]
  79. }
  80. }
  81.  
  82. impl IndexMut<(usize, usize)> for Grid {
  83. fn index_mut<'a>(&'a mut self, i: (usize, usize)) -> &'a mut Cell {
  84. &mut self.data[i.0 + self.size * i.1]
  85. }
  86. }
  87.  
  88. fn heuristic(a: Cell, b: Cell) -> u32 {
  89. (a.x as i32 - b.x as i32).abs() as u32
  90. + (a.y as i32 - b.y as i32).abs() as u32
  91. }
  92.  
  93. fn a_star_search(grid: &Grid, start: (usize, usize), goal: (usize, usize))
  94. -> Option<(HashMap<Cell, Cell>, HashMap<Cell, u32>, Vec<Cell>)>
  95. {
  96. if grid.is_passable(start) && grid.is_passable(goal) {
  97. let start = grid[start];
  98. let goal = grid[goal];
  99.  
  100. let mut frontier = BinaryHeap::new();
  101. // frontier.push(start, 0);
  102. frontier.push((Reverse(0), start));
  103.  
  104. let mut came_from = HashMap::new();
  105. came_from.insert(start, start);
  106.  
  107. let mut cost_so_far = HashMap::new();
  108. cost_so_far.insert(start, 0);
  109.  
  110. while let Some((Reverse(priority), current)) = frontier.pop() {
  111. println!("current = {:?}, priority = {:?}", current, priority);
  112. if current == goal {
  113. break;
  114. }
  115.  
  116. for next in grid.neighbors_for((current.x, current.y)) {
  117. let new_cost = cost_so_far[&current] + next.tile.cost();
  118.  
  119. let next_cost = cost_so_far.get(&next);
  120. if next_cost.is_none() || new_cost < *next_cost.unwrap() {
  121. println!("new_cost = {:?}", new_cost);
  122. println!("heuristic = {:?}", heuristic(next, goal));
  123. let priority = new_cost + heuristic(next, goal);
  124. // frontier.push(next, priority);
  125. frontier.push((Reverse(priority), next));
  126. cost_so_far.insert(next, new_cost);
  127. came_from.insert(next, current);
  128. }
  129. }
  130. }
  131.  
  132.  
  133. let mut path = Vec::new();
  134. let mut current = goal;
  135. while current != start {
  136. println!("current = {:?}", current);
  137. path.push(current);
  138. current = came_from[&current];
  139. }
  140. path.reverse();
  141.  
  142. Some((came_from, cost_so_far, path))
  143. } else {
  144. None
  145. }
  146. }
  147.  
  148. fn main() {
  149. let grid = Grid::new(20);
  150.  
  151. // grid[(1,1)].tile = Tile::Wall;
  152. // grid[(1,2)].tile = Tile::Wall;
  153. // grid[(1,3)].tile = Tile::Wall;
  154. // grid[(1,4)].tile = Tile::Wall;
  155.  
  156. if let Some((_came_from, cost_so_far, path)) = a_star_search(&grid, (0, 0), (19, 19)) {
  157. let mut graph = vec![0; grid.size * grid.size];
  158.  
  159. for (cell, cost) in cost_so_far.iter() {
  160. graph[cell.x + cell.y * grid.size] = *cost;
  161. }
  162.  
  163. println!("Cost grid");
  164. for x in 0..grid.size {
  165. for y in 0..grid.size {
  166. print!("{:3}", graph[x + y * grid.size]);
  167. }
  168. println!();
  169. }
  170.  
  171. println!("Path grid");
  172. println!("{:?}", grid[(1,0)]);
  173. let mut graph = grid.data.iter().map(|c| match c.tile {
  174. Tile::Wall => '#',
  175. Tile::Ground => '-',
  176. }).collect::<Vec<_>>();
  177. for cell in path {
  178. graph[cell.x + cell.y * grid.size] = '*';
  179. }
  180. graph[0] = 's';
  181. graph[19 + 19 * grid.size] = 'e';
  182.  
  183. for x in 0..grid.size {
  184. for y in 0..grid.size {
  185. print!("{}", graph[x + y * grid.size]);
  186. }
  187. println!();
  188. }
  189.  
  190. // for x in _came_from {
  191. // println!("{:?}", x);
  192. // }
  193.  
  194. // for (cf, csf) in came_from.iter().zip(cost_so_far.iter()) {
  195. // println!("{:?}: {:?}", cf, csf);
  196. // }
  197. }
  198. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement