changeset 1 | 5f81068a8a88 |
parent 0 | a95b84125269 |
child 2 | 950660fddec0 |
0:a95b84125269 | 1:5f81068a8a88 |
---|---|
1 // vigyazz6! autplayer |
1 // vigyazz6! autplayer |
2 // |
2 // |
3 |
3 |
4 use core::fmt; |
4 use core::{fmt, panic}; |
5 use std::collections::VecDeque; |
5 use std::collections::VecDeque; |
6 use rand::Rng; |
6 use rand::Rng; |
7 use std::mem; |
7 use std::mem; |
8 |
8 |
9 fn main() { |
9 fn main() { |
10 println!("Hello, world!"); |
10 game(); |
11 } |
11 } |
12 |
12 |
13 #[derive(Debug)] |
13 #[derive(Debug)] |
14 struct Card { |
14 struct Card { |
15 value: i8, |
15 value: i8, |
59 fn eq(&self, other: &Self) -> bool { |
59 fn eq(&self, other: &Self) -> bool { |
60 self.value == other.value |
60 self.value == other.value |
61 } |
61 } |
62 } |
62 } |
63 |
63 |
64 impl Eq for Card {} |
|
65 |
|
66 impl PartialOrd for Card { |
|
67 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
|
68 match self.value.partial_cmp(&other.value) { |
|
69 Some(core::cmp::Ordering::Equal) => {None} |
|
70 ord => return ord, |
|
71 } |
|
72 } |
|
73 } |
|
74 |
|
75 impl Ord for Card { |
|
76 fn cmp(&self, other: &Self) -> std::cmp::Ordering { |
|
77 self.value.cmp(&other.value) |
|
78 } |
|
79 } |
|
80 |
|
81 |
|
82 #[derive(Debug)] |
|
64 struct Deck { |
83 struct Deck { |
65 content: VecDeque<Card>, |
84 content: VecDeque<Card>, |
66 } |
85 } |
67 |
86 |
68 impl Deck { |
87 impl Deck { |
86 // * naive: swap cards n times |
105 // * naive: swap cards n times |
87 // * kgb: half the deck, take 1..4 cards sequentially from each |
106 // * kgb: half the deck, take 1..4 cards sequentially from each |
88 // * grin: take 1..6 from front and put at bottom |
107 // * grin: take 1..6 from front and put at bottom |
89 |
108 |
90 // naive shuffle: exchange random cards |
109 // naive shuffle: exchange random cards |
91 for _i in 1..500 { |
110 for _i in 1..=500 { |
92 let c1 = rng.gen_range(1 .. self.content.len()); |
111 let c1 = rng.gen_range(0 .. self.content.len()); |
93 let c2 = rng.gen_range(1 .. self.content.len()); |
112 let c2 = rng.gen_range(0 .. self.content.len()); |
94 if c1 != c2 { |
113 if c1 != c2 { |
95 self.content.swap(c1, c2); |
114 self.content.swap(c1, c2); |
96 } |
115 } |
97 } |
116 } |
98 } |
117 } |
118 panic!("get_nth: index {} out of bounds ({})!", n, self.content.len()); |
137 panic!("get_nth: index {} out of bounds ({})!", n, self.content.len()); |
119 } |
138 } |
120 } |
139 } |
121 } |
140 } |
122 |
141 |
142 #[derive(Debug)] |
|
123 struct Player { |
143 struct Player { |
124 name: String, |
144 name: String, |
125 hand: Deck, |
145 hand: Deck, |
126 pile: Vec<Card>, |
146 pile: Vec<Card>, |
127 game_point: i32, |
147 game_point: i32, |
154 panic!("throw_card: Player {} has no card in hand!", self.name); |
174 panic!("throw_card: Player {} has no card in hand!", self.name); |
155 } |
175 } |
156 } |
176 } |
157 |
177 |
158 // get a busted row of cards |
178 // get a busted row of cards |
159 fn get_pile( &mut self, cards: Vec<Card> ) { |
179 fn get_pile( &mut self, cards: VecDeque<Card> ) { |
160 for c in cards.into_iter() { |
180 for c in cards.into_iter() { |
161 self.game_point += c.points as i32; |
181 self.game_point += c.points as i32; |
162 self.pile.push(c); |
182 self.pile.push(c); |
163 } |
183 } |
164 self.rows_busted += 1; |
184 self.rows_busted += 1; |
206 self.game_point = 0; |
226 self.game_point = 0; |
207 } |
227 } |
208 } |
228 } |
209 |
229 |
210 // a row of cards on the table (max 5) |
230 // a row of cards on the table (max 5) |
231 #[derive(Debug)] |
|
211 struct Row { |
232 struct Row { |
212 cards: VecDeque<Card>, |
233 cards: VecDeque<Card>, |
213 } |
234 } |
214 |
235 |
215 impl Row { |
236 impl Row { |
241 println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len()); |
262 println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len()); |
242 self.cards.get( self.cards.len()-1 ).unwrap().value |
263 self.cards.get( self.cards.len()-1 ).unwrap().value |
243 } |
264 } |
244 } |
265 } |
245 |
266 |
267 #[derive(Debug)] |
|
246 struct PlayerCard { |
268 struct PlayerCard { |
247 player_id: u32, |
269 player_id: i32, |
248 card: Card, |
270 card: Card, |
249 } |
271 } |
250 |
272 |
273 impl PlayerCard { |
|
274 fn get_player(&self) -> i32 { |
|
275 self.player_id |
|
276 } |
|
277 } |
|
278 |
|
279 impl PartialEq for PlayerCard { |
|
280 fn eq(&self, other: &Self) -> bool { |
|
281 self.card == other.card |
|
282 } |
|
283 } |
|
284 |
|
285 impl PartialOrd for PlayerCard { |
|
286 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
|
287 match self.card.partial_cmp(&other.card) { |
|
288 Some(core::cmp::Ordering::Equal) => {None} |
|
289 ord => return ord, |
|
290 } |
|
291 } |
|
292 } |
|
293 |
|
294 #[derive(Debug)] |
|
251 struct Table { |
295 struct Table { |
252 rows: Vec<Row>, |
296 rows: Vec<Row>, |
253 player_cards: Vec<PlayerCard>, // owned by a player |
297 player_cards: Vec<PlayerCard>, // owned by a player |
254 } |
298 } |
255 |
299 |
256 |
300 impl Table { |
301 fn new(row_cards: Vec<Card>) -> Self { |
|
302 let mut rows = Vec::new(); |
|
303 for card in row_cards { |
|
304 // create a new row then put a card into it |
|
305 let mut row = Row::new(); |
|
306 if let Some(c) = row.push_or_collect(card) { |
|
307 panic!("Freshly created row overflowed"); |
|
308 } |
|
309 rows.push( row ); |
|
310 } |
|
311 |
|
312 Table { |
|
313 rows, |
|
314 player_cards: Vec::new(), |
|
315 } |
|
316 } |
|
317 |
|
318 fn lay_player_card( &mut self, card: Card, player_id: i32 ) { |
|
319 self.player_cards.push( PlayerCard { player_id, card } ); |
|
320 } |
|
321 |
|
322 fn sort_cards( &mut self ) { |
|
323 self.player_cards.sort_by( |a,b| b.card.cmp(&a.card) ); |
|
324 } |
|
325 |
|
326 fn get_smallest_player_card( &mut self ) -> PlayerCard { |
|
327 self.player_cards.pop().expect("out of player cards on table") |
|
328 } |
|
329 |
|
330 fn get_closest_row( &self, pcard: &PlayerCard ) -> Option<i8> { |
|
331 // get the row id with last card closest smaller to players' |
|
332 todo!() |
|
333 } |
|
334 |
|
335 fn put_card_into_row( &mut self, pcard: PlayerCard, row_id: i8 ) -> Option<VecDeque<Card>> { |
|
336 self.rows[row_id as usize].push_or_collect(pcard.card) |
|
337 } |
|
338 } |
|
257 |
339 |
258 |
340 |
259 fn game() { |
341 fn game() { |
260 /* |
342 let mut cnt_shuffle = 0; |
261 let mut deck = deck_init(); |
343 |
262 let mut players = Vec::new(); |
344 let mut deck = Deck::new(); |
263 |
345 |
264 for cnt_game in (1..100) { |
346 let player_names = vec![ "grin", "moni", "icbalint", "orsi", "topi", "kgb", "zsu", "csilla" ]; |
265 |
347 let mut players: Vec<Player> = player_names.iter().map( |n| Player::new(n.to_string()) ).collect(); |
266 } |
348 |
267 */ |
349 let player_count = players.len(); // pc - 1 |
350 |
|
351 for _cnt_game in 1..=2 { |
|
352 deck.shuffle(); |
|
353 cnt_shuffle += 1; |
|
354 |
|
355 // dealing |
|
356 for i in 1..=10 { |
|
357 for player in 0 .. player_count { |
|
358 players[player].get_card( deck.pop().expect("Deck is empty while dealing to players") ); |
|
359 } |
|
360 } |
|
361 |
|
362 // we need 5 crds from deck |
|
363 let mut cards = Vec::new(); |
|
364 for i in 1..=5 { |
|
365 cards.push( deck.pop().expect("deck empty before starting the game") ); |
|
366 } |
|
367 println!("We push 5 cards to rows: {:?}\n", cards); |
|
368 let mut table = Table::new(cards); |
|
369 |
|
370 // DEBUG |
|
371 println!("Table: {:?}\n", table); |
|
372 println!("PLayers: {:?}\n", players); |
|
373 println!("Deck: {:?}\n", deck); |
|
374 |
|
375 |
|
376 // playing |
|
377 for turn in 1..=10 { |
|
378 |
|
379 // everyone puts a card face down |
|
380 for player in 0 .. player_count { |
|
381 let player_id: i32 = player.try_into().unwrap(); |
|
382 // get a card from the player |
|
383 let topcard = players[player].throw_card(); |
|
384 // put it on the table ("turned face down") |
|
385 table.lay_player_card( topcard, player_id ); |
|
386 } |
|
387 |
|
388 // process cards |
|
389 table.sort_cards(); |
|
390 |
|
391 let smallest = table.get_smallest_player_card(); |
|
392 |
|
393 let closest_row = table.get_closest_row(&smallest); |
|
394 match closest_row { |
|
395 Some(rowid) => { |
|
396 let player_id: usize = smallest.player_id.try_into().unwrap(); |
|
397 let overflow = table.put_card_into_row(smallest, rowid); |
|
398 if let Some(cards) = overflow { |
|
399 // row is full, got pile |
|
400 // player gets pile, card gets into row head |
|
401 players[ player_id ].get_pile( cards ); |
|
402 } |
|
403 }, |
|
404 None => { |
|
405 // card too small, need to pick row! |
|
406 todo!(); |
|
407 } |
|
408 } |
|
409 |
|
410 } |
|
411 |
|
412 // end of round |
|
413 |
|
414 // recollect deck |
|
415 |
|
416 panic!("FInish now."); |
|
417 } |
|
268 } |
418 } |
269 |
419 |
270 #[cfg(test)] |
420 #[cfg(test)] |
271 mod tests { |
421 mod tests { |
422 use core::panic; |
|
423 use std::collections::VecDeque; |
|
424 |
|
425 use rand::Rng; |
|
426 |
|
272 use crate::{Card, Player, Row}; |
427 use crate::{Card, Player, Row}; |
273 |
428 |
274 #[test] |
429 #[test] |
275 fn card_values() { |
430 fn card_values() { |
276 let card_values = vec![1,2,5,10,33,55,77]; |
431 let card_values = vec![1,2,5,10,33,55,77]; |
285 #[test] |
440 #[test] |
286 fn player_take_pile() { |
441 fn player_take_pile() { |
287 // create a player |
442 // create a player |
288 let mut p = Player::new("bob".to_string()); |
443 let mut p = Player::new("bob".to_string()); |
289 // create a pile |
444 // create a pile |
290 let mut pile = Vec::new(); |
445 let mut pile = VecDeque::new(); |
291 let mut refpile = Vec::new(); |
446 let mut refpile = Vec::new(); |
292 for i in 5..10 { |
447 for i in 5..10 { |
293 let c = Card::new(i); |
448 let c = Card::new(i); |
294 pile.push(c); |
449 pile.push_back(c); |
295 let c = Card::new(i); |
450 let c = Card::new(i); |
296 refpile.push(c); |
451 refpile.push(c); |
297 } |
452 } |
298 // add the pile to player |
453 // add the pile to player |
299 p.get_pile(pile); |
454 p.get_pile(pile); |
305 |
460 |
306 // the pile we got shall be same as the pile we gave |
461 // 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 |
462 // this check is O(n^2), doesn't matter for less than 100 items |
308 assert!( pile.iter().all( |item| refpile.contains(item)) ); |
463 assert!( pile.iter().all( |item| refpile.contains(item)) ); |
309 |
464 |
310 let mut pile = Vec::new(); |
465 let mut pile = VecDeque::new(); |
311 for i in 4..9 { |
466 for i in 4..=9 { |
312 let c = Card::new(i); |
467 let c = Card::new(i); |
313 pile.push(c); |
468 pile.push_back(c); |
314 } |
469 } |
315 p.get_pile(pile); |
470 p.get_pile(pile); |
316 assert!( p.rows_busted == 2 ); |
471 assert!( p.rows_busted == 2 ); |
317 } |
472 } |
318 |
473 |
340 // check card value |
495 // check card value |
341 assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval ); |
496 assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval ); |
342 } |
497 } |
343 assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() ); |
498 assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() ); |
344 } |
499 } |
500 |
|
501 #[test] |
|
502 fn sort_cards() { |
|
503 let mut cards: Vec<Card> = Vec::new(); |
|
504 let mut rng = rand::thread_rng(); |
|
505 for i in 1..50 { |
|
506 let n = rng.gen_range(1..104); |
|
507 cards.push( Card::new(n) ); |
|
508 } |
|
509 cards.sort(); |
|
510 |
|
511 for i in 1..cards.len() { |
|
512 assert!( cards[i-1].value <= cards[i].value, "Bad ordering: {} > {}", cards[i-1].value,cards[i].value ); |
|
513 } |
|
514 } |
|
515 |
|
345 } |
516 } |
346 |
517 |
347 /* |
518 /* |
348 |
519 |
349 - 1-104 lap, |
520 - 1-104 lap, |