local
This commit is contained in:
+170
@@ -0,0 +1,170 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user