Files
shitty-tetris/src/piece.rs
T
Ultradesu 1890568ada local
2026-04-09 20:45:25 +01:00

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
}
}