diff --git a/snake.py b/snake.py index edb2c79..81e3224 100644 --- a/snake.py +++ b/snake.py @@ -3,26 +3,27 @@ import sys from random import randint + class Field: def __init__(self, size): self.size = size self.icons = { - 0: ' . ', - 1: ' * ', - 2: ' # ', - 3: ' & ', + 0: " . ", + 1: " * ", + 2: " > ", # snake head (default right) + 3: " & ", # food } self.snake_coords = [] self._generate_field() self.add_entity() def add_entity(self): - - while(True): - i = randint(0, self.size-1) - j = randint(0, self.size-1) + + while True: + i = randint(0, self.size - 1) + j = randint(0, self.size - 1) entity = [i, j] - + if entity not in self.snake_coords: self.field[i][j] = 3 break @@ -30,29 +31,51 @@ def add_entity(self): def _generate_field(self): self.field = [[0 for j in range(self.size)] for i in range(self.size)] - def _clear_field(self): - self.field = [[j if j!= 1 and j!= 2 else 0 for j in i] for i in self.field] - + def _clear_field(self): + self.field = [[j if j != 1 and j != 2 else 0 for j in i] for i in self.field] def render(self, screen): size = self.size self._clear_field() - # Render snake on the field - for i, j in self.snake_coords: + for i, j in self.snake_coords[:-1]: self.field[i][j] = 1 # Mark head + # add proper direction + if self.snake.direction == curses.KEY_RIGHT: + self.icons[2] = " > " + elif self.snake.direction == curses.KEY_LEFT: + self.icons[2] = " < " + elif self.snake.direction == curses.KEY_UP: + self.icons[2] = " ^ " + elif self.snake.direction == curses.KEY_DOWN: + self.icons[2] = " v " + head = self.snake_coords[-1] self.field[head[0]][head[1]] = 2 for i in range(size): - row = '' + row = "" for j in range(size): - row += self.icons[ self.field[i][j] ] - - screen.addstr(i, 0, row) + icon = self.icons[self.field[i][j]] + screen.addstr(i, j * 3, icon, curses.color_pair(self.field[i][j])) + # Color snake body + if self.field[i][j] == 1: + screen.addstr( + i, j * 3, icon, curses.color_pair(1) + ) # Green Snake body + # Color snake head + elif self.field[i][j] == 2: + screen.addstr( + i, j * 3, icon, curses.color_pair(2) + ) # Red Snake head + # Yellow Color food + elif self.field[i][j] == 3: + screen.addstr(i, j * 3, icon, curses.color_pair(3)) + else: + screen.addstr(i, j * 3, icon) # Default (empty space) def get_entity_pos(self): for i in range(self.size): @@ -62,7 +85,6 @@ def get_entity_pos(self): return [-1, -1] - def is_snake_eat_entity(self): entity = self.get_entity_pos() head = self.snake_coords[-1] @@ -76,7 +98,7 @@ def __init__(self, name): # Init basic coords self.coords = [[0, 0], [0, 1], [0, 2], [0, 3]] - + def set_direction(self, ch): # Check if wrong direction @@ -87,7 +109,7 @@ def set_direction(self, ch): if ch == curses.KEY_UP and self.direction == curses.KEY_DOWN: return if ch == curses.KEY_DOWN and self.direction == curses.KEY_UP: - return + return self.direction = ch @@ -99,13 +121,13 @@ def level_up(self): tail = a[:] if a[0] < b[0]: - tail[0]-=1 + tail[0] -= 1 elif a[1] < b[1]: - tail[1]-=1 + tail[1] -= 1 elif a[0] > b[0]: - tail[0]+=1 + tail[0] += 1 elif a[1] > b[1]: - tail[1]+=1 + tail[1] += 1 tail = self._check_limit(tail) self.coords.insert(0, tail) @@ -117,13 +139,13 @@ def is_alive(self): def _check_limit(self, point): # Check field limit - if point[0] > self.field.size-1: + if point[0] > self.field.size - 1: point[0] = 0 elif point[0] < 0: - point[0] = self.field.size-1 + point[0] = self.field.size - 1 elif point[1] < 0: - point[1] = self.field.size-1 - elif point[1] > self.field.size-1: + point[1] = self.field.size - 1 + elif point[1] > self.field.size - 1: point[1] = 0 return point @@ -134,62 +156,75 @@ def move(self): # Calc new head coords if self.direction == curses.KEY_UP: - head[0]-=1 + head[0] -= 1 elif self.direction == curses.KEY_DOWN: - head[0]+=1 + head[0] += 1 elif self.direction == curses.KEY_RIGHT: - head[1]+=1 + head[1] += 1 elif self.direction == curses.KEY_LEFT: - head[1]-=1 + head[1] -= 1 # Check field limit head = self._check_limit(head) - del(self.coords[0]) + del self.coords[0] self.coords.append(head) self.field.snake_coords = self.coords + self.field.snake = self # add snake to field so render can access direction if not self.is_alive(): sys.exit() - # check if snake eat an entity if self.field.is_snake_eat_entity(): curses.beep() self.level_up() self.field.add_entity() - - - def set_field(self, field): self.field = field def main(screen): - # Configure screen - screen.timeout(0) - - # Init snake & field - field = Field(10) - snake = Snake("Joe") - snake.set_field(field) - - while(True): - # Get last pressed key - ch = screen.getch() - if ch != -1: - # If some arrows did pressed - change direction - snake.set_direction(ch) - - # Move snake - snake.move() - - # Render field - field.render(screen) - screen.refresh() - - time.sleep(.4) - -if __name__=='__main__': + try: + # Initialize color pairs + curses.start_color() + curses.init_pair( + 1, curses.COLOR_GREEN, curses.COLOR_BLACK + ) # Snake body - green + curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) # Snake head - red + curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # Food - yellow + + # Configure screen + screen.timeout(0) + + # Init snake & field + field = Field(30) + snake = Snake("Joe") + snake.set_field(field) + field.snake = snake + + while True: + # Get last pressed key + ch = screen.getch() + if ch != -1: + # If some arrows did pressed - change direction + snake.set_direction(ch) + + # Move snake + snake.move() + + # Render field + field.render(screen) + screen.refresh() + + time.sleep(0.15) + + except Exception as e: + print(f"An error occurred: {e}") + finally: + curses.endwin() + + +if __name__ == "__main__": curses.wrapper(main)