Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 98 additions & 63 deletions snake.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,79 @@
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

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):
Expand All @@ -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]
Expand All @@ -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
Expand All @@ -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

Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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)