forked from coding-horror/basic-computer-games
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request coding-horror#744 from ugurkupeli/30_Cube/rust
30 cube/rust
- Loading branch information
Showing
4 changed files
with
271 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[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] | ||
rand = "0.8.5" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
use crate::util; | ||
|
||
pub type Position = (u8, u8, u8); | ||
|
||
pub struct Game { | ||
wallet: usize, | ||
bet: Option<usize>, | ||
landmines: Vec<Position>, | ||
player: Position, | ||
} | ||
|
||
impl Game { | ||
pub fn new() -> Self { | ||
Game { | ||
wallet: 500, | ||
bet: None, | ||
landmines: util::get_landmines(), | ||
player: (1, 1, 1), | ||
} | ||
} | ||
|
||
pub fn play(&mut self) -> bool { | ||
self.bet = self.get_bet(); | ||
|
||
let mut first_move = true; | ||
let mut result = (false, "******BANG!******\nYOU LOSE"); | ||
|
||
loop { | ||
let msg = if first_move { | ||
first_move = false; | ||
"ITS YOUR MOVE" | ||
} else { | ||
"NEXT MOVE" | ||
}; | ||
|
||
let (ok, p) = self.ask_position(msg); | ||
|
||
if ok { | ||
if p == (3, 3, 3) { | ||
result.0 = true; | ||
result.1 = "CONGRATULATIONS!"; | ||
break; | ||
} else if self.landmines.contains(&p) { | ||
break; | ||
} else { | ||
self.player = p; | ||
} | ||
} else { | ||
result.1 = "ILLEGAL MOVE\nYOU LOSE."; | ||
break; | ||
} | ||
} | ||
|
||
println!("{}", result.1); | ||
self.calculate_wallet(result.0); | ||
self.reset_game(); | ||
|
||
if self.wallet <= 0 { | ||
println!("YOU ARE BROKE!"); | ||
return false; | ||
} | ||
|
||
return util::prompt_bool("DO YOU WANT TO TRY AGAIN?"); | ||
} | ||
|
||
fn get_bet(&self) -> Option<usize> { | ||
loop { | ||
if util::prompt_bool("WANT TO MAKE A WAGER?") { | ||
let b = util::prompt_number("HOW MUCH?"); | ||
|
||
if b != 0 && b <= self.wallet { | ||
return Some(b); | ||
} else { | ||
println!("YOU CAN'T BET THAT!"); | ||
} | ||
} else { | ||
return None; | ||
}; | ||
} | ||
} | ||
|
||
fn ask_position(&self, msg: &str) -> (bool, Position) { | ||
if let Some(p) = util::prompt_position(msg, self.player) { | ||
return (true, p); | ||
} | ||
return (false, (0, 0, 0)); | ||
} | ||
|
||
fn calculate_wallet(&mut self, win: bool) { | ||
if let Some(b) = self.bet { | ||
if win { | ||
self.wallet += b; | ||
} else { | ||
self.wallet -= b; | ||
} | ||
self.bet = None; | ||
println!("YOU NOW HAVE {} DOLLARS", self.wallet); | ||
} | ||
} | ||
|
||
fn reset_game(&mut self) { | ||
self.player = (1, 1, 1); | ||
self.landmines.clear(); | ||
self.landmines = util::get_landmines(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
use crate::game::Game; | ||
|
||
mod game; | ||
mod util; | ||
|
||
fn main() { | ||
println!("\n\n\t\tCUBE"); | ||
println!("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"); | ||
|
||
if util::prompt_bool("DO YOU WANT TO SEE THE INSTRUCTIONS? (YES--1,NO--0)") { | ||
println!("\nThis is a game in which you will be playing against the"); | ||
println!("random decisions of the computer. The field of play is a"); | ||
println!("cube of side 3. Any of the 27 locations can be designated"); | ||
println!("by inputing three numbers such as 2,3,1. At the start,"); | ||
println!("you are automatically at location 1,1,1. The object of"); | ||
println!("the game is to get to location 3,3,3. One minor detail:"); | ||
println!("the computer will pick, at random, 5 locations at which"); | ||
println!("it will plant land mines. If you hit one of these locations"); | ||
println!("you lose. One other detail: You may move only one space"); | ||
println!("in one direction each move. For example: From 1,1,2 you"); | ||
println!("may move to 2,1,2 or 1,1,3. You may not change"); | ||
println!("two of the numbers on the same move. If you make an illegal"); | ||
println!("move, you lose and the computer takes the money you may"); | ||
println!("have bet on that round.\n"); | ||
println!("When stating the amount of a wager, print only the number"); | ||
println!("of dollars (example: 250) you are automatically started with"); | ||
println!("500 dollars in your account.\n"); | ||
println!("Good luck!\n"); | ||
} | ||
|
||
let mut game = Game::new(); | ||
|
||
loop { | ||
if !game.play() { | ||
println!("\nTOUGH LUCK\n\nGOODBYE!\n"); | ||
break; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
use std::num::ParseIntError; | ||
|
||
use crate::game::Position; | ||
|
||
pub fn get_random_position() -> Position { | ||
(get_random_axis(), get_random_axis(), get_random_axis()) | ||
} | ||
|
||
fn get_random_axis() -> u8 { | ||
rand::Rng::gen_range(&mut rand::thread_rng(), 1..=3) | ||
} | ||
|
||
pub fn get_landmines() -> Vec<Position> { | ||
let mut landmines = Vec::new(); | ||
|
||
for _ in 0..5 { | ||
let mut m = get_random_position(); | ||
while landmines.contains(&m) { | ||
m = get_random_position(); | ||
} | ||
landmines.push(m); | ||
} | ||
|
||
landmines | ||
} | ||
|
||
fn read_line() -> Result<usize, ParseIntError> { | ||
let mut input = String::new(); | ||
std::io::stdin() | ||
.read_line(&mut input) | ||
.expect("~~Failed reading line!~~"); | ||
input.trim().parse::<usize>() | ||
} | ||
|
||
pub fn prompt_bool(msg: &str) -> bool { | ||
loop { | ||
println!("{}", msg); | ||
|
||
if let Ok(n) = read_line() { | ||
if n == 1 { | ||
return true; | ||
} else if n == 0 { | ||
return false; | ||
} | ||
} | ||
println!("ENTER YES--1 OR NO--0\n"); | ||
} | ||
} | ||
|
||
pub fn prompt_number(msg: &str) -> usize { | ||
loop { | ||
println!("{}", msg); | ||
|
||
if let Ok(n) = read_line() { | ||
return n; | ||
} | ||
println!("ENTER A NUMBER\n"); | ||
} | ||
} | ||
|
||
pub fn prompt_position(msg: &str, prev_pos: Position) -> Option<Position> { | ||
loop { | ||
println!("{}", msg); | ||
|
||
let mut input = String::new(); | ||
std::io::stdin() | ||
.read_line(&mut input) | ||
.expect("~~Failed reading line!~~"); | ||
|
||
let input: Vec<&str> = input.trim().split(",").collect(); | ||
|
||
let pp = [prev_pos.0, prev_pos.1, prev_pos.2]; | ||
let mut pos = Vec::new(); | ||
|
||
if input.len() != 3 { | ||
println!("YOU MUST ENTER 3 AXES!"); | ||
} else { | ||
for a in input { | ||
if let Ok(n) = a.parse::<u8>() { | ||
if n == 0 || n > 3 { | ||
println!("YOU MUST ENTER AN AXIS BETWEEN 1 AND 3!"); | ||
} else { | ||
pos.push(n); | ||
} | ||
} else { | ||
println!("INVALID LOCATION."); | ||
} | ||
} | ||
|
||
let mut moved = false; | ||
for (i, p) in pos.iter().enumerate() { | ||
let dt = ((*p as isize) - (pp[i] as isize)).abs(); | ||
|
||
if dt > 1 { | ||
return None; | ||
} | ||
|
||
if dt == 1 { | ||
if moved { | ||
return None; | ||
} else { | ||
moved = true; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if pos.len() == 3 { | ||
let pos = (pos[0], pos[1], pos[2]); | ||
if pos == prev_pos { | ||
println!("YOU ARE ALREADY THERE!"); | ||
} else { | ||
return Some(pos); | ||
} | ||
} | ||
} | ||
} |