.
This commit is contained in:
@@ -11,7 +11,7 @@ pub fn move_snake(s: &mut Snake, dir: &Point) -> () {
|
|||||||
e.y = s[0].y + dir.y;
|
e.y = s[0].y + dir.y;
|
||||||
s.insert(0, e);
|
s.insert(0, e);
|
||||||
}
|
}
|
||||||
pub fn will_self_collide(s: &Snake, dir: &Point) -> bool {
|
pub fn snake_will_self_collide(s: &Snake, dir: &Point) -> bool {
|
||||||
let next_head = Point {
|
let next_head = Point {
|
||||||
x: s[0].x + dir.x,
|
x: s[0].x + dir.x,
|
||||||
y: s[0].y + dir.y,
|
y: s[0].y + dir.y,
|
||||||
@@ -19,7 +19,27 @@ pub fn will_self_collide(s: &Snake, dir: &Point) -> bool {
|
|||||||
|
|
||||||
(&s[0..(s.len() - 1)]).contains(&next_head)
|
(&s[0..(s.len() - 1)]).contains(&next_head)
|
||||||
}
|
}
|
||||||
|
pub fn get_snake_head(s: &Snake) -> Point {
|
||||||
|
s[0]
|
||||||
|
}
|
||||||
|
pub fn get_next_snake_head(s: &Snake, dir: &Point) -> Point {
|
||||||
|
Point {
|
||||||
|
x: s[0].x + dir.x,
|
||||||
|
y: s[0].y + dir.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_should_return_head() {
|
||||||
|
let s = vec![
|
||||||
|
//
|
||||||
|
Point { x: 3, y: 0 },
|
||||||
|
Point { x: 2, y: 0 },
|
||||||
|
Point { x: 1, y: 0 },
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(get_snake_head(&s), Point { x: 3, y: 0 });
|
||||||
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn it_should_detect_self_collide() {
|
fn it_should_detect_self_collide() {
|
||||||
let mut s = vec![
|
let mut s = vec![
|
||||||
@@ -35,11 +55,22 @@ fn it_should_detect_self_collide() {
|
|||||||
move_snake(&mut s, &DIRECTION_UP);
|
move_snake(&mut s, &DIRECTION_UP);
|
||||||
move_snake(&mut s, &DIRECTION_LEFT);
|
move_snake(&mut s, &DIRECTION_LEFT);
|
||||||
|
|
||||||
assert_eq!(will_self_collide(&s, &DIRECTION_DOWN), true);
|
assert_eq!(snake_will_self_collide(&s, &DIRECTION_DOWN), true);
|
||||||
|
|
||||||
move_snake(&mut s, &DIRECTION_LEFT);
|
move_snake(&mut s, &DIRECTION_LEFT);
|
||||||
|
|
||||||
assert_eq!(will_self_collide(&s, &DIRECTION_DOWN), false);
|
assert_eq!(snake_will_self_collide(&s, &DIRECTION_DOWN), false);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn it_should_detect_self_collide_2() {
|
||||||
|
let s = vec![
|
||||||
|
//
|
||||||
|
Point { x: 3, y: 0 },
|
||||||
|
Point { x: 2, y: 0 },
|
||||||
|
Point { x: 1, y: 0 },
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(snake_will_self_collide(&s, &DIRECTION_LEFT), true);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn it_should_move_snake() {
|
fn it_should_move_snake() {
|
||||||
|
|||||||
@@ -1,21 +1,58 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::grid::{Cell, Grid, Point, DIRECTIONS};
|
use crate::grid::{Cell, Grid, Point, DIRECTIONS};
|
||||||
use crate::snake::Snake;
|
use crate::snake::{
|
||||||
|
get_next_snake_head, get_snake_head, move_snake, snake_will_self_collide, Snake,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn get_route_to_eat_all(
|
pub fn get_route_to_eat_all(
|
||||||
grid: &Grid,
|
grid: &Grid,
|
||||||
walkable: Cell,
|
walkable: Cell,
|
||||||
initial_snake: &Snake,
|
initial_snake: &Snake,
|
||||||
cells_to_eat: HashSet<Point>,
|
cells_to_eat: HashSet<Point>,
|
||||||
) -> Vec<Snake> {
|
) -> Vec<Point> {
|
||||||
let mut targets = cells_to_eat.clone();
|
// let mut targets: Vec<Point> = cells_to_eat.iter().map(|p| p.clone()).collect();
|
||||||
|
|
||||||
while let Some(p) = targets.iter().next().cloned() {
|
let mut targets: Vec<&Point> = cells_to_eat.iter().collect();
|
||||||
targets.remove(&p);
|
|
||||||
|
|
||||||
let mut open_list: HashSet<Snake> = HashSet::new();
|
let mut path: Vec<Point> = Vec::new();
|
||||||
|
|
||||||
|
let mut initial_snake = initial_snake.clone();
|
||||||
|
|
||||||
|
while let Some(target) = targets.pop() {
|
||||||
|
// prepare
|
||||||
|
let mut open_list: HashSet<(Snake, Vec<Point>)> = HashSet::new();
|
||||||
|
open_list.insert((initial_snake.clone(), Vec::new()));
|
||||||
|
|
||||||
|
while let Some(x) = open_list.iter().next().cloned() {
|
||||||
|
open_list.remove(&x);
|
||||||
|
|
||||||
|
let snake = x.0;
|
||||||
|
let mut sub_path = x.1;
|
||||||
|
|
||||||
|
if get_snake_head(&snake) == *target {
|
||||||
|
path.append(&mut sub_path);
|
||||||
|
initial_snake = snake;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for dir in DIRECTIONS {
|
||||||
|
if {
|
||||||
|
let h = get_next_snake_head(&snake, &dir);
|
||||||
|
grid.get_cell(&h) <= walkable
|
||||||
|
} && !snake_will_self_collide(&snake, &dir)
|
||||||
|
{
|
||||||
|
let mut next_snake = snake.clone();
|
||||||
|
move_snake(&mut next_snake, &dir);
|
||||||
|
|
||||||
|
let mut next_sub_path = sub_path.clone();
|
||||||
|
next_sub_path.push(dir.clone());
|
||||||
|
|
||||||
|
open_list.insert((next_snake, next_sub_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for dir in DIRECTIONS {}
|
|
||||||
Vec::new()
|
path
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user