rust port

This commit is contained in:
Uğur Küpeli
2022-05-06 20:15:45 +03:00
parent 3e8b3901d7
commit b055cba4cb
6 changed files with 389 additions and 0 deletions

View File

@@ -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"

View File

@@ -0,0 +1,57 @@
use std::{thread, time::Duration};
use crate::{horses::Horses, players::Players};
pub struct Game {
horses: Horses,
players: Players,
}
impl Game {
pub fn new() -> Self {
Game {
horses: Horses::new(),
players: Players::new(),
}
}
pub fn play(&mut self) -> bool {
self.horses.randomize_odds();
self.horses.print_table();
self.players.make_bets();
println!("\n1 2 3 4 5 6 7 8");
for _ in 1..=7 {
self.horses.advance();
self.draw();
thread::sleep(Duration::from_secs(1));
}
let winner = self.horses.print_placements();
self.players.process_winner(winner);
return self.players.prompt_next_round();
}
pub fn draw(&self) {
println!("=============");
println!("XXXXSTARTXXXX");
for row in 1..=28 {
let neighbors = self.horses.get_at(row);
match neighbors.len() {
0 => println!(),
1 => println!("{}", neighbors[0].no),
_ => {
for h in neighbors {
print!("{} ", h.no);
}
println!();
}
}
}
println!("XXXXFINISHXXXX");
}
}

View File

@@ -0,0 +1,114 @@
use rand::Rng;
pub struct Horse {
pub name: String,
pub no: u8,
pub odd: f32,
pub position: u8,
}
impl Horse {
fn new(name: &str, no: u8) -> Self {
Horse {
name: name.to_string(),
no,
odd: 0.,
position: 0,
}
}
}
pub struct Horses {
horses: [Horse; 8],
}
impl Horses {
pub fn new() -> Self {
Horses {
horses: [
Horse::new("JOE MAW", 1),
Horse::new("L.B.J.", 2),
Horse::new("MR.WASHBURN", 3),
Horse::new("MISS KAREN", 4),
Horse::new("JOLLY", 5),
Horse::new("HORSE", 6),
Horse::new("JELLY DO NOT", 7),
Horse::new("MIDNIGHT", 8),
],
}
}
pub fn randomize_odds(&mut self) {
let mut odds = Vec::new();
for _ in 1..=8 {
odds.push(rand::thread_rng().gen_range(1.0..=10.));
}
let total: f32 = odds.iter().sum();
for (i, o) in odds.iter().enumerate() {
let o = total / o;
self.horses[i].odd = o;
}
}
pub fn advance(&mut self) {
for h in self.horses.iter_mut() {
let distance = rand::thread_rng().gen_range(1..=100);
let scale = h.odd.ceil() as i32;
let dt = if distance < 10 {
1
} else if distance < scale + 17 {
2
} else if distance < scale + 37 {
3
} else if distance < scale + 57 {
4
} else if distance < scale + 77 {
5
} else if distance < scale + 92 {
6
} else {
7
};
h.position += dt as u8;
}
}
pub fn get_at(&self, row: usize) -> Vec<&Horse> {
self.horses
.iter()
.filter(|h| h.position == row as u8)
.collect()
}
pub fn print_table(&self) {
println!("HORSE\t\tNUMBER\t\tODDS\t\t\n");
for horse in self.horses.iter() {
let (h, n, o) = (horse.name.clone(), horse.no, horse.odd);
if h.len() > 7 {
println!("{}\t{}\t\t{:.2} :1", h, n, o);
} else {
println!("{}\t\t{}\t\t{:.2} :1", h, n, o);
}
}
println!("-----------------------------------------\n")
}
pub fn print_placements(&mut self) -> u8 {
self.horses.sort_by(|a, b| b.position.cmp(&a.position));
println!("\nTHE RACE RESULTS ARE:\n");
for (i, h) in self.horses.iter_mut().enumerate() {
println!("{} PLACE HORSE NO. {}\t\tAT {:.2} :1", i + 1, h.no, h.odd);
h.position = 0;
}
self.horses[0].no
}
}

View File

@@ -0,0 +1,15 @@
use crate::game::Game;
mod game;
mod horses;
mod players;
mod util;
fn main() {
let mut game = Game::new();
let mut again = true;
while again {
again = game.play();
}
}

