From b86c30e89ce42a1ec9d852be83edca0b5494dfb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=9Fur=20K=C3=BCpeli?= Date: Thu, 5 May 2022 02:00:33 +0300 Subject: [PATCH 1/3] init working on draw methods --- 90_Tower/rust/Cargo.toml | 8 ++++++++ 90_Tower/rust/src/disk.rs | 27 +++++++++++++++++++++++++++ 90_Tower/rust/src/game.rs | 34 ++++++++++++++++++++++++++++++++++ 90_Tower/rust/src/main.rs | 11 +++++++++++ 90_Tower/rust/src/needle.rs | 26 ++++++++++++++++++++++++++ 90_Tower/rust/src/util.rs | 15 +++++++++++++++ 6 files changed, 121 insertions(+) create mode 100644 90_Tower/rust/Cargo.toml create mode 100644 90_Tower/rust/src/disk.rs create mode 100644 90_Tower/rust/src/game.rs create mode 100644 90_Tower/rust/src/main.rs create mode 100644 90_Tower/rust/src/needle.rs create mode 100644 90_Tower/rust/src/util.rs diff --git a/90_Tower/rust/Cargo.toml b/90_Tower/rust/Cargo.toml new file mode 100644 index 00000000..1ec69633 --- /dev/null +++ b/90_Tower/rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/90_Tower/rust/src/disk.rs b/90_Tower/rust/src/disk.rs new file mode 100644 index 00000000..39326a4c --- /dev/null +++ b/90_Tower/rust/src/disk.rs @@ -0,0 +1,27 @@ +pub struct Disk { + size: u8, +} + +impl Disk { + pub fn new(size: u8) -> Self { + Disk { size } + } + + pub fn draw(&self) { + let space_amount = (15 - self.size) / 2; + + let draw_space = || { + if space_amount > 0 { + for _ in 0..space_amount { + print!(" "); + } + } + }; + + draw_space(); + for _ in 0..self.size { + print!("*"); + } + draw_space(); + } +} diff --git a/90_Tower/rust/src/game.rs b/90_Tower/rust/src/game.rs new file mode 100644 index 00000000..823903ac --- /dev/null +++ b/90_Tower/rust/src/game.rs @@ -0,0 +1,34 @@ +use crate::{needle::Needle, util}; + +pub struct Game { + pub needles: Vec, + _moves: usize, +} + +impl Game { + pub fn new() -> Self { + let mut needles = Vec::new(); + + for i in 0..3 { + let number = (i + 1) as u8; + let disks = match number { + 1 => util::generate_disks(4), + 2 => util::generate_disks(3), + _ => Vec::new(), + }; + + needles.push(Needle { disks, number }); + } + + Game { needles, _moves: 0 } + } + + pub fn draw(&self) { + for r in (1..=7).rev() { + for n in &self.needles { + n.draw(r) + } + println!(""); + } + } +} diff --git a/90_Tower/rust/src/main.rs b/90_Tower/rust/src/main.rs new file mode 100644 index 00000000..ae54ccb7 --- /dev/null +++ b/90_Tower/rust/src/main.rs @@ -0,0 +1,11 @@ +use game::Game; + +mod disk; +mod game; +mod needle; +mod util; + +fn main() { + let game = Game::new(); + game.draw(); +} diff --git a/90_Tower/rust/src/needle.rs b/90_Tower/rust/src/needle.rs new file mode 100644 index 00000000..0a23c732 --- /dev/null +++ b/90_Tower/rust/src/needle.rs @@ -0,0 +1,26 @@ +use crate::disk::Disk; + +pub struct Needle { + pub disks: Vec, + pub number: u8, +} + +impl Needle { + pub fn draw(&self, row: u8) { + //println!("printing row: {}", row); + + let offset = match self.number { + 1 => " ", + _ => "\t\t\t", + }; + + let row = row as usize; + + if self.disks.len() >= row { + self.disks[row - 1].draw(); + } else { + print!("{offset}"); + print!("*"); + } + } +} diff --git a/90_Tower/rust/src/util.rs b/90_Tower/rust/src/util.rs new file mode 100644 index 00000000..f047d38c --- /dev/null +++ b/90_Tower/rust/src/util.rs @@ -0,0 +1,15 @@ +use crate::disk::Disk; + +pub fn generate_disks(amount: u8) -> Vec { + if amount > 7 { + println!("CANNOT HAVE MORE THAN 7 DISKS!"); + } + + let mut disks = Vec::new(); + + for i in (1..=amount).rev() { + disks.push(Disk::new(i * 2 + 1)); + } + + disks +} From ece3fe0f5232bf7768cce9fb63a4de41cd18c4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=9Fur=20K=C3=BCpeli?= Date: Fri, 6 May 2022 13:22:57 +0300 Subject: [PATCH 2/3] fixed drawing --- 90_Tower/rust/src/disk.rs | 5 +++-- 90_Tower/rust/src/game.rs | 7 +++---- 90_Tower/rust/src/needle.rs | 8 +++----- 90_Tower/rust/src/util.rs | 8 ++++++-- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/90_Tower/rust/src/disk.rs b/90_Tower/rust/src/disk.rs index 39326a4c..c15399d9 100644 --- a/90_Tower/rust/src/disk.rs +++ b/90_Tower/rust/src/disk.rs @@ -8,9 +8,9 @@ impl Disk { } pub fn draw(&self) { - let space_amount = (15 - self.size) / 2; - let draw_space = || { + let space_amount = (15 - self.size) / 2; + if space_amount > 0 { for _ in 0..space_amount { print!(" "); @@ -23,5 +23,6 @@ impl Disk { print!("*"); } draw_space(); + print!(" "); } } diff --git a/90_Tower/rust/src/game.rs b/90_Tower/rust/src/game.rs index 823903ac..14f3cf8e 100644 --- a/90_Tower/rust/src/game.rs +++ b/90_Tower/rust/src/game.rs @@ -9,15 +9,14 @@ impl Game { pub fn new() -> Self { let mut needles = Vec::new(); - for i in 0..3 { - let number = (i + 1) as u8; - let disks = match number { + for i in 1..=3 { + let disks = match i { 1 => util::generate_disks(4), 2 => util::generate_disks(3), _ => Vec::new(), }; - needles.push(Needle { disks, number }); + needles.push(Needle { disks, number:i }); } Game { needles, _moves: 0 } diff --git a/90_Tower/rust/src/needle.rs b/90_Tower/rust/src/needle.rs index 0a23c732..b1e1d44c 100644 --- a/90_Tower/rust/src/needle.rs +++ b/90_Tower/rust/src/needle.rs @@ -9,18 +9,16 @@ impl Needle { pub fn draw(&self, row: u8) { //println!("printing row: {}", row); - let offset = match self.number { - 1 => " ", - _ => "\t\t\t", - }; - let row = row as usize; if self.disks.len() >= row { self.disks[row - 1].draw(); } else { + let offset = " "; + print!("{offset}"); print!("*"); + print!("{offset} "); } } } diff --git a/90_Tower/rust/src/util.rs b/90_Tower/rust/src/util.rs index f047d38c..76ff38b7 100644 --- a/90_Tower/rust/src/util.rs +++ b/90_Tower/rust/src/util.rs @@ -5,10 +5,14 @@ pub fn generate_disks(amount: u8) -> Vec { println!("CANNOT HAVE MORE THAN 7 DISKS!"); } + // check for if amount == 0 + let mut disks = Vec::new(); - for i in (1..=amount).rev() { - disks.push(Disk::new(i * 2 + 1)); + let mut half_size = 7; + for _ in (1..=amount).rev() { + disks.push(Disk::new(half_size * 2 + 1)); + half_size -= 1; } disks From 0f2360797b24cecf4afab126aad4eb4054c156c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=9Fur=20K=C3=BCpeli?= Date: Fri, 6 May 2022 16:04:34 +0300 Subject: [PATCH 3/3] rust: final --- 90_Tower/rust/src/disk.rs | 2 +- 90_Tower/rust/src/game.rs | 119 +++++++++++++++++++++++++++++++++--- 90_Tower/rust/src/main.rs | 43 ++++++++++++- 90_Tower/rust/src/needle.rs | 6 +- 90_Tower/rust/src/util.rs | 66 ++++++++++++++------ 5 files changed, 207 insertions(+), 29 deletions(-) diff --git a/90_Tower/rust/src/disk.rs b/90_Tower/rust/src/disk.rs index c15399d9..9d5b4b6d 100644 --- a/90_Tower/rust/src/disk.rs +++ b/90_Tower/rust/src/disk.rs @@ -1,5 +1,5 @@ pub struct Disk { - size: u8, + pub size: u8, } impl Disk { diff --git a/90_Tower/rust/src/game.rs b/90_Tower/rust/src/game.rs index 14f3cf8e..50ef0fe1 100644 --- a/90_Tower/rust/src/game.rs +++ b/90_Tower/rust/src/game.rs @@ -1,33 +1,138 @@ -use crate::{needle::Needle, util}; +use crate::{ + disk::Disk, + needle::Needle, + util::{self, prompt, PromptResult}, +}; pub struct Game { pub needles: Vec, - _moves: usize, + disk_count: u8, + moves: usize, } impl Game { pub fn new() -> Self { let mut needles = Vec::new(); + let disk_count = util::get_disk_count(); for i in 1..=3 { let disks = match i { - 1 => util::generate_disks(4), - 2 => util::generate_disks(3), - _ => Vec::new(), + 1 => { + let mut disks = Vec::new(); + + let mut half_size = 7; + for _ in (1..=disk_count).rev() { + disks.push(Disk::new(half_size * 2 + 1)); + half_size -= 1; + } + + disks + } + 2 | 3 => Vec::new(), + _ => panic!("THERE MUST BE EXACTLY THREE NEEDLES!"), }; - needles.push(Needle { disks, number:i }); + needles.push(Needle { disks, number: i }); } - Game { needles, _moves: 0 } + Game { + needles, + disk_count, + moves: 0, + } + } + + pub fn update(&mut self) -> bool { + self.draw(); + + loop { + let (disk_index, from_needle_index) = self.get_disk_to_move(); + let to_needle_index = self.ask_which_needle(); + + if from_needle_index == to_needle_index { + println!("DISK IS ALREADY AT THAT NEEDLE!"); + break; + } + + let to_needle = &self.needles[to_needle_index]; + + if to_needle.disks.len() == 0 + || to_needle.disks[0].size > self.needles[from_needle_index].disks[disk_index].size + { + self.move_disk(disk_index, from_needle_index, to_needle_index); + break; + } else { + println!("CAN'T PLACE ON A SMALLER DISK!"); + } + } + + if self.needles[2].disks.len() == self.disk_count as usize { + self.draw(); + println!("CONGRATULATIONS!!"); + println!("YOU HAVE PERFORMED THE TASK IN {} MOVES.", self.moves); + return true; + } + + false } pub fn draw(&self) { + println!(""); for r in (1..=7).rev() { for n in &self.needles { n.draw(r) } println!(""); } + println!(""); + } + + fn get_disk_to_move(&self) -> (usize, usize) { + loop { + if let PromptResult::Number(n) = prompt(true, "WHICH DISK WOULD YOU LIKE TO MOVE?") { + let smallest_disk = 15 - ((self.disk_count - 1) * 2); + + if n < smallest_disk as i32 || n > 15 || (n % 2) == 0 { + println!("PLEASE ENTER A VALID DISK!") + } else { + for (n_i, needle) in self.needles.iter().enumerate() { + if let Some((i, _)) = needle + .disks + .iter() + .enumerate() + .find(|(_, disk)| disk.size == n as u8) + { + if i == (needle.disks.len() - 1) { + return (i, n_i); + } + + println!("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE."); + } + } + } + } + } + } + + fn ask_which_needle(&self) -> usize { + loop { + if let PromptResult::Number(n) = prompt(true, "PLACE DISK ON WHICH NEEDLE?") { + if n <= 0 || n > 3 { + println!("PLEASE ENTER A VALID NEEDLE."); + } else { + return (n - 1) as usize; + } + } + } + } + + fn move_disk(&mut self, disk: usize, from: usize, to: usize) { + let from = &mut self.needles[from]; + let size = from.disks[disk].size; + + from.disks.remove(disk); + self.needles[to].add(size); + + self.moves += 1; } } diff --git a/90_Tower/rust/src/main.rs b/90_Tower/rust/src/main.rs index ae54ccb7..5ec26079 100644 --- a/90_Tower/rust/src/main.rs +++ b/90_Tower/rust/src/main.rs @@ -1,4 +1,5 @@ use game::Game; +use util::PromptResult; mod disk; mod game; @@ -6,6 +7,44 @@ mod needle; mod util; fn main() { - let game = Game::new(); - game.draw(); + println!("\n\n\t\tTOWERS"); + println!("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"); + + println!("TOWERS OF HANOI PUZZLE\n"); + + println!("YOU MUST TRANSFER THE DISKS FROM THE LEFT TO THE RIGHT"); + println!("TOWER, ON AT A TIME, NEVER PUTTING A LARGER DISK ON A"); + println!("SMALLER DISK.\n"); + + let mut quit = false; + + while !quit { + let mut game = Game::new(); + + println!(""); + println!( + r#"IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE. +3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE, +7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH +2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS +THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES +ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL +START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM +TO NEEDLE 3. + +GOOD LUCK!"# + ); + + loop { + if game.update() { + break; + } + } + + if let PromptResult::YesNo(r) = util::prompt(false, "TRY AGAIN (YES OR NO)?") { + quit = !r; + } + } + + println!("THANKS FOR THE GAME!"); } diff --git a/90_Tower/rust/src/needle.rs b/90_Tower/rust/src/needle.rs index b1e1d44c..b2286eaf 100644 --- a/90_Tower/rust/src/needle.rs +++ b/90_Tower/rust/src/needle.rs @@ -7,8 +7,6 @@ pub struct Needle { impl Needle { pub fn draw(&self, row: u8) { - //println!("printing row: {}", row); - let row = row as usize; if self.disks.len() >= row { @@ -21,4 +19,8 @@ impl Needle { print!("{offset} "); } } + + pub fn add(&mut self, size: u8) { + self.disks.push(Disk { size }); + } } diff --git a/90_Tower/rust/src/util.rs b/90_Tower/rust/src/util.rs index 76ff38b7..9feacf94 100644 --- a/90_Tower/rust/src/util.rs +++ b/90_Tower/rust/src/util.rs @@ -1,19 +1,51 @@ -use crate::disk::Disk; +use std::io; -pub fn generate_disks(amount: u8) -> Vec { - if amount > 7 { - println!("CANNOT HAVE MORE THAN 7 DISKS!"); - } - - // check for if amount == 0 - - let mut disks = Vec::new(); - - let mut half_size = 7; - for _ in (1..=amount).rev() { - disks.push(Disk::new(half_size * 2 + 1)); - half_size -= 1; - } - - disks +pub enum PromptResult { + Number(i32), + YesNo(bool), +} + +pub fn prompt(numeric: bool, msg: &str) -> PromptResult { + use PromptResult::*; + loop { + println!("{}", msg); + + let mut input = String::new(); + + io::stdin() + .read_line(&mut input) + .expect("Failed to read line."); + + let input = input.trim().to_string(); + + if numeric { + if let Ok(n) = input.parse::() { + return Number(n); + } + + println!("PLEASE ENTER A NUMBER.") + } else { + match input.to_uppercase().as_str() { + "YES" | "Y" => return YesNo(true), + "NO" | "N" => return YesNo(false), + _ => println!("PLEASE ENTER (Y)ES OR (N)O."), + } + } + } +} + +pub fn get_disk_count() -> u8 { + loop { + if let PromptResult::Number(n) = + prompt(true, "HOW MANY DISKS DO YOU WANT TO MOVE (7 IS MAX)?") + { + if n <= 2 { + println!("THERE MUST BE AT LEAST 3 DISKS!") + } else if n > 7 { + println!("THERE CAN'T BE MORE THAN 7 DISKS!") + } else { + return n as u8; + } + } + } }