use rand::Rng; /// Тип фигуры тетриса #[derive(Clone, Copy, PartialEq, Debug)] pub enum PieceType { I, O, T, S, Z, J, L, } impl PieceType { /// Возвращает все возможные типы фигур pub fn all() -> [PieceType; 7] { [PieceType::I, PieceType::O, PieceType::T, PieceType::S, PieceType::Z, PieceType::J, PieceType::L] } /// Генерирует случайную фигуру pub fn random() -> PieceType { let mut rng = rand::thread_rng(); let idx: u8 = rng.gen_range(0..7); match idx { 0 => PieceType::I, 1 => PieceType::O, 2 => PieceType::T, 3 => PieceType::S, 4 => PieceType::Z, 5 => PieceType::J, 6 => PieceType::L, _ => PieceType::I, } } /// Возвращает цвет (ANSI код) для фигуры pub fn color(&self) -> u8 { match self { PieceType::I => 36, // Cyan PieceType::O => 33, // Yellow PieceType::T => 35, // Magenta PieceType::S => 32, // Green PieceType::Z => 31, // Red PieceType::J => 34, // Blue PieceType::L => 37, // White } } } /// Блок фигуры - относительная координата #[derive(Clone, Copy, Debug)] pub struct Block { pub x: i32, pub y: i32, } /// Фигура тетриса с позицией #[derive(Clone, Debug)] pub struct Piece { pub piece_type: PieceType, pub blocks: [Block; 4], pub center: (i32, i32), } impl Piece { /// Создает новую фигуру заданного типа в центре сверху pub fn new(piece_type: PieceType) -> Piece { let blocks = match piece_type { PieceType::I => [ Block { x: -1, y: 0 }, Block { x: 0, y: 0 }, Block { x: 1, y: 0 }, Block { x: 2, y: 0 }, ], PieceType::O => [ Block { x: 0, y: 0 }, Block { x: 1, y: 0 }, Block { x: 0, y: 1 }, Block { x: 1, y: 1 }, ], PieceType::T => [ Block { x: -1, y: 0 }, Block { x: 0, y: 0 }, Block { x: 1, y: 0 }, Block { x: 0, y: 1 }, ], PieceType::S => [ Block { x: 0, y: 0 }, Block { x: 1, y: 0 }, Block { x: -1, y: 1 }, Block { x: 0, y: 1 }, ], PieceType::Z => [ Block { x: -1, y: 0 }, Block { x: 0, y: 0 }, Block { x: 0, y: 1 }, Block { x: 1, y: 1 }, ], PieceType::J => [ Block { x: -1, y: 0 }, Block { x: 0, y: 0 }, Block { x: 1, y: 0 }, Block { x: -1, y: 1 }, ], PieceType::L => [ Block { x: -1, y: 0 }, Block { x: 0, y: 0 }, Block { x: 1, y: 0 }, Block { x: 1, y: 1 }, ], }; Piece { piece_type, blocks, center: (5, 0), } } /// Возвращает позиции всех блоков в абсолютных координатах pub fn positions(&self) -> Vec<(i32, i32)> { self.blocks .iter() .map(|b| (self.center.0 + b.x, self.center.1 + b.y)) .collect() } /// Поворачивает фигуру на 90 градусов по часовой стрелке pub fn rotate(&mut self) { for block in &mut self.blocks { let (x, y) = (block.x, block.y); block.x = -y; block.y = x; } } /// Возвращает новую фигуру с тем же типом, но повернутую pub fn rotated(&self) -> Piece { let mut new = self.clone(); new.rotate(); new } /// Двигает фигуру влево pub fn move_left(&mut self) { self.center.0 -= 1; } /// Двигает фигуру вправо pub fn move_right(&mut self) { self.center.0 += 1; } /// Двигает фигуру вниз pub fn move_down(&mut self) { self.center.1 += 1; } /// Проверяет, находится ли фигура в допустимой области pub fn is_within_bounds(&self, width: i32, height: i32) -> bool { for block in &self.blocks { let (x, y) = (self.center.0 + block.x, self.center.1 + block.y); if x < 0 || x >= width || y >= height { return false; } } true } }