View File

@@ -0,0 +1,154 @@
use crate::util::{self, PromptResult};
#[derive(Debug)]
pub struct Player {
pub name: String,
pub money: u32,
pub playing: bool,
pub horse_no: u8,
pub bet: u32,
}
impl Player {
fn new(name: String) -> Self {
Player {
name,
money: 100000,
playing: true,
horse_no: 0,
bet: 0,
}
}
}
#[derive(Debug)]
pub struct Players {
players: Vec<Player>,
}
impl Players {
pub fn new() -> Self {
let players;
loop {
if let PromptResult::Numeric(n) = util::prompt(Some(true), "HOW MANY WANT TO BET?") {
if n <= 0 {
println!("THERE CAN'T BE (LESS THAN) ZERO PLAYERS!");
} else {
println!("WHEN ? APPEARS, TYPE NAME");
players = Players::generate_players(n);
break;
}
}
}
Players { players }
}
pub fn make_bets(&mut self) {
println!("PLACE YOUR BETS...HORSE # THEN AMOUNT");
for p in self.players.iter_mut() {
if !p.playing {
continue;
}
let name = format!("{}?", p.name);
'prompt: loop {
if let PromptResult::Normal(response) = util::prompt(None, name.as_str()) {
let response: Vec<&str> = response.trim().split(",").collect();
for (i, n) in response.iter().enumerate() {
if let Ok(n) = n.parse::<i32>() {
if n.is_negative() {
println!("YOU CAN'T ENTER A NEGATIVE NUMBER!")
} else {
match i {
0 => {
if n > 8 {
println!("INVALID HORSE #")
} else {
p.horse_no = n as u8;
}
}
1 => {
if n == 0 {
println!("YOU CAN'T BET NOTHING!");
} else if n > p.money as i32 {
println!("YOU DON'T HAVE ENOUGH MONEY!")
} else {
p.bet = n as u32;
break 'prompt;
}
}
_ => println!("YOU CAN'T ENTER MORE THAN 2 NUMBERS!"),
}
}
} else {
println!("ONLY ENTER NUMBERS PLEASE!");
}
}
}
}
}
}
fn generate_players(n: i32) -> Vec<Player> {
let mut players: Vec<Player> = Vec::new();
for _ in 0..n {
loop {
if let PromptResult::Normal(name) = util::prompt(None, "?") {
let name = name.trim().to_uppercase();
if name.is_empty() {
println!("NAME CAN'T BE EMPTY!");
} else if let Some(_) = players.iter().find(|p| p.name == name) {
println!("THERE IS ALREADY A PLAYER WITH THAT NAME!");
} else {
players.push(Player::new(name));
break;
}
}
}
}
players
}
pub fn process_winner(&mut self, no: u8) {
println!();
for p in self.players.iter_mut() {
if !p.playing {
continue;
}
if p.horse_no == no {
p.money += p.bet;
println!("{} WON ${}! THEY HAVE ${}.", p.name, p.bet, p.money);
} else {
p.money -= p.bet;
println!("{} LOST ${}. THEY HAVE ${} LEFT.", p.name, p.bet, p.money);
}
p.bet = 0;
p.horse_no = 0;
}
println!();
}
pub fn prompt_next_round(&mut self) -> bool {
for p in self.players.iter_mut() {
let msg = format!("{}, DO YOU WANT TO BET ON THE NEXT RACE?", p.name);
if let PromptResult::YesNo(yes) = util::prompt(Some(false), msg.as_str()) {
p.playing = yes;
}
}
if let None = self.players.iter().find(|p| p.playing) {
return false;
}
true
}
}

View File

@@ -0,0 +1,40 @@
use std::io;
pub enum PromptResult {
Normal(String),
YesNo(bool),
Numeric(i32),
}
pub fn prompt(is_numeric: Option<bool>, msg: &str) -> PromptResult {
use PromptResult::*;
println!("{msg}");
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read input.");
if let Some(is_numeric) = is_numeric {
let input = input.trim();
if is_numeric {
if let Ok(n) = input.parse::<i32>() {
return Numeric(n);
}
println!("PLEASE ENTER A VALID 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."),
}
}
} else {
return Normal(input);
}
}
}