Add repo.
// vigyazz6! autplayer
//
use core::fmt;
use std::collections::VecDeque;
use rand::Rng;
use std::mem;
fn main() {
println!("Hello, world!");
}
#[derive(Debug)]
struct Card {
value: i8,
points: i8,
}
impl Card {
fn new(value: i8)->Self {
let mut points = 0;
if value % 10 == 5 {
// ends with 5 = 2 point
points = 2;
// println!("*5 add 1, val={}, pt={}", value, points);
}
if value % 10 == 0 {
// ends with 0 = 3 point
points = 3;
// println!("*0 add 2, val={}, pt={}", value, points);
}
if value % 10 == value / 10 {
// same numbers = 5 points (55=7)
points += 5;
// println!("NN add 5, val={}, pt={}", value, points);
}
if points == 0 {
points = 1;
}
Card {
value,
points,
}
}
}
impl fmt::Display for Card {
fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {
write!(f, "(Card {}, points {})", self.value, self.points)
}
}
impl PartialEq for Card {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
struct Deck {
content: VecDeque<Card>,
}
impl Deck {
fn new_empty() -> Self {
Deck {
content: VecDeque::new(),
}
}
fn new() -> Self {
let content = (1..104).into_iter().map( |n| Card::new(n) ).collect();
Deck {
content,
}
}
fn shuffle( &mut self ) {
let mut rng = rand::thread_rng();
// shufflers:
// * naive: swap cards n times
// * kgb: half the deck, take 1..4 cards sequentially from each
// * grin: take 1..6 from front and put at bottom
// naive shuffle: exchange random cards
for _i in 1..500 {
let c1 = rng.gen_range(1 .. self.content.len());
let c2 = rng.gen_range(1 .. self.content.len());
if c1 != c2 {
self.content.swap(c1, c2);
}
}
}
// get top card from deck
fn pop( &mut self ) -> Option<Card> {
self.content.pop_front()
}
// put a card into the bottom of the deck
fn push( &mut self, c: Card ) {
self.content.push_back(c);
}
fn len( &self ) -> usize {
self.content.len()
}
fn get_nth( &mut self, n: usize ) -> Card {
if let Some(c) = self.content.remove(n) {
c
} else {
panic!("get_nth: index {} out of bounds ({})!", n, self.content.len());
}
}
}
struct Player {
name: String,
hand: Deck,
pile: Vec<Card>,
game_point: i32,
total_point: i32,
rows_busted: i32,
}
impl Player {
fn new(name: String)->Self {
Player {
name,
hand: Deck::new_empty(),
pile: Vec::new(),
game_point: 0,
total_point: 0,
rows_busted: 0,
}
}
// get one card from th dealer
fn get_card( &mut self, card: Card ) {
self.hand.push(card);
}
// throw a card from hand to the table
fn throw_card( &mut self )->Card {
if let Some(c) = self.hand.pop() {
c
} else {
panic!("throw_card: Player {} has no card in hand!", self.name);
}
}
// get a busted row of cards
fn get_pile( &mut self, cards: Vec<Card> ) {
for c in cards.into_iter() {
self.game_point += c.points as i32;
self.pile.push(c);
}
self.rows_busted += 1;
}
// ask the player their score
fn tell_points( self ) -> i32 {
self.game_point
}
// give back cards from the pile
fn give_pile( &mut self ) -> Vec<Card> {
mem::take( &mut self.pile )
// same effect:
// self.pile.drain(..).collect()
// very cumbersome manual fiddling (also reverted...)
/* let mut throw: Vec<Card> = Vec::new();
for _i in 0 .. self.pile.len() {
throw.push( self.pile.pop().unwrap() );
}
throw
*/
}
// I can do this just because I *throw away* c!
// doesn't work if I want to use it.
/* fn _gimme_pile(self)->Self {
for c in &self.pile {
println!("Throw {} ", c);
}
self
}
*/
fn close_round( &mut self ) {
if self.hand.len() > 0 {
panic!("Closing round when {} has {} cards in hand", self.name, self.hand.len());
}
if self.pile.len() > 0 {
panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len());
}
self.total_point += self.game_point;
self.game_point = 0;
}
}
// a row of cards on the table (max 5)
struct Row {
cards: VecDeque<Card>,
}
impl Row {
const MAX_LEN: usize = 5;
fn new() -> Self {
Row {
cards: VecDeque::new(),
}
}
fn push_or_collect( &mut self, card: Card ) -> Option<VecDeque<Card>> {
if self.cards.len() < Self::MAX_LEN {
self.cards.push_back(card);
None
} else {
// row overflow
let row_cards = mem::take( &mut self.cards );
self.cards.push_back(card);
if self.cards.len() != 1 {
panic!("New row must have one card, not {}", self.cards.len());
}
Some(row_cards)
}
}
fn last_card_value(&self) -> i8 {
println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len());
self.cards.get( self.cards.len()-1 ).unwrap().value
}
}
struct PlayerCard {
player_id: u32,
card: Card,
}
struct Table {
rows: Vec<Row>,
player_cards: Vec<PlayerCard>, // owned by a player
}
fn game() {
/*
let mut deck = deck_init();
let mut players = Vec::new();
for cnt_game in (1..100) {
}
*/
}
#[cfg(test)]
mod tests {
use crate::{Card, Player, Row};
#[test]
fn card_values() {
let card_values = vec![1,2,5,10,33,55,77];
let card_points = vec![1,1,2,3, 5, 7, 5];
for i in 1 .. card_values.len() {
let c = Card::new( card_values[i] );
let p = c.points;
assert!(p == card_points[i], "card={} card points={} i={} expected point={}", card_values[i], p, i, card_points[i]);
}
}
#[test]
fn player_take_pile() {
// create a player
let mut p = Player::new("bob".to_string());
// create a pile
let mut pile = Vec::new();
let mut refpile = Vec::new();
for i in 5..10 {
let c = Card::new(i);
pile.push(c);
let c = Card::new(i);
refpile.push(c);
}
// add the pile to player
p.get_pile(pile);
assert!( p.rows_busted == 1 );
// get back the pile from player
// p = p.gimme_pile();
let pile = p.give_pile();
// the pile we got shall be same as the pile we gave
// this check is O(n^2), doesn't matter for less than 100 items
assert!( pile.iter().all( |item| refpile.contains(item)) );
let mut pile = Vec::new();
for i in 4..9 {
let c = Card::new(i);
pile.push(c);
}
p.get_pile(pile);
assert!( p.rows_busted == 2 );
}
#[test]
fn row_push() {
let mut row = Row::new();
let mut refcard = Vec::new(); // reference vec to check
for i in 1..=7 {
let cval = i+5;
let card = Card::new(cval);
// push a card into the row
if let Some(cards) = row.push_or_collect(card) {
// got the overflow
println!("Got overflow row at {}!", i);
assert!( i == 6, "Overflow at wrong position: {} != 6", i );
// we need to get the proper vec
assert!( cards.iter().all( |item| refcard.contains(item) ), "Got cards {:?}", cards );
} else {
println!("push success {}", i);
}
// remember the correct vec for checking
let card = Card::new(cval);
refcard.push(card);
// check card value
assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval );
}
assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() );
}
}
/*
- 1-104 lap,
- *5 - 2
- *0 - 3
- NN - 5
- 55 - 7
- deck
- jatekosok; kezben tartott lapok; elvitt lapok; pontszamok; counter: elvitt sorok, okrok, total pont
-- keveres (keveresek szama)
-- osztas: mindenki 10 lap
-- start sorok: 5 kartya
- jatek (jatekok szama)
-- mindenki a felso lapot kiteszi
-- szamsorrendben felkerulnek, aki viszi, viszi
--- ha kisebb, akkor dontes
---- ha van legkevesebb, viszi
---- ha tobb min van, random valaszt
- osszesites
-- okrok, elvitt sorok
-- keveresek szama, jatekok szama, eltelt ido
- deck osszegyujtes
*/