-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsnake.py
133 lines (114 loc) · 3.96 KB
/
snake.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import curses
from random import randint
class SnakeGame:
def __init__(self, board_width = 20, board_height = 20, gui = False):
self.score = 0
self.done = False
self.board = {'width': board_width, 'height': board_height}
self.gui = gui
self.obstacles = []
def start(self):
self.snake_init()
self.generate_food()
self.generate_obstacles()
if self.gui: self.render_init()
return self.generate_observations()
def generate_obstacles(self):
self.obstacles.append([2,3])
self.obstacles.append([4,3])
self.obstacles.append([14,6])
self.obstacles.append([15,3])
self.obstacles.append([10,15])
self.obstacles.append([11,16])
self.obstacles.append([9,4])
self.obstacles.append([18,7])
self.obstacles.append([7,3])
def snake_init(self):
x = randint(5, self.board["width"] - 5)
y = randint(5, self.board["height"] - 5)
self.snake = []
vertical = randint(0,1) == 0
for i in range(3):
point = [x + i, y] if vertical else [x, y + i]
self.snake.insert(0, point)
def generate_food(self):
food = []
while food == []:
food = [randint(1, self.board["width"]), randint(1, self.board["height"])]
if food in self.snake: food = []
if food in self.obstacles: food = []
self.food = food
def render_init(self):
curses.initscr()
win = curses.newwin(self.board["width"] + 2, self.board["height"] + 2, 0, 0)
curses.curs_set(0)
win.nodelay(1)
win.timeout(200)
self.win = win
self.render()
def render(self):
self.win.clear()
self.win.border(0)
self.win.addstr(0, 2, 'Score : ' + str(self.score) + ' ')
for i in self.obstacles:
self.win.addch(i[0], i[1], '#')
self.win.addch(self.food[0], self.food[1], 'o')
for i, point in enumerate(self.snake):
if i == 0:
self.win.addch(point[0], point[1], 'X')
else:
self.win.addch(point[0], point[1], 'x')
self.win.getch()
def step(self, key):
# 0 - UP
# 1 - RIGHT
# 2 - DOWN
# 3 - LEFT
if self.done == True: self.end_game()
self.create_new_point(key)
if self.food_eaten():
self.score += 1
self.generate_food()
else:
self.remove_last_point()
self.check_collisions()
if self.gui: self.render()
return self.generate_observations()
def create_new_point(self, key):
new_point = [self.snake[0][0], self.snake[0][1]]
if key == 0:
new_point[0] -= 1
elif key == 1:
new_point[1] += 1
elif key == 2:
new_point[0] += 1
elif key == 3:
new_point[1] -= 1
self.snake.insert(0, new_point)
def remove_last_point(self):
self.snake.pop()
def food_eaten(self):
return self.snake[0] == self.food
def check_collisions(self):
if (self.snake[0][0] == 0 or
self.snake[0][0] == self.board["width"] + 1 or
self.snake[0][1] == 0 or
self.snake[0][1] == self.board["height"] + 1 or
self.snake[0] in self.snake[1:-1] or
self.snake[0] in self.obstacles):
self.done = True
def generate_observations(self):
return self.done, self.score, self.snake, self.food, self.obstacles
def generate_observations_as_list(self):
return [self.done, self.score, self.snake, self.food, self.obstacles]
def render_destroy(self):
curses.endwin()
def end_game(self):
if self.gui:
curses.endwin()
exit()
if __name__ == "__main__":
game = SnakeGame(gui = True)
game.start()
for _ in range(20):
game.step(randint(0,3))