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