Snake doesn't clear the board every run

also changed all i32 to u32
This commit is contained in:
Uttarayan Mondal
2021-01-25 02:48:54 +05:30
parent eeaa8a2675
commit 8bc7770bf3
7 changed files with 90 additions and 53 deletions
Generated
+1 -1
View File
@@ -94,7 +94,7 @@ dependencies = [
[[package]]
name = "snake"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"ncurses",
"rand",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "snake"
version = "0.2.0"
version = "0.2.1"
authors = ["Uttarayan Mondal <uttarayan21@gmail.com>"]
edition = "2018"
+3 -2
View File
@@ -79,9 +79,10 @@ A few notes about the game and how I should improve the game
<summary>Rust specific stuff I learned</summary>
> [char](https://doc.rust-lang.org/stable/std/primitive.char.html) and [std::char](https://doc.rust-lang.org/stable/std/char/index.html) are different
> [char](https://doc.rust-lang.org/stable/std/primitive.char.html) and [std::char](https://doc.rust-lang.org/stable/std/char/index.html) are not the same.
> [char](https://doc.rust-lang.org/stable/std/primitive.char.html) is the primitive type [std::char](https://doc.rust-lang.org/stable/std/char/index.html) is the char module.
> [char](https://doc.rust-lang.org/stable/std/primitive.char.html) is the primitive type [std::char](https://doc.rust-lang.org/stable/std/char/index.html) is the char module. All the functions are not completely same for both (as of rust v1.49.0)
> As of Sat, 23 Jan 2021 21:49:13 +0000 the char::from_u32 (used in this program) is not valid in primitive [char](https://doc.rust-lang.org/stable/std/primitive.char.html) but is valid in [std::char](https://doc.rust-lang.org/stable/std/char/index.html)
> [ncursesw](httsp://docs.rs/ncursesw) is not needed to print unicode characters. I have no clue where I got that idea from.
+4
View File
@@ -0,0 +1,4 @@
- v0.2.1
- > Change all the i32 variables to u32.
- > Changed the snake logic a bit so that the snake doesn't clear the whole board for every draw
+43 -20
View File
@@ -61,8 +61,8 @@ pub enum CellType {
Empty,
}
pub struct Cell {
line: i32,
col: i32,
line: u32,
col: u32,
ctype: CellType,
}
impl PartialEq for Cell {
@@ -77,28 +77,37 @@ impl PartialEq for Cell {
impl Sub for Cell {
type Output = (i32, i32);
fn sub(self, rhs: Cell) -> (i32, i32) {
return (self.line - rhs.line, self.col - rhs.col);
return (
self.line as i32 - rhs.line as i32,
self.col as i32 - rhs.col as i32,
);
}
}
impl Cell {
pub fn new(l: i32, c: i32, t: CellType) -> Cell {
pub fn new(l: u32, c: u32, t: CellType) -> Cell {
Cell {
line: l,
col: c,
ctype: t,
}
}
pub fn random(lines: i32, cols: i32) -> Cell {
pub fn random(lines: u32, cols: u32) -> Cell {
let mut rng = rand::thread_rng();
Cell::new(
rng.gen_range(1..lines - 1),
rng.gen_range(1..cols - 1),
rng.gen_range(1..lines - 1) as u32,
rng.gen_range(1..cols - 1) as u32,
CellType::Food,
)
}
pub fn posyx(&self) -> (i32, i32) {
pub fn posyx(&self) -> (u32, u32) {
return (self.line, self.col);
}
pub fn posy(&self) -> u32 {
return self.line;
}
pub fn posx(&self) -> u32 {
return self.col;
}
pub fn chtype(&mut self, ctype: CellType) {
self.ctype = ctype;
}
@@ -138,15 +147,15 @@ enum GameState {
}
pub struct Board {
maxlines: i32,
maxcols: i32,
maxlines: u32,
maxcols: u32,
gamestate: GameState,
food: Cell,
}
// impl Board<'_> {
impl Board {
pub fn new(maxlines: i32, maxcols: i32) -> Board {
pub fn new(maxlines: u32, maxcols: u32) -> Board {
Board {
maxlines,
maxcols,
@@ -155,7 +164,7 @@ impl Board {
}
}
pub fn check_collision(&mut self, snake: &Snake) -> bool {
let (snake_line, snake_col): (i32, i32) = snake.posyx();
let (snake_line, snake_col): (u32, u32) = snake.posyx();
if (snake_line >= self.maxlines - 1)
|| (snake_col >= self.maxcols - 1)
|| (snake_line <= 0)
@@ -182,9 +191,12 @@ impl Board {
return false;
}
}
pub fn food_posyx(&self) -> (i32, i32) {
pub fn food_posyx(&self) -> (u32, u32) {
return self.food.posyx();
}
// pub fn food_posy(&self) -> u32 {
// return self.food.line;
// }
pub fn eat_food(&mut self, snake: &mut Snake) {
snake.grow();
// self.food.chtype(CellType::Empty);
@@ -217,7 +229,8 @@ pub struct Snake {
body: LinkedList<Cell>,
direction: Direction,
grow: bool,
speed: i32,
speed: u32,
last_tail: Option<Cell>,
}
impl Snake {
pub fn new(head: Cell) -> Snake {
@@ -230,14 +243,14 @@ impl Snake {
direction: Direction::Right,
grow: false,
speed: 15,
last_tail: Some(head),
}
}
pub fn posyx(&self) -> (i32, i32) {
pub fn posyx(&self) -> (u32, u32) {
return (self.head.line, self.head.col);
}
pub fn smove(&mut self, _direction: Direction) {
// smove because move is already a keyword
let mut tail: Cell;
let direction: Direction;
if self.direction == _direction.opposite() {
direction = self.direction
@@ -245,18 +258,22 @@ impl Snake {
direction = _direction
}
if self.grow == false {
tail = self.body.pop_back().unwrap();
tail.chtype(CellType::Empty);
self.last_tail = Some(self.body.pop_back().unwrap());
// self.grow = false;
}
let (dl, dc) = match direction {
let (dl, dc): (i32, i32) = match direction {
Direction::Up => (-1, 0),
Direction::Down => (1, 0),
Direction::Left => (0, -1),
Direction::Right => (0, 1),
};
self.direction = direction;
self.head = Cell::new(self.head.line + dl, self.head.col + dc, CellType::Snake);
self.head = Cell::new(
((self.head.line as i32) + dl) as u32,
((self.head.col as i32) + dc) as u32,
CellType::Snake,
);
self.body.push_front(self.head);
self.grow = false;
}
@@ -274,4 +291,10 @@ impl Snake {
pub fn iter(&self) -> impl Iterator<Item = &Cell> {
return self.body.iter();
}
pub fn remove(&self) -> Option<Cell> {
return self.last_tail;
}
pub fn set_speed(&mut self, speed: u32) {
self.speed = speed;
}
}
+26 -20
View File
@@ -4,15 +4,15 @@ use ncurses::{
box_, delwin, keypad, mvwaddstr, newwin, stdscr, waddstr, wborder, wclrtobot, wmove, wrefresh,
WINDOW,
};
pub fn game_window(mlines: i32, mcols: i32, vmargin: i32, hmargin: i32) -> WINDOW {
pub fn game_window(mlines: u32, mcols: u32, vmargin: u32, hmargin: u32) -> WINDOW {
let game_win: WINDOW;
let (lines, cols): (i32, i32);
let (starty, startx): (i32, i32);
let (lines, cols): (u32, u32);
let (starty, startx): (u32, u32);
lines = mlines - vmargin * 2;
cols = mcols - hmargin * 2;
starty = vmargin;
startx = hmargin;
game_win = newwin(lines, cols, starty, startx);
game_win = newwin(lines as i32, cols as i32, starty as i32, startx as i32);
box_(game_win, 0, 0);
keypad(game_win, true);
wrefresh(game_win);
@@ -32,7 +32,7 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
let (mut prev, mut current, _next): (&Cell, &Cell, &Cell);
let mut snake_iter = snake.iter();
wmove(game_win, 0, 0);
wclrtobot(game_win);
// wclrtobot(game_win);
box_(game_win, 0, 0);
// I want to draw the snake as ascii box charachters
@@ -41,10 +41,16 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
prev = snake_iter.next().unwrap(); // currently this should be head. On initial run this should be the only snake_cell
mvwaddstr(
game_win,
prev.posyx().0,
prev.posyx().1,
prev.posy() as i32,
prev.posx() as i32,
&format!("{}", std::char::from_u32(0x0298).unwrap_or('O')),
);
match snake.remove() {
Some(tail) => {
mvwaddstr(game_win, tail.posy() as i32, tail.posx() as i32, " ");
}
None => (),
}
let _current = snake_iter.next();
current = match _current {
Some(cell) => cell,
@@ -52,7 +58,7 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
};
for next in snake_iter {
// O(n) the whole snake is redrawn every single tick
let (snake_l, snake_c): (i32, i32) = current.posyx();
let (snake_l, snake_c): (u32, u32) = current.posyx();
// mvwaddstr(game_win, snake_l, snake_c, "o");
let snake_char: u32 = match (
prev.is_adjacent(current).unwrap(),
@@ -68,8 +74,8 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
};
mvwaddstr(
game_win,
snake_l,
snake_c,
snake_l as i32,
snake_c as i32,
&format!("{}", std::char::from_u32(snake_char).unwrap_or('o')),
);
prev = current;
@@ -78,8 +84,8 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
mvwaddstr(
game_win,
current.posyx().0,
current.posyx().1,
current.posy() as i32,
current.posx() as i32,
&format!(
"{}",
std::char::from_u32(match current.is_adjacent(prev).unwrap() {
@@ -93,22 +99,22 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
}
pub fn draw_board(board: &Board, game_win: WINDOW) {
let (food_l, food_c): (i32, i32) = board.food_posyx();
let (food_l, food_c): (u32, u32) = board.food_posyx();
mvwaddstr(
game_win,
food_l,
food_c,
food_l as i32,
food_c as i32,
&format!("{}", std::char::from_u32(0x0298).unwrap_or('F')),
);
}
pub fn _log(snake: &Snake, board: &Board) {
let (shl, shc): (i32, i32) = snake.posyx();
let (bfl, bfc): (i32, i32) = board.food_posyx();
pub fn _log(_snake: &Snake, _board: &Board) {
let (shl, shc): (u32, u32) = _snake.posyx();
let (stl, stc): (u32, u32) = _snake.remove().unwrap().posyx();
mvwaddstr(stdscr(), 0, 0, &format!("snake:head: {} {} ", shl, shc));
mvwaddstr(stdscr(), 1, 0, &format!("board:food: {} {} ", bfl, bfc));
mvwaddstr(stdscr(), 1, 0, &format!("snake:tail: {} {} ", stl, stc));
wmove(stdscr(), 2, 0);
for snake_cell in snake.iter() {
for snake_cell in _snake.iter() {
waddstr(
stdscr(),
&format!(
+12 -9
View File
@@ -10,21 +10,21 @@ pub fn start() {
let (mut mlines, mut mcols): (i32, i32) = (0, 0);
let game_win: WINDOW;
let mut ch: i32;
let (vmargin, hmargin): (i32, i32) = (5, 10);
let (vmargin, hmargin): (u32, u32) = (5, 10);
getmaxyx(stdscr(), &mut mlines, &mut mcols);
game_win = frontend::game_window(mlines, mcols, vmargin, hmargin);
game_win = frontend::game_window(mlines as u32, mcols as u32, vmargin, hmargin);
let mut snake = Snake::new(Cell::new(
mlines / 2 - vmargin,
mcols / 2 - hmargin,
mlines as u32 / 2 - vmargin,
mcols as u32 / 2 - hmargin,
backend::CellType::Snake,
)); //Initialise snake in the middle of the screen
let mut board = Board::new(mlines - vmargin * 2, mcols - hmargin * 2);
let mut board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2);
nodelay(game_win, true);
loop {
frontend::draw_snake(&snake, game_win); // always draw snake before board because the snake will clear the game win
frontend::draw_board(&board, game_win);
// frontend::_log(&snake, &board);
frontend::_log(&snake, &board);
if board.check_collision(&snake) {
// Add stuff here to show the score and
// how You lose screen
@@ -46,9 +46,12 @@ pub fn start() {
//112 is keycode for 'p'
0 => (), //resume
1 => {
snake =
Snake::new(Cell::new(mlines / 2, mcols / 2, backend::CellType::Snake)); //Initialise snake in the middle of the screen
board = Board::new(mlines - vmargin * 2, mcols - hmargin * 2);
snake = Snake::new(Cell::new(
mlines as u32 / 2,
mcols as u32 / 2,
backend::CellType::Snake,
)); //Initialise snake in the middle of the screen
board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2);
} //restart
2 => break, //exit
_ => (), //other charachters just in case