rust implementation

This commit is contained in:
Uğur Küpeli
2022-07-03 14:50:32 +03:00
parent c10584f232
commit d1d0ef9e57
2 changed files with 78 additions and 42 deletions

View File

@@ -6,3 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"

View File

@@ -1,3 +1,9 @@
use std::{thread, time::Duration};
use rand::Rng;
// AI "learning" is not implemented. Don't have the time. - Ugur
fn main() {
loop {
let mut game = Game::default();
@@ -12,11 +18,13 @@ fn main() {
}
enum DistributeResult {
Normal, // Leftover beans
EndOnHomePit(bool), // "true" if ended on Player Home Pit
EndOnEmptyPit(usize), // "index" of the empty pit within the Row
Normal,
// Leftover beans
EndOnHomePit(bool),
// "true" if ended on Player Home Pit
EndOnEmptyPit(usize),
// "index" of the empty pit within the Row
ChosenEmpty,
GameOver,
}
struct Game {
@@ -26,7 +34,7 @@ struct Game {
impl Default for Game {
fn default() -> Self {
println!("\t\t\t AWARI");
println!("\n\n\t\t AWARI");
println!("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
Self {
@@ -39,35 +47,68 @@ impl Default for Game {
impl Game {
fn step_through(&mut self, mut index: usize) -> usize {
let mut bean_amount = self.pits[index];
self.pits[index] = 0;
loop {
index += 1;
if index > self.pits.len() - 1 {
index = 0;
}
self.pits[index] += 1;
bean_amount -= 1;
if bean_amount == 0 {
return index;
}
index += 1;
if index > self.pits.len() - 1 {
index = 0;
}
}
}
fn play_turn(&mut self, is_repeat: bool) -> bool {
use DistributeResult::*;
if self.is_game_over() {
println!("\nGame Over!");
let (player_beans, ai_beans) = (self.pits[6], self.pits[13]);
if player_beans == ai_beans {
println!("It's a draw")
} else if player_beans > ai_beans {
println!("You win by {}", player_beans - ai_beans);
} else {
println!("I win by {}", ai_beans - player_beans);
}
return true;
}
let chosen_index = if self.player_turn {
player_prompt(if is_repeat { "Again?" } else { "Your move?" })
player_prompt(if is_repeat { "Again?" } else { "Your move?" }) - 1
} else {
println!("My move is ");
0 // ai choice
println!("========================");
thread::sleep(Duration::from_secs(1));
let non_empty_pits: Vec<usize> = self
.pits
.iter()
.enumerate()
.filter(|&(i, p)| (7..13).contains(&i) && *p > 0)
.map(|(i, _)| i)
.collect();
let random_index = rand::thread_rng().gen_range(0..non_empty_pits.len());
let ai_move = non_empty_pits[random_index];
println!("My move is {}", ai_move - 6);
println!("========================");
ai_move
};
match self.process_choice(chosen_index) {
Normal => (),
EndOnHomePit(player) => {
self.draw();
if player == self.player_turn && !is_repeat {
self.play_turn(true);
}
@@ -85,34 +126,25 @@ impl Game {
println!("Chosen pit is empty");
return self.play_turn(is_repeat);
}
GameOver => {
let (player_beans, ai_beans) = (self.pits[6], self.pits[13]);
if player_beans == ai_beans {
println!("It's a draw")
} else if player_beans > ai_beans {
println!("You win by {}", player_beans - ai_beans);
} else {
println!("I win by {}", ai_beans - player_beans);
}
return true;
}
}
self.player_turn = !self.player_turn;
if !is_repeat {
self.player_turn = !self.player_turn;
}
false
}
pub fn process_choice(&mut self, index: usize) -> DistributeResult {
use DistributeResult::*;
if self.pits[index + 1] == 0 {
if self.pits[index] == 0 {
return ChosenEmpty;
}
let last_index = self.step_through(index + 1);
let last_index = self.step_through(index);
if self.is_gameover() {
return GameOver;
} else if last_index == 6 && self.player_turn {
if last_index == 6 && self.player_turn {
return EndOnHomePit(true);
} else if last_index == 13 && !self.player_turn {
return EndOnHomePit(false);
@@ -123,31 +155,34 @@ impl Game {
Normal
}
fn is_gameover(&self) -> bool {
for (i, p) in self.pits.iter().enumerate() {
if i != 6 || i != 13 {
if *p > 0 {
return false;
}
}
}
true
fn is_game_over(&self) -> bool {
let player_empty = !(0..6).any(|i| self.pits[i] > 0);
let ai_empty = !(7..13).any(|i| self.pits[i] > 0);
player_empty || ai_empty
}
fn draw(&self) {
let row_as_string = |player: bool| -> String {
let mut row_as_string = String::new();
let range = if player { 0..6 } else { 7..13 };
range.for_each(|i| {
let mut bean_amount_as_string = self.pits[i].to_string();
bean_amount_as_string.push_str(" ");
row_as_string.push_str(&bean_amount_as_string);
if player {
row_as_string.push_str(&bean_amount_as_string);
} else {
row_as_string.insert_str(0, &bean_amount_as_string);
}
});
return row_as_string;
row_as_string
};
println!(
" {}\n{}\t\t {}\n {}",
"\n {}\n{} {}\n {}\n",
row_as_string(false),
self.pits[13].to_string(),
self.pits[6].to_string(),