usize terminal size for width and height
This commit is contained in:
84
src/main.rs
84
src/main.rs
@@ -1,13 +1,14 @@
|
||||
use crossterm::{
|
||||
cursor::{Hide, Show},
|
||||
event::{poll, read, Event, KeyCode},
|
||||
terminal::{disable_raw_mode, enable_raw_mode},
|
||||
terminal::{disable_raw_mode, enable_raw_mode, size},
|
||||
ExecutableCommand,
|
||||
};
|
||||
use rand::prelude::*;
|
||||
use std::collections::VecDeque;
|
||||
use std::io::stdout;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
const WIDTH: usize = 20;
|
||||
const HEIGHT: usize = 20;
|
||||
const FRAME_TIME: Duration = Duration::from_millis(100);
|
||||
const SNAKE_COLOR: Color = Color { r: 0, g: 255, b: 0 };
|
||||
const APPLE_COLOR: Color = Color { r: 255, g: 0, b: 0 };
|
||||
@@ -29,20 +30,29 @@ enum CrashLocation {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut snake: VecDeque<(usize, usize)> = vec![(0, 0), (1, 0), (2, 0)].into();
|
||||
let mut snake: VecDeque<(u16, u16)> = vec![(0, 0), (1, 0), (2, 0)].into();
|
||||
let mut direction = Direction::Right;
|
||||
let mut length = snake.len();
|
||||
|
||||
stdout().execute(Hide).unwrap();
|
||||
|
||||
let (width, height) = size().unwrap_or((20, 20));
|
||||
println!("width {width}, height: {height}");
|
||||
let (width, height) = ((width - 2) / 2, height - 5);
|
||||
let mut rng = thread_rng();
|
||||
let mut apple = (rng.gen_range(0..WIDTH), rng.gen_range(0..WIDTH));
|
||||
let mut apple = (
|
||||
rng.gen_range(0..width),
|
||||
rng.gen_range(0..height),
|
||||
);
|
||||
|
||||
loop {
|
||||
let now = Instant::now();
|
||||
|
||||
render(&snake, apple, length);
|
||||
render(&snake, apple, length, (width, height));
|
||||
enable_raw_mode().unwrap();
|
||||
change_dir(&mut direction);
|
||||
disable_raw_mode().unwrap();
|
||||
if let Some(crash) = move_snake(&mut snake, &direction, length) {
|
||||
if let Some(crash) = move_snake(&mut snake, &direction, length, (width, height)) {
|
||||
match crash {
|
||||
CrashLocation::North => println!("You crashed in the North wall!"),
|
||||
CrashLocation::South => println!("You crashed in the South wall!"),
|
||||
@@ -52,24 +62,36 @@ fn main() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
eat(&snake, &mut apple, &mut length, &mut rng);
|
||||
eat(&snake, &mut apple, &mut length, &mut rng, (width, height));
|
||||
|
||||
while now.elapsed() < FRAME_TIME {}
|
||||
}
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
fn eat(
|
||||
snake: &VecDeque<(usize, usize)>,
|
||||
apple: &mut (usize, usize),
|
||||
snake: &VecDeque<(u16, u16)>,
|
||||
apple: &mut (u16, u16),
|
||||
length: &mut usize,
|
||||
rng: &mut ThreadRng,
|
||||
(width, height): (u16, u16),
|
||||
) {
|
||||
if snake.contains(&apple) {
|
||||
*apple = (rng.gen_range(0..WIDTH), rng.gen_range(0..WIDTH));
|
||||
if snake.contains(apple) {
|
||||
*apple = (
|
||||
rng.gen_range(0..width),
|
||||
rng.gen_range(0..height),
|
||||
);
|
||||
*length += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn exit() {
|
||||
disable_raw_mode().unwrap();
|
||||
stdout().execute(Show).unwrap();
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
fn change_dir(direction: &mut Direction) {
|
||||
if let Some(k) = key_input(FRAME_TIME) {
|
||||
match k {
|
||||
@@ -93,10 +115,7 @@ fn change_dir(direction: &mut Direction) {
|
||||
*direction = Direction::Down;
|
||||
}
|
||||
}
|
||||
'q' => {
|
||||
disable_raw_mode().unwrap();
|
||||
std::process::exit(0);
|
||||
}
|
||||
'q' => exit(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@@ -114,9 +133,10 @@ fn key_input(timeout: Duration) -> Option<char> {
|
||||
}
|
||||
|
||||
fn move_snake(
|
||||
snake: &mut VecDeque<(usize, usize)>,
|
||||
snake: &mut VecDeque<(u16, u16)>,
|
||||
direction: &Direction,
|
||||
length: usize,
|
||||
(width, height): (u16, u16),
|
||||
) -> Option<CrashLocation> {
|
||||
if length == snake.len() {
|
||||
snake.pop_front();
|
||||
@@ -125,7 +145,7 @@ fn move_snake(
|
||||
|
||||
match direction {
|
||||
Direction::Right => {
|
||||
if a.0 + 1 < WIDTH {
|
||||
if a.0 + 1 < width {
|
||||
a.0 += 1
|
||||
} else {
|
||||
return Some(CrashLocation::East);
|
||||
@@ -139,7 +159,7 @@ fn move_snake(
|
||||
}
|
||||
}
|
||||
Direction::Up => {
|
||||
if a.1 + 1 < WIDTH {
|
||||
if a.1 + 1 < height {
|
||||
a.1 += 1
|
||||
} else {
|
||||
return Some(CrashLocation::North);
|
||||
@@ -162,16 +182,21 @@ fn move_snake(
|
||||
None
|
||||
}
|
||||
|
||||
fn render(snake: &VecDeque<(usize, usize)>, apple: (usize, usize), length: usize) {
|
||||
fn render(
|
||||
snake: &VecDeque<(u16, u16)>,
|
||||
apple: (u16, u16),
|
||||
length: usize,
|
||||
(width, height): (u16, u16),
|
||||
) {
|
||||
let mut s = String::new();
|
||||
s.push_str("\u{001b}c");
|
||||
s.push_str(&format!("length: {length}\n"));
|
||||
s.push('┏');
|
||||
s.push_str(&"━".repeat(WIDTH * 2));
|
||||
s.push_str(&"━".repeat(width as usize * 2));
|
||||
s.push_str("┓\n");
|
||||
for y in (0..HEIGHT).rev() {
|
||||
for y in (0..height).rev() {
|
||||
s.push('┃');
|
||||
for x in 0..WIDTH {
|
||||
for x in 0..width {
|
||||
if snake.contains(&(x, y)) {
|
||||
s.push_str(&" ".bg(SNAKE_COLOR));
|
||||
} else if (x, y) == apple {
|
||||
@@ -183,7 +208,7 @@ fn render(snake: &VecDeque<(usize, usize)>, apple: (usize, usize), length: usize
|
||||
s.push_str("┃\n");
|
||||
}
|
||||
s.push('┗');
|
||||
s.push_str(&"━".repeat(WIDTH * 2));
|
||||
s.push_str(&"━".repeat(width as usize * 2));
|
||||
s.push('┛');
|
||||
println!("{s}");
|
||||
}
|
||||
@@ -212,22 +237,23 @@ mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn move_test() {
|
||||
let mut snake: VecDeque<(usize, usize)> = vec![(16, 16), (17, 16), (18, 16)].into();
|
||||
let mut snake: VecDeque<(u16, u16)> = vec![(16, 16), (17, 16), (18, 16)].into();
|
||||
let mut direction = Direction::Up;
|
||||
let length = snake.len();
|
||||
move_snake(&mut snake, &direction, length);
|
||||
let size = size().unwrap_or((20, 20));
|
||||
move_snake(&mut snake, &direction, length, size);
|
||||
assert_eq!(snake, vec![(17, 16), (18, 16), (18, 17)]);
|
||||
|
||||
direction = Direction::Right;
|
||||
move_snake(&mut snake, &direction, length);
|
||||
move_snake(&mut snake, &direction, length, size);
|
||||
assert_eq!(snake, vec![(18, 16), (18, 17), (19, 17)]);
|
||||
|
||||
direction = Direction::Down;
|
||||
move_snake(&mut snake, &direction, length);
|
||||
move_snake(&mut snake, &direction, length, size);
|
||||
assert_eq!(snake, vec![(18, 17), (19, 17), (19, 16)]);
|
||||
|
||||
direction = Direction::Left;
|
||||
move_snake(&mut snake, &direction, length);
|
||||
move_snake(&mut snake, &direction, length, size);
|
||||
assert_eq!(snake, vec![(19, 17), (19, 16), (18, 16)]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user