SHARE
TWEET

main.rs

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