171 lines
4.8 KiB
Rust
171 lines
4.8 KiB
Rust
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
|
|
}
|
|
}
|