initial commit

This commit is contained in:
Noah Swerhun 2023-06-29 18:25:32 -05:00
parent 8288f3f628
commit 6198043d76
4 changed files with 213 additions and 1 deletions

10
Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "snake-rs"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
crossterm = "0.26.1"
rand = "0.8.5"

View file

@ -1,3 +1,10 @@
# snake-rs # snake-rs
Classic snake game with terminal graphics written in rust. Classic snake game with terminal graphics written in rust.
This is my first project in rust so the code is probably great.
Play the game:
```
cargo run
```

195
src/main.rs Normal file
View file

@ -0,0 +1,195 @@
use crossterm::{*, cursor::*, event::*, style::*, terminal::*};
use std::io::{stdout, Stdout, Write};
use std::time::Duration;
use rand::{Rng, thread_rng};
#[derive(Copy, Clone)]
struct Point {
x: u16,
y: u16
}
#[derive(Copy, Clone, std::fmt::Debug, PartialEq, Eq)]
enum Direction {
Up,
Down,
Left,
Right
}
fn init_screen() -> Result<Stdout> {
let mut stdout: Stdout = stdout();
enable_raw_mode()?;
stdout.queue(Clear(ClearType::All))?;
stdout.queue(Hide)?;
stdout.queue(MoveTo(0, 0))?;
stdout.flush()?;
Ok(stdout)
}
fn cleanup(stdout: &mut Stdout) -> Result<()> {
stdout.queue(Clear(ClearType::All))?;
stdout.queue(Show)?;
stdout.queue(MoveTo(0, 0))?;
disable_raw_mode()?;
stdout.flush()?;
Ok(())
}
fn move_snake(snake: &mut Vec<Point>, direction: Direction, cols: u16, rows: u16) {
for i in (0..(*snake).len()).rev() {
if i == 0 {
match direction {
Direction::Up => {
if snake[0].y == 0 {
snake[0].y = rows-1;
} else {
snake[0].y -= 1;
}
},
Direction::Down => {
if snake[0].y == rows-1 {
snake[0].y = 0;
} else {
snake[0].y += 1;
}
},
Direction::Left => {
if snake[0].x == 0 {
snake[0].x = cols-1;
} else {
snake[0].x -= 1;
}
},
Direction::Right => {
if snake[0].x == cols-1 {
snake[0].x = 0;
} else {
snake[0].x += 1;
}
}
}
} else {
snake[i] = snake[i-1];
}
}
}
fn print_snake(snake: &Vec<Point>, screen: &mut Stdout) -> Result<()> {
for seg in (*snake).iter() {
(*screen).queue(MoveTo(seg.x, seg.y))?;
(*screen).queue(Print("#".to_string()))?;
}
Ok(())
}
fn main() -> Result<()> {
let mut screen = init_screen()?;
let (cols, rows) = size()?;
let mut snake: Vec<Point> = Vec::new();
let mut apples: Vec<Point> = Vec::new();
let inital_length = 5;
let num_apples = 10;
let mut head_x = cols/2 - inital_length/2;
let mut head_y = rows/2;
let mut direction: Direction = Direction::Left;
let mut score = 0;
let mut lost = false;
screen.queue(MoveTo(head_x, head_y))?;
// create snake
for i in 0..inital_length {
snake.push(Point { x: head_x + i, y: head_y });
screen.queue(Print("#".to_string()))?;
}
// create apples
for i in 0..num_apples {
apples.push(Point { x: thread_rng().gen_range(0..cols), y: thread_rng().gen_range(0..rows-1)});
screen.queue(MoveTo(apples[i].x, apples[i].y))?;
screen.queue(Print("*".to_string()))?;
}
'main: loop {
screen.queue(MoveTo(head_x, head_y))?;
match direction {
Direction::Up => {move_snake(&mut snake, direction, cols, rows);},
Direction::Down => {move_snake(&mut snake, direction, cols, rows);},
Direction::Left => {move_snake(&mut snake, direction, cols, rows);},
Direction::Right => {move_snake(&mut snake, direction, cols, rows);}
}
head_x = snake[0].x;
head_y = snake[0].y;
for i in 1..snake.len() {
if head_x == snake[i].x && head_y == snake[i].y {
lost = true;
break 'main;
}
}
for i in 0..num_apples {
if head_x == apples[i].x && head_y == apples[i].y {
score += 1;
apples[i] = Point { x: thread_rng().gen_range(0..cols), y: thread_rng().gen_range(0..rows)};
snake.push(Point { x: 0, y: 0 });
}
screen.queue(MoveTo(apples[i].x, apples[i].y))?;
screen.queue(Print("*".to_string()))?;
}
print_snake(&snake, &mut screen)?;
screen.queue(MoveTo(0, rows))?;
screen.queue(Print(format!("SCORE: {} | <q> to quit | arrow keys to move", score)))?;
screen.flush()?;
screen.queue(Clear(ClearType::All))?;
if poll(Duration::from_millis(150))? {
match read()? {
Event::Key(e) => match e.code {
KeyCode::Char('q') => break 'main,
KeyCode::Up => direction =
if direction != Direction::Down { Direction::Up }
else { direction },
KeyCode::Down => direction =
if direction != Direction::Up { Direction::Down }
else { direction },
KeyCode::Left => direction =
if direction != Direction::Right { Direction::Left }
else { direction },
KeyCode::Right => direction =
if direction != Direction::Left { Direction::Right }
else { direction },
_ => ()
},
_ => ()
}
}
}
cleanup(&mut screen)?;
if lost {
println!("You loose. Final Score: {}", score);
} else {
println!("Goodbye! Final Score: {}", score);
}
Ok(())
}

0
src/snake.rs Normal file
View file