I am a beginner to Rust and experimenting. I found out I need to change the way I think to solve problems in Rust. As I expected Rust compiler threw stack overflow error but I don't know how to change the algorithm. Anybody can point out, how to deal with such kind of algorithms.
I am building the algorithm presented in http://www.holdirdeinenvertrag.de/ with out modifications just to check how Rust works.
use std::collections::HashMap;
use std::collections::HashSet;
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
struct Position{
pub x : u32,
pub y : u32
}
impl Position {
fn new(x : u32, y : u32) -> Position {
Position {
x,
y
}
}
fn inc_x(&mut self) {
self.x += 1;
}
fn inc_y(&mut self) {
self.x += 1;
}
fn dec_x(&mut self) {
self.x -= 1;
}
fn dec_y(&mut self) {
self.x -= 1;
}
}
#[derive(Clone)]
struct Game {
position: Position,
letters: HashMap<Position, char>,
obstacles: HashSet<Position>,
}
impl Game {
fn is_invalid(player_position: &Position) -> bool {
let (x , y) = (player_position.x, player_position.y);
// Check whether player went out of boundary in 7x7 cell
if x > 0 && x < 7 && y > 0 && y < 7 {
return true;
}
false
}
}
#[derive(Clone)]
struct GameProgress {
visited: HashSet<Position>,
collect: Vec<char>,
game: Game
}
impl GameProgress {
fn new(visited : HashSet<Position>, collect : Vec<char>, game : Game) -> GameProgress {
GameProgress {
visited,
collect,
game
}
}
fn player_collected_all_letters(&self) -> bool {
if self.collect.len() == self.game.letters.len() {
return true;
}
false
}
fn mark_as_visited(&mut self, position : Position) {
self.visited.insert(position);
}
fn add_to_player_letter_collection(&mut self, letter : char) {
self.collect.push(letter);
}
fn move_player(&mut self, position : Position) {
self.game.position = position;
}
fn player_position(&mut self) -> &Position {
&self.game.position
}
fn get_all_letter_positions(&self) -> &HashMap<Position, char> {
&self.game.letters
}
fn get_all_obstacle_positions(&self) -> &HashSet<Position> {
&self.game.obstacles
}
fn has_visited(&self, position : &Position) -> bool {
if self.visited.contains(position) {
return true;
}
false
}
fn player_position_invalid(&self) -> bool {
let (x , y) = (self.game.position.x, self.game.position.x);
// Check whether player went out of boundary in 7x7 cell
if x > 0 && x < 7 && y > 0 && y < 7 {
return true;
}
false
}
fn is_obstacle(&self, player_position: &Position) -> bool {
if self.game.obstacles.contains(player_position) {
return true;
}
false
}
fn has_letter(&self, player_position: &Position) -> bool {
if self.game.letters.contains_key(player_position) {
return true
}
false
}
fn letter_at(&self, player_position: &Position) -> Option<&char> {
self.game.letters.get(player_position)
}
}
fn go_to(game_progress: &mut GameProgress) {
let player = game_progress.clone();
let player_position = player.game.position;
while !game_progress.player_collected_all_letters() {
// Check whether player goes out of boundary or visited the position
if game_progress.player_position_invalid() &&
game_progress.has_visited(&player_position) {
return;
}
// current position contain letter then keep in players wallet
if !game_progress.is_obstacle(&player_position) &&
game_progress.has_letter(&player_position) {
// let letter_at_position = game_progress.letter_at(&player_position);
match game_progress.letter_at(&player_position).cloned() {
Some(character) => {
game_progress.add_to_player_letter_collection(character)
},
None => println!("Empty character at the position"),
}
}
// Mark the position as visited
game_progress.mark_as_visited(Position::new(player_position.x, player_position.y));
{
game_progress.game.position.inc_x();
go_to(game_progress);
}
{
game_progress.game.position.inc_y();
go_to(game_progress);
}
{
game_progress.game.position.dec_x();
go_to(game_progress);
}
{
game_progress.game.position.dec_y();
go_to(game_progress);
}
}
}
fn initialize_search(game: Game) {
let mut game_progress = GameProgress {
visited: HashSet::new(),
collect: Vec::new(),
game
};
go_to(&mut game_progress);
print!("{:?}", game_progress.collect);
}
fn main() {
let start_position = Position::new(6, 4);
let mut letters: HashMap<Position, char> = HashMap::new();
let mut obstacles: HashSet<Position> = HashSet::new();
letters.insert(Position::new(2, 0), 'L');
letters.insert(Position::new(3, 1), 'A');
letters.insert(Position::new(4, 0), 'I');
letters.insert(Position::new(2, 1), 'O');
letters.insert(Position::new(5, 2), 'S');
obstacles.insert(Position::new(0, 1));
obstacles.insert(Position::new(0, 5));
obstacles.insert(Position::new(1, 4));
obstacles.insert(Position::new(2, 3));
obstacles.insert(Position::new(2, 5));
obstacles.insert(Position::new(6, 6));
let game: Game = Game {
position: start_position,
letters,
obstacles,
};
initialize_search(game);
}