From d7ef7da9fbb0b6115fec6035c3e9598311350660 Mon Sep 17 00:00:00 2001 From: platane Date: Mon, 24 Mar 2025 22:01:03 +0100 Subject: [PATCH] . --- packages/solver-r/src/snake.rs | 37 ++++++++++++++++++-- packages/solver-r/src/snake_walk.rs | 53 ++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/packages/solver-r/src/snake.rs b/packages/solver-r/src/snake.rs index e9e2ea8..bf7244a 100644 --- a/packages/solver-r/src/snake.rs +++ b/packages/solver-r/src/snake.rs @@ -11,7 +11,7 @@ pub fn move_snake(s: &mut Snake, dir: &Point) -> () { e.y = s[0].y + dir.y; 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 { x: s[0].x + dir.x, 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) } +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] fn it_should_detect_self_collide() { 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_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); - 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] fn it_should_move_snake() { diff --git a/packages/solver-r/src/snake_walk.rs b/packages/solver-r/src/snake_walk.rs index 5239e24..2a5424e 100644 --- a/packages/solver-r/src/snake_walk.rs +++ b/packages/solver-r/src/snake_walk.rs @@ -1,21 +1,58 @@ use std::collections::HashSet; 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( grid: &Grid, walkable: Cell, initial_snake: &Snake, cells_to_eat: HashSet, -) -> Vec { - let mut targets = cells_to_eat.clone(); +) -> Vec { + // let mut targets: Vec = cells_to_eat.iter().map(|p| p.clone()).collect(); - while let Some(p) = targets.iter().next().cloned() { - targets.remove(&p); + let mut targets: Vec<&Point> = cells_to_eat.iter().collect(); - let mut open_list: HashSet = HashSet::new(); + let mut path: Vec = Vec::new(); + + let mut initial_snake = initial_snake.clone(); + + while let Some(target) = targets.pop() { + // prepare + let mut open_list: HashSet<(Snake, Vec)> = 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 }