Go Fish/Rust
< Go Fish
Go Fish/Rust is part of Go_Fish. You may find other members of Go_Fish at Category:Go_Fish.
Rust implementation of Go Fish.
use rand::thread_rng;
use rand::seq::SliceRandom;
use std::io::Write;
// parameters
const STARTING_HAND_SIZE: usize = 9;
const NUM_SUITS: usize = 4;
struct Deck {
cards: Vec<String>,
}
impl Deck {
fn new() -> Self {
Self { // initializes deck with cards
cards: {
let mut deck = vec![];
for i in "2 3 4 5 6 7 8 9 10 J Q K A".split(" ") {
for _ in 0..NUM_SUITS {
deck.push(String::from(i));
}
}
deck
}
}
}
fn shuffle(&mut self) {
self.cards.shuffle(&mut thread_rng());
}
fn done(&self) -> bool {
self.cards.len() == 0
}
fn draw(& mut self) -> String {
self.cards.pop().unwrap()
}
}
struct Player {
hand: Vec<String>,
score: usize,
name: String,
}
impl Player {
fn new(deck: &mut Deck, name: &str) -> Self {
// initializes player, draws starting hand
let mut p = Self {
hand: vec![],
score: 0,
name: String::from(name),
};
for _ in 0..STARTING_HAND_SIZE {
p.add(deck.draw(), deck);
}
p
}
fn done(&self) -> bool {
self.hand.len() == 0
}
fn draw(&mut self, deck: &mut Deck) {
self.add(deck.draw(), deck);
}
fn has(&self, card: &String) -> bool {
self.hand.contains(card)
}
fn take(&mut self, card: &String) -> Option<String> {
if self.has(card) {
let mut i = 0;
for c in &self.hand {
if c == card {
break;
}
i += 1;
}
Some(self.hand.remove(i))
} else {
None
}
}
fn add(&mut self, card: String, deck: &mut Deck) {
// adds card to hand. If you have NUM_SUITS, get a book. If you have no cards, draw.
if self.hand.contains(&card) {
let mut i = 0;
for item in &self.hand {
if item == &card {
i += 1;
}
}
if i == NUM_SUITS-1 {
while self.has(&card) { self.take(&card); }
self.score += 1;
if self.done() && !deck.done() {
self.draw(deck);
}
return;
}
}
self.hand.push(card);
self.hand.sort();
}
}
fn input(string: &str) -> String {
print!("{}", string);
std::io::stdout().flush().unwrap();
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
line.pop(); // \n\r
line.pop();
line
}
fn main() {
let mut thread = thread_rng();
let mut deck = Deck::new();
deck.shuffle();
let mut user = Player::new(&mut deck, &input("Enter your name: "));
let mut npc = Player::new(&mut deck, "NPC");
let mut has_guessed = vec![];
let mut player_turn = true; // toggle
while !deck.done() {
println!("\n\ndeck size: {}", deck.cards.len());
if player_turn {
while !deck.done() {
print!("\n== {}'s Turn ==\n{}: {}\nNPC: {}\nYOUR HAND: ", user.name, user.name, user.score, npc.score);
for card in &user.hand {
print!("{} ", card);
}
let mut choice = input("\nYou fish for a: ");
while !"2 3 4 5 6 7 8 9 10 J Q K A".split(" ").collect::<Vec<&str>>().contains(&choice.as_str()) || !user.hand.contains(&choice) {
println!("invalid response, expecting 2, 3, 4, 5, ..., Q, K, A. The card must be in your hand.");
choice = input("You fish for a: ");
}
if !has_guessed.contains(&choice) { has_guessed.push(choice.clone()); }
match npc.take(&choice) {
Some(thing) => {
user.add(thing, &mut deck);
while npc.has(&choice) {
user.add(npc.take(&choice).unwrap(), &mut deck);
}
println!("Yes, go again");
}
None => {
user.draw(&mut deck);
println!("Go fish!");
break;
}
}
}
} else {
while !deck.done() {
print!("\n== NPC's Turn ==\n{}: {}\nNPC: {}\nYOUR HAND: ", user.name, user.score, npc.score);
for card in &user.hand {
print!("{} ", card);
}
// guess if user has guessed & you have
let mut choice = String::new();
for string in &has_guessed {
if npc.hand.contains(string) {
choice = string.clone();
}
}
if &choice == "" {
choice = npc.hand.choose(&mut thread).unwrap().clone();
}
println!("\nDo you have a {}?", choice);
match user.take(&choice) {
Some(thing) => {
println!("Yes, I do.");
npc.add(thing, &mut deck);
while user.has(&choice) {
npc.add(user.take(&choice).unwrap(), &mut deck);
}
input("\n...");
}
None => {
npc.draw(&mut deck);
println!("Go fish!");
input("\n...");
break;
}
}
}
}
player_turn = !player_turn;
}
if deck.done() {
println!("Deck Empty, Game Over");
}
if user.score > npc.score {
println!("{} has won with a score of {}", user.name, user.score);
} else if user.score == npc.score {
println!("{} and {} have tied with a score of {}", user.name, npc.name, user.score);
} else {
println!("{} has won with a score of {}", npc.name, npc.score);
}
}