|
1 // vigyazz6! autplayer |
|
2 // |
|
3 |
|
4 use core::fmt; |
|
5 use std::collections::VecDeque; |
|
6 use rand::Rng; |
|
7 use std::mem; |
|
8 |
|
9 fn main() { |
|
10 println!("Hello, world!"); |
|
11 } |
|
12 |
|
13 #[derive(Debug)] |
|
14 struct Card { |
|
15 value: i8, |
|
16 points: i8, |
|
17 } |
|
18 |
|
19 impl Card { |
|
20 fn new(value: i8)->Self { |
|
21 |
|
22 let mut points = 0; |
|
23 if value % 10 == 5 { |
|
24 // ends with 5 = 2 point |
|
25 points = 2; |
|
26 // println!("*5 add 1, val={}, pt={}", value, points); |
|
27 } |
|
28 |
|
29 if value % 10 == 0 { |
|
30 // ends with 0 = 3 point |
|
31 points = 3; |
|
32 // println!("*0 add 2, val={}, pt={}", value, points); |
|
33 } |
|
34 |
|
35 if value % 10 == value / 10 { |
|
36 // same numbers = 5 points (55=7) |
|
37 points += 5; |
|
38 // println!("NN add 5, val={}, pt={}", value, points); |
|
39 } |
|
40 |
|
41 if points == 0 { |
|
42 points = 1; |
|
43 } |
|
44 |
|
45 Card { |
|
46 value, |
|
47 points, |
|
48 } |
|
49 } |
|
50 } |
|
51 |
|
52 impl fmt::Display for Card { |
|
53 fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result { |
|
54 write!(f, "(Card {}, points {})", self.value, self.points) |
|
55 } |
|
56 } |
|
57 |
|
58 impl PartialEq for Card { |
|
59 fn eq(&self, other: &Self) -> bool { |
|
60 self.value == other.value |
|
61 } |
|
62 } |
|
63 |
|
64 struct Deck { |
|
65 content: VecDeque<Card>, |
|
66 } |
|
67 |
|
68 impl Deck { |
|
69 fn new_empty() -> Self { |
|
70 Deck { |
|
71 content: VecDeque::new(), |
|
72 } |
|
73 } |
|
74 |
|
75 fn new() -> Self { |
|
76 let content = (1..104).into_iter().map( |n| Card::new(n) ).collect(); |
|
77 Deck { |
|
78 content, |
|
79 } |
|
80 } |
|
81 |
|
82 fn shuffle( &mut self ) { |
|
83 let mut rng = rand::thread_rng(); |
|
84 |
|
85 // shufflers: |
|
86 // * naive: swap cards n times |
|
87 // * kgb: half the deck, take 1..4 cards sequentially from each |
|
88 // * grin: take 1..6 from front and put at bottom |
|
89 |
|
90 // naive shuffle: exchange random cards |
|
91 for _i in 1..500 { |
|
92 let c1 = rng.gen_range(1 .. self.content.len()); |
|
93 let c2 = rng.gen_range(1 .. self.content.len()); |
|
94 if c1 != c2 { |
|
95 self.content.swap(c1, c2); |
|
96 } |
|
97 } |
|
98 } |
|
99 |
|
100 // get top card from deck |
|
101 fn pop( &mut self ) -> Option<Card> { |
|
102 self.content.pop_front() |
|
103 } |
|
104 |
|
105 // put a card into the bottom of the deck |
|
106 fn push( &mut self, c: Card ) { |
|
107 self.content.push_back(c); |
|
108 } |
|
109 |
|
110 fn len( &self ) -> usize { |
|
111 self.content.len() |
|
112 } |
|
113 |
|
114 fn get_nth( &mut self, n: usize ) -> Card { |
|
115 if let Some(c) = self.content.remove(n) { |
|
116 c |
|
117 } else { |
|
118 panic!("get_nth: index {} out of bounds ({})!", n, self.content.len()); |
|
119 } |
|
120 } |
|
121 } |
|
122 |
|
123 struct Player { |
|
124 name: String, |
|
125 hand: Deck, |
|
126 pile: Vec<Card>, |
|
127 game_point: i32, |
|
128 total_point: i32, |
|
129 rows_busted: i32, |
|
130 } |
|
131 |
|
132 impl Player { |
|
133 fn new(name: String)->Self { |
|
134 Player { |
|
135 name, |
|
136 hand: Deck::new_empty(), |
|
137 pile: Vec::new(), |
|
138 game_point: 0, |
|
139 total_point: 0, |
|
140 rows_busted: 0, |
|
141 } |
|
142 } |
|
143 |
|
144 // get one card from th dealer |
|
145 fn get_card( &mut self, card: Card ) { |
|
146 self.hand.push(card); |
|
147 } |
|
148 |
|
149 // throw a card from hand to the table |
|
150 fn throw_card( &mut self )->Card { |
|
151 if let Some(c) = self.hand.pop() { |
|
152 c |
|
153 } else { |
|
154 panic!("throw_card: Player {} has no card in hand!", self.name); |
|
155 } |
|
156 } |
|
157 |
|
158 // get a busted row of cards |
|
159 fn get_pile( &mut self, cards: Vec<Card> ) { |
|
160 for c in cards.into_iter() { |
|
161 self.game_point += c.points as i32; |
|
162 self.pile.push(c); |
|
163 } |
|
164 self.rows_busted += 1; |
|
165 } |
|
166 |
|
167 // ask the player their score |
|
168 fn tell_points( self ) -> i32 { |
|
169 self.game_point |
|
170 } |
|
171 |
|
172 // give back cards from the pile |
|
173 fn give_pile( &mut self ) -> Vec<Card> { |
|
174 mem::take( &mut self.pile ) |
|
175 // same effect: |
|
176 // self.pile.drain(..).collect() |
|
177 |
|
178 // very cumbersome manual fiddling (also reverted...) |
|
179 /* let mut throw: Vec<Card> = Vec::new(); |
|
180 for _i in 0 .. self.pile.len() { |
|
181 throw.push( self.pile.pop().unwrap() ); |
|
182 } |
|
183 throw |
|
184 */ |
|
185 } |
|
186 |
|
187 // I can do this just because I *throw away* c! |
|
188 // doesn't work if I want to use it. |
|
189 /* fn _gimme_pile(self)->Self { |
|
190 for c in &self.pile { |
|
191 println!("Throw {} ", c); |
|
192 } |
|
193 self |
|
194 } |
|
195 */ |
|
196 fn close_round( &mut self ) { |
|
197 if self.hand.len() > 0 { |
|
198 panic!("Closing round when {} has {} cards in hand", self.name, self.hand.len()); |
|
199 } |
|
200 |
|
201 if self.pile.len() > 0 { |
|
202 panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len()); |
|
203 } |
|
204 |
|
205 self.total_point += self.game_point; |
|
206 self.game_point = 0; |
|
207 } |
|
208 } |
|
209 |
|
210 // a row of cards on the table (max 5) |
|
211 struct Row { |
|
212 cards: VecDeque<Card>, |
|
213 } |
|
214 |
|
215 impl Row { |
|
216 const MAX_LEN: usize = 5; |
|
217 |
|
218 fn new() -> Self { |
|
219 Row { |
|
220 cards: VecDeque::new(), |
|
221 } |
|
222 } |
|
223 |
|
224 fn push_or_collect( &mut self, card: Card ) -> Option<VecDeque<Card>> { |
|
225 if self.cards.len() < Self::MAX_LEN { |
|
226 self.cards.push_back(card); |
|
227 None |
|
228 |
|
229 } else { |
|
230 // row overflow |
|
231 let row_cards = mem::take( &mut self.cards ); |
|
232 self.cards.push_back(card); |
|
233 if self.cards.len() != 1 { |
|
234 panic!("New row must have one card, not {}", self.cards.len()); |
|
235 } |
|
236 Some(row_cards) |
|
237 } |
|
238 } |
|
239 |
|
240 fn last_card_value(&self) -> i8 { |
|
241 println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len()); |
|
242 self.cards.get( self.cards.len()-1 ).unwrap().value |
|
243 } |
|
244 } |
|
245 |
|
246 struct PlayerCard { |
|
247 player_id: u32, |
|
248 card: Card, |
|
249 } |
|
250 |
|
251 struct Table { |
|
252 rows: Vec<Row>, |
|
253 player_cards: Vec<PlayerCard>, // owned by a player |
|
254 } |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 fn game() { |
|
260 /* |
|
261 let mut deck = deck_init(); |
|
262 let mut players = Vec::new(); |
|
263 |
|
264 for cnt_game in (1..100) { |
|
265 |
|
266 } |
|
267 */ |
|
268 } |
|
269 |
|
270 #[cfg(test)] |
|
271 mod tests { |
|
272 use crate::{Card, Player, Row}; |
|
273 |
|
274 #[test] |
|
275 fn card_values() { |
|
276 let card_values = vec![1,2,5,10,33,55,77]; |
|
277 let card_points = vec![1,1,2,3, 5, 7, 5]; |
|
278 for i in 1 .. card_values.len() { |
|
279 let c = Card::new( card_values[i] ); |
|
280 let p = c.points; |
|
281 assert!(p == card_points[i], "card={} card points={} i={} expected point={}", card_values[i], p, i, card_points[i]); |
|
282 } |
|
283 } |
|
284 |
|
285 #[test] |
|
286 fn player_take_pile() { |
|
287 // create a player |
|
288 let mut p = Player::new("bob".to_string()); |
|
289 // create a pile |
|
290 let mut pile = Vec::new(); |
|
291 let mut refpile = Vec::new(); |
|
292 for i in 5..10 { |
|
293 let c = Card::new(i); |
|
294 pile.push(c); |
|
295 let c = Card::new(i); |
|
296 refpile.push(c); |
|
297 } |
|
298 // add the pile to player |
|
299 p.get_pile(pile); |
|
300 assert!( p.rows_busted == 1 ); |
|
301 |
|
302 // get back the pile from player |
|
303 // p = p.gimme_pile(); |
|
304 let pile = p.give_pile(); |
|
305 |
|
306 // the pile we got shall be same as the pile we gave |
|
307 // this check is O(n^2), doesn't matter for less than 100 items |
|
308 assert!( pile.iter().all( |item| refpile.contains(item)) ); |
|
309 |
|
310 let mut pile = Vec::new(); |
|
311 for i in 4..9 { |
|
312 let c = Card::new(i); |
|
313 pile.push(c); |
|
314 } |
|
315 p.get_pile(pile); |
|
316 assert!( p.rows_busted == 2 ); |
|
317 } |
|
318 |
|
319 #[test] |
|
320 fn row_push() { |
|
321 let mut row = Row::new(); |
|
322 let mut refcard = Vec::new(); // reference vec to check |
|
323 for i in 1..=7 { |
|
324 let cval = i+5; |
|
325 let card = Card::new(cval); |
|
326 // push a card into the row |
|
327 if let Some(cards) = row.push_or_collect(card) { |
|
328 // got the overflow |
|
329 println!("Got overflow row at {}!", i); |
|
330 assert!( i == 6, "Overflow at wrong position: {} != 6", i ); |
|
331 // we need to get the proper vec |
|
332 assert!( cards.iter().all( |item| refcard.contains(item) ), "Got cards {:?}", cards ); |
|
333 } else { |
|
334 println!("push success {}", i); |
|
335 } |
|
336 // remember the correct vec for checking |
|
337 let card = Card::new(cval); |
|
338 refcard.push(card); |
|
339 |
|
340 // check card value |
|
341 assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval ); |
|
342 } |
|
343 assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() ); |
|
344 } |
|
345 } |
|
346 |
|
347 /* |
|
348 |
|
349 - 1-104 lap, |
|
350 - *5 - 2 |
|
351 - *0 - 3 |
|
352 - NN - 5 |
|
353 - 55 - 7 |
|
354 - deck |
|
355 - jatekosok; kezben tartott lapok; elvitt lapok; pontszamok; counter: elvitt sorok, okrok, total pont |
|
356 -- keveres (keveresek szama) |
|
357 -- osztas: mindenki 10 lap |
|
358 -- start sorok: 5 kartya |
|
359 - jatek (jatekok szama) |
|
360 -- mindenki a felso lapot kiteszi |
|
361 -- szamsorrendben felkerulnek, aki viszi, viszi |
|
362 --- ha kisebb, akkor dontes |
|
363 ---- ha van legkevesebb, viszi |
|
364 ---- ha tobb min van, random valaszt |
|
365 - osszesites |
|
366 -- okrok, elvitt sorok |
|
367 -- keveresek szama, jatekok szama, eltelt ido |
|
368 - deck osszegyujtes |
|
369 |
|
370 |
|
371 */ |