diff options
-rw-r--r-- | src/main.rs | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/src/main.rs b/src/main.rs index 2cf1b23..468da4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ extern crate termios; -use rand::Rng; +use rand::seq::SliceRandom; use nonblock::NonBlockingReader; const FIELD_COLS: usize = 10; @@ -29,9 +29,9 @@ enum FigureKind { I, L2, L, - T, B, S, + T, Z, } @@ -69,25 +69,17 @@ struct Figure { } impl Figure { - fn kind_random() -> Self { - return match rand::thread_rng().gen_range(0..7) { - 0 => Self::kind_i(), - 1 => Self::kind_l2(), - 2 => Self::kind_l(), - 3 => Self::kind_b(), - 4 => Self::kind_s(), - 5 => Self::kind_t(), - 6 => Self::kind_z(), - _ => unreachable!(), - }; + fn from_kind(kind: FigureKind) -> Self { + match kind { + FigureKind::I => Self{ cells: CELLS_I, kind }, + FigureKind::L2 => Self{ cells: CELLS_L2, kind }, + FigureKind::L => Self{ cells: CELLS_L, kind }, + FigureKind::B => Self{ cells: CELLS_B, kind }, + FigureKind::S => Self{ cells: CELLS_S, kind }, + FigureKind::T => Self{ cells: CELLS_T, kind }, + FigureKind::Z => Self{ cells: CELLS_Z, kind }, + } } - const fn kind_i() -> Self { Self{ cells: CELLS_I, kind: FigureKind::I } } - const fn kind_l2() -> Self { Self{ cells: CELLS_L2, kind: FigureKind::L2 } } - const fn kind_l() -> Self { Self{ cells: CELLS_L, kind: FigureKind::L } } - const fn kind_b() -> Self { Self{ cells: CELLS_B, kind: FigureKind::B } } - const fn kind_s() -> Self { Self{ cells: CELLS_S, kind: FigureKind::S } } - const fn kind_t() -> Self { Self{ cells: CELLS_T, kind: FigureKind::T } } - const fn kind_z() -> Self { Self{ cells: CELLS_Z, kind: FigureKind::Z } } fn rotate_cw_4x4(&mut self) { let mut tmp: [u8; 4 * 4] = Default::default(); for y in 0..4 { @@ -190,6 +182,44 @@ impl Field { } } +struct Bag { + index: u8, + pieces: [u8; 7], +} + +impl Bag { + fn next(&mut self) -> FigureKind { + if self.index >= 7 { + self.index = 0; + self.pieces.shuffle(&mut rand::thread_rng()); + } + let i = self.index; + self.index += 1; + match self.pieces[i as usize] { + 0 => FigureKind::I, + 1 => FigureKind::L2, + 2 => FigureKind::L, + 4 => FigureKind::B, + 5 => FigureKind::S, + 3 => FigureKind::T, + 6 => FigureKind::Z, + _ => unreachable!(), + } + } +} + +impl Default for Bag { + #[inline] + fn default() -> Self { + let mut pieces: [u8; 7] = [0, 1, 2, 3, 4, 5, 6]; + pieces.shuffle(&mut rand::thread_rng()); + Self{ + index: 0, + pieces + } + } +} + struct Game { field: Field, figure: Figure, @@ -197,18 +227,22 @@ struct Game { y: isize, fall_timeout: Timeout, place_timeout: Option<Timeout>, + bag: Bag, } impl Default for Game { #[inline] fn default() -> Self { + let mut bag = Bag::default(); + let kind = bag.next(); Self{ field: Field::default(), - figure: Figure::kind_random(), + figure: Figure::from_kind(kind), x: 3, y: 17, fall_timeout: Timeout::from_duration(std::time::Duration::from_millis(500)), place_timeout: None, + bag, } } } @@ -216,7 +250,7 @@ impl Default for Game { impl Game { fn place_figure(&mut self) { self.field.render(&self.figure, self.x, self.y); - self.figure = Figure::kind_random(); + self.figure = Figure::from_kind(self.bag.next()); (self.x, self.y) = (3, 17); self.stop_place_timeout(); for line in 0..FIELD_ROWS - 1 { |