This commit is contained in:
2024-05-24 20:31:45 +02:00
commit ea64a7c7bb
3 changed files with 171 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
Cargo.lock

7
Cargo.toml Normal file
View File

@@ -0,0 +1,7 @@
[package]
name = "term_tetris"
version = "0.1.0"
edition = "2021"
[dependencies]
rand = "0.8.5"

162
src/main.rs Normal file
View File

@@ -0,0 +1,162 @@
// use rand::prelude::*;
use std::time::Instant;
use std::{io, io::Write};
// https://tetris.wiki/Super_Rotation_System
const RED_BLOCK: &str = "\x1b[48;2;255;0;0m \x1b[0m";
const GREEN_BLOCK: &str = "\x1b[48;2;0;255;0m \x1b[0m";
const BLUE_BLOCK: &str = "\x1b[48;2;0;0;255m \x1b[0m";
const YELLOW_BLOCK: &str = "\x1b[48;2;255;255;0m \x1b[0m";
const ORANGE_BLOCK: &str = "\x1b[48;2;255;166;0m \x1b[0m";
const PURPLE_BLOCK: &str = "\x1b[48;2;128;0;128m \x1b[0m";
const CYAN_BLOCK: &str = "\x1b[48;2;0;255;255m \x1b[0m";
const I: [(i8, i8); 4] = [(-1, 0), (0, 0), (1, 0), (2, 0)];
const J: [(i8, i8); 4] = [(0, 0), (-1, 0), (1, 0), (-1, 1)];
const L: [(i8, i8); 4] = [(0, 0), (-1, 0), (1, 0), (1, 1)];
const T: [(i8, i8); 4] = [(0, 0), (0, 1), (-1, 0), (1, 0)];
fn main() {
let instant = Instant::now();
std::thread::sleep(std::time::Duration::from_millis(3));
let mut tetromino = Tetromino::new(&instant);
let mut blocks = vec![];
loop {
render(&tetromino, &blocks);
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
enum TetrominoKind {
I,
O,
T,
J,
L,
S,
Z,
}
struct Tetromino {
kind: TetrominoKind,
pos: (i8, i8),
b: [(i8, i8); 4],
}
struct Block {
pos: (i8, i8),
kind: TetrominoKind,
}
// impl TetrominoKind {
// fn to_str(&self) -> &str {
// match self {
// Color::Red => RED_BLOCK,
// Color::Blue => BLUE_BLOCK,
// Color::Green => GREEN_BLOCK,
// Color::Yellow => YELLOW_BLOCK,
// Color::Orange => ORANGE_BLOCK,
// Color::Purple => PURPLE_BLOCK,
// Color::Cyan => CYAN_BLOCK,
// }
// }
// }
//
impl Tetromino {
fn new(instant: &Instant) -> Self {
let kind = TetrominoKind::new(instant);
Self {
b: kind.get_blocks(),
kind,
pos: (5, 5),
}
}
}
impl TetrominoKind {
fn new(instant: &Instant) -> Self {
match instant.elapsed().as_millis() % 7 {
0 => Self::I,
1 => Self::O,
2 => Self::T,
3 => Self::J,
4 => Self::L,
5 => Self::S,
6 => Self::Z,
7 => Self::O,
_ => unreachable!(),
}
}
fn get_blocks(&self) -> [(i8, i8); 4] {
match self {
Self::I => I,
Self::O => T,
Self::T => T,
Self::J => J,
Self::L => L,
Self::S => T,
Self::Z => T,
}
}
fn to_block(&self) -> &str {
match self {
Self::I => CYAN_BLOCK,
Self::O => YELLOW_BLOCK,
Self::T => PURPLE_BLOCK,
Self::J => BLUE_BLOCK,
Self::L => ORANGE_BLOCK,
Self::S => GREEN_BLOCK,
Self::Z => RED_BLOCK,
}
}
}
fn render(tetromino: &Tetromino, blocks: &Vec<Block>) {
let mut s = String::with_capacity(2 * 22 * 22);
s.push('┏');
s.push_str("━━━━━━━━━━━━━━━━━━━━");
s.push_str("\n");
for y in (0..20).rev() {
s.push('┃');
for x in 0..10 {
let mut found = false;
for block in blocks {
if block.pos == (x, y) {
s.push_str(block.kind.to_block());
found = true;
break;
}
}
for block in tetromino.b {
if (block.0 + tetromino.pos.0, block.1 + tetromino.pos.1) == (x, y) {
s.push_str(tetromino.kind.to_block());
found = true;
break;
}
}
if !found {
s.push_str(" ");
}
}
s.push_str("\n");
}
s.push('┗');
s.push_str("━━━━━━━━━━━━━━━━━━━━");
s.push('┛');
print!("\x1b[2J\x1b[H{s}");
io::stdout().flush().unwrap();
}
#[test]
fn color() {
println!("red: {RED_BLOCK}");
println!("green: {GREEN_BLOCK}");
println!("blue: {BLUE_BLOCK}");
println!("yellow: {YELLOW_BLOCK}");
println!("orange: {ORANGE_BLOCK}");
println!("purple: {PURPLE_BLOCK}");
println!("cyan: {CYAN_BLOCK}");
}