CS396-Projects/assignmentSix/src/main.rs

480 lines
13 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// import libraries, namespaces
use std::io;
use std::io::Write;
use std::fmt;
use rand::Rng;
use rand::thread_rng;
use rand::seq::SliceRandom;
// enum for Rank
// TWO = 2, ... ACE
// implement fmt::Display
#[derive(PartialEq, Eq, Clone)]
enum Rank
{
None,
TWO = 2,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING,
ACE
}
impl fmt::Display for Rank {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self
{
Rank::None => write!(f, "{}", 'X'),
Rank::TWO => write!(f, "{}", 2),
Rank::THREE => write!(f, "{}", 3),
Rank::FOUR => write!(f, "{}", 4),
Rank::FIVE => write!(f, "{}", 5),
Rank::SIX => write!(f, "{}", 6),
Rank::SEVEN => write!(f, "{}", 7),
Rank::EIGHT => write!(f, "{}", 8),
Rank::NINE => write!(f, "{}", 9),
Rank::TEN => write!(f, "{}", 10),
Rank::JACK => write!(f, "{}", 'J'),
Rank::QUEEN => write!(f, "{}", 'Q'),
Rank::KING => write!(f, "{}", 'K'),
Rank::ACE => write!(f, "{}", 'A')
}
}
}
fn number_to_rank(num_rank: i32) -> Rank
{
match num_rank
{
1 => Rank::ACE,
2 => Rank::TWO,
3 => Rank::THREE,
4 => Rank::FOUR,
5 => Rank::FIVE,
6 => Rank::SIX,
7 => Rank::SEVEN,
8 => Rank::EIGHT,
9 => Rank::NINE,
10 => Rank::TEN,
11 => Rank::JACK,
12 => Rank::QUEEN,
13 => Rank::KING,
_ => Rank::None
}
}
fn rank_to_number(in_rank: Rank) -> i32
{
match in_rank
{
Rank::ACE => 1,
Rank::TWO => 2,
Rank::THREE => 3,
Rank::FOUR => 4,
Rank::FIVE => 5,
Rank::SIX => 6,
Rank::SEVEN => 7,
Rank::EIGHT => 8,
Rank::NINE => 9,
Rank::TEN => 10,
Rank::JACK => 11,
Rank::QUEEN => 12,
Rank::KING => 13,
Rank::None => -1
}
}
// enum for Suit
// HEARTS, DIAMONDS, SPADES, CLUBS
// implement fmt::Display
#[derive(PartialEq, Eq, Clone)]
enum Suit
{
None,
HEARTS,
DIAMONDS,
SPADES,
CLUBS
}
impl fmt::Display for Suit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self
{
Suit::None => write!(f, "{}", 'X'),
Suit::HEARTS => write!(f, "{}", 'H'),
Suit::DIAMONDS => write!(f, "{}", 'D'),
Suit::SPADES => write!(f, "{}", 'S'),
Suit::CLUBS => write!(f, "{}", 'C')
}
}
}
fn number_to_suit(num_suit: i32) -> Suit
{
match num_suit
{
1 => Suit::HEARTS,
2 => Suit::DIAMONDS,
3 => Suit::SPADES,
4 => Suit::CLUBS,
_ => Suit::None
}
}
// Card struct
// rank and suit variable
// implement fmt::Display
#[derive(Clone)]
struct Card
{
card_rank: Rank,
card_suit: Suit
}
impl fmt::Display for Card {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.card_rank, self.card_suit)
}
}
// Deck struct
// vector of Cards
// new() method, [creates deck of cards, shuffles, return a deck object]
// shuffle() method [shuffles a deck object]
// draw() method ['draws' an card from the top (last) of the deck, return card]
// is_empty() method [returns t/f if the deck (reference) is empty]
struct Deck
{
card_deck: Vec<Card>
}
impl Deck
{
fn new() -> Deck
{
// create deck of cards
let mut full_deck = Deck
{
card_deck: vec![]
};
// to create deck,
// need a double for loop (or just loop with counter) to
// iterate through 2-A (or 0 to 12 / 1-13) for each suit (diamonds, etc.)
// add the card via index.
let mut suit_counter = 0;
let mut card_counter = 0;
loop
{
if suit_counter == 4
{
break;
}
else
{
loop
{
if card_counter == 13
{
break;
}
else
{
// create card here.
let temp_card = Card
{
card_rank: number_to_rank(card_counter + 1),
card_suit: number_to_suit(suit_counter + 1)
};
full_deck.card_deck.push(temp_card);
card_counter = card_counter + 1;
}
}
card_counter = 0;
suit_counter = suit_counter + 1;
}
}
// shuffle deck of cards
full_deck.card_deck.shuffle(&mut thread_rng());
// return deck struct
return full_deck;
}
fn shuffle(mut self) -> Deck
{
self.card_deck.shuffle(&mut thread_rng());
return self;
}
fn draw(&mut self) -> Card
{
if !self.card_deck.is_empty()
{
return self.card_deck.pop().unwrap();
}
else
{
panic!("Card ran out somehow");
}
}
fn is_empty(&self) -> bool
{
return self.card_deck.is_empty();
}
}
// Player struct
// vector of cards [referred to as hand]
// new() method, [creates a new player object]
// add_cards() method [takes vector of cards, adds to player hand.]
// has_rank() method [accepts a Rank, returns vector of cards belonging to that
// rank, removes the cards from player hand]
// check_set() method [returns true if player has a set and removes the cards
// belonging to that set]
#[derive(Clone)]
struct Player
{
player_hand: Vec<Card>
}
impl Player
{
fn new() -> Player
{
let mut hand = Player
{
player_hand: vec![]
};
return hand;
}
fn add_cards(&mut self, mut card_vec: Vec<Card>)
{
// append the card vector to the player's hand.
self.player_hand.append(&mut card_vec);
}
fn has_rank(&mut self, in_card_rank: &Rank) -> Vec<Card>
{
// check to see if the rank matches any of the items in vector
// if they do match, remove from hand, place into temp vector,
// return temp vector.
let mut card_counter = 0;
let mut card_out = vec![];
loop
{
if self.player_hand.is_empty() || self.player_hand.len() - 1 < card_counter
{
break;
}
if self.player_hand.get(card_counter).unwrap().card_rank == *in_card_rank
{
let current_card = Card
{
card_rank: self.player_hand.get(card_counter).unwrap().card_rank.clone(),
card_suit: self.player_hand.get(card_counter).unwrap().card_suit.clone(),
};
card_out.push(current_card);
self.player_hand.remove(card_counter);
}
card_counter = card_counter + 1;
}
return card_out;
}
fn check_set(&mut self) -> bool
{
// check to see if the vector (self.player_hand) has four of the same rank.
// if the player does, remove the cards, and return true,
// otherwise, return false.
let mut count = 0;
let mut rank_check = 0;
loop
{
if rank_check > 13
{
break;
}
for card in &self.player_hand
{
if card.card_rank == number_to_rank(rank_check)
{
count += 1;
}
}
if count >= 4
{
self.player_hand.retain(|card| card.card_rank != number_to_rank(rank_check));
return true;
}
rank_check = rank_check + 1;
count = 0;
}
return false;
}
}
// Game struct
// deck [main instance of deck]
// human player [instance of Player]
// computer player [instance of Player]
// new() method [returns new Game object]
// human_turn() [prompts the user to ask for a rank and check if the computer
// has the requested rank. If the card is available, it will transfer the cards
// to the human’s hand, otherwise, it will draw a card]
// computer_turn() [that generates a random rank and checks if the human has the
// requested rank. If the card is available, it will transfer the cards to the
// computer’s hand, otherwise, it will draw a card]
// play() [handles the gameplay by switching between the player’s turn and the
// computer’s turn and checks for the game to be completed]
// print_scores() [prints the final score of the players]
// winner() [returns name of the winner (player or computer)]
struct Game
{
// data
full_card_deck: Deck,
human_player: Player,
computer_player: Player,
human_score: u32,
computer_score: u32
}
impl Game
{
// methods
fn new() -> Game
{
let mut full_game = Game
{
full_card_deck: Deck::new(),
human_player: Player::new(),
computer_player: Player::new(),
human_score: 0,
computer_score: 0
};
// deal seven cards to each player.
let mut card_count = 0;
let mut human_cards_vec = vec![];
let mut computer_cards_vec = vec![];
loop
{
if card_count > 6
{
break;
}
human_cards_vec.push(full_game.full_card_deck.draw());
computer_cards_vec.push(full_game.full_card_deck.draw());
card_count = card_count + 1;
}
full_game.human_player.add_cards(human_cards_vec);
full_game.computer_player.add_cards(computer_cards_vec);
return full_game;
}
fn human_turn(&mut self)
{
print!("Human's Turn: ");
for card in &*self.human_player.player_hand
{
print!("{} ", card);
}
println!("");
print!("Your turn. Enter a rank (2-10, A/1, J/11, Q/12, K/13): ");
let _=io::stdout().flush();
let mut rank_enter = String::new();
let mut rank_num: i32 = 0;
let mut rank_exit: Rank;
io::stdin().read_line(&mut rank_enter).expect("String wrong");
rank_num = rank_enter.trim().parse().unwrap();
rank_exit = number_to_rank(rank_num);
// check if the computer has the rank requested.
let mut temp_vec = self.computer_player.has_rank(&rank_exit);
if !temp_vec.is_empty()
{
println!("Computer has {}s.", rank_exit);
// add the cards from the temp_vec.
self.human_player.add_cards(temp_vec);
}
else
{
println!("Computer does not have {}s. Go fish.", rank_exit);
// draw a card.
let mut new_card_vec = vec![];
new_card_vec.push(self.full_card_deck.draw());
self.human_player.add_cards(new_card_vec)
}
if self.human_player.check_set()
{
self.human_score = self.human_score + 1;
}
}
fn computer_turn(&mut self)
{
print!("Computer's Turn... ");
println!("");
let rank_pick = rand::thread_rng().gen_range(1..=13);
// check if the computer has the rank requested.
let mut temp_vec = self.human_player.has_rank(&number_to_rank(rank_pick));
if !temp_vec.is_empty()
{
println!("Human has {}s.", number_to_rank(rank_pick));
// add the cards from the temp_vec.
self.computer_player.add_cards(temp_vec);
}
else
{
println!("Human does not have {}s. Computer goes fish.", number_to_rank(rank_pick));
// draw a card.
let mut new_card_vec = vec![];
new_card_vec.push(self.full_card_deck.draw());
self.computer_player.add_cards(new_card_vec)
}
if self.computer_player.check_set()
{
self.computer_score = self.computer_score + 1;
}
}
fn play(&mut self)
{
loop
{
if self.full_card_deck.card_deck.len() == 0
{
println!("Game Over.");
self.print_scores();
self.winner();
break;
}
self.human_turn();
self.computer_turn();
}
}
fn print_scores(&mut self)
{
println!("Human Score: {}", self.human_score);
println!("Computer Score: {}", self.computer_score);
}
fn winner(&mut self)
{
if self.human_score > self.computer_score
{
println!("Human Wins with a score of: {}", self.human_score);
}
else if self.human_score < self.computer_score
{
println!("Computer Wins with a score of: {}", self.computer_score);
}
else
{
println!("It's a tie!");
}
}
}
fn main()
{
println!("Welcome to the Go Fish Game!");
println!("----------------------------");
let mut game = Game::new();
game.play();
}