-
Notifications
You must be signed in to change notification settings - Fork 0
/
snake.py
235 lines (207 loc) · 8.23 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# -*- coding: utf-8 -*-
import keyboard
import os, keyboard, time, random
global clearVar
syst = os.name
if syst == 'nt':
clearVar = "cls"
else:
clearVar = "clear"
def gridSet(x, y, positions, apple, blocked):
"""
Draws grid with all relevant characters.
Starts at the top of the board and draws the board row by row using the coordinates "right" and "down"
At each coordinate checks what mark should be printed and adds it to a line string which is printed for each row
"""
appleChar = 'Ó'
spaceChar = ' '
bottomChar = '▀'
topChar = '▄'
sideChar = '█'
char = '#'
blockedChar = '█'
down = 0
lineBreak = '\n'
lines = [] #creates an array that will be joined later to form the play grid
topRow = topChar*(x+2) #adds top border
lines.append(topRow) #adds lines one by one to the grid array
for height in range(y): #begins building grid by row
right = 0
down += 1
line = ''
for width in range(x+1): #goes through row unit by unit
if right == 0 or right == x:
line+=sideChar #adds right and left border
right += 1
if [right, down] in positions: #adds symbol for snake if coord is snake
line+=char
elif [right, down] == apple: #adds symbol for apple if coord is apple
line+=appleChar
elif [right, down] in blocked:
line+=blockedChar
else:
line+=spaceChar #otherwise adds empy char
lines.append(line) #adds line to the grid array
bottomRow = bottomChar*(x+2)
lines.append(bottomRow)
grid = lineBreak.join(lines)#joins together the grid array with line breaks between lines
print(grid) #print all lines at once to reduce flicker
def appleRandom(x,y):
"""
Gives random coordinates for a new apple
"""
appleX = random.randint(1,x)
appleY = random.randint(1,y)
apple = [appleX, appleY]
return apple
def applePlacer(x,y,positions, blocked):
"""
Places a new apple on the grid, tries to randomly place apples
until the apple is in an unoccupied square
"""
while True:
apple = appleRandom(x,y)
if apple not in positions and apple not in blocked:
return apple
def moveChar(x,y,positions, direction, apple, score, blocked):
"""
Moves the snake around the grid and keeps track of score
"""
pos1 = [positions[len(positions)-1][0],positions[len(positions)-1][1]] #creates a copy coordinate of the front of player snake
if direction == 'up': #moves the front coordinate in the relevant direction temporarily until conditions can be checked
pos1[1] -= 1
elif direction == 'down':
pos1[1] +=1
elif direction == 'left':
pos1[0] -=1
elif direction == 'right':
pos1[0] +=1
if pos1[0] >x: #checks if the front coordinate hit a wall
pos1[0] = x
return False
if pos1[0]<1:
pos1[0]=1
return False
if pos1[1] >y:
pos1[1] = y
return False
if pos1[1]<1:
pos1[1] = 1
return False
if pos1 in positions:#checks if the front coordinate hit the snake
return False
if pos1 in blocked: #checks if front coordinate hit a blocked section
return False
else:
positions.append(pos1)#moves the front position permanently
if pos1 == apple: #checks if snake ate an apple, snake is lengthened by not removing back coordinate
score += 100
apple = applePlacer(x,y,positions, blocked)#places new apple
else:
positions = positions[1:]#if an apple is not eaten, the snake "moves" by removing the back coordinate after a new front coordinate is added
return positions, direction, apple, score
def directionChanger(direction):
"""
Checks if the player is changing direction by checking if the player is pressing a key
"""
if keyboard.is_pressed('up'):
if direction != 'down': #won't let player move in the opposite direction they are currently moving
direction = 'up'
elif keyboard.is_pressed('down'):
if direction != 'up':
direction = 'down'
elif keyboard.is_pressed('left'):
if direction != 'right':
direction = 'left'
elif keyboard.is_pressed('right'):
if direction != 'left':
direction = 'right'
return direction
def levelSelect():
"""
gives blocked spaced based on the player's level selection
"""
level0 = [] #sets the blocked squares
level1 = [[5,5],[5,6],[5, 4],[5,7],[5, 8],[5, 3],[14, 3],[14, 4],[14,5],[14,6],[14,7],[14,8]]
levels = [level0, level1]#adds the level options to the level array
while True:
print('Which level would you like to play?')
level = input('1. Open\n2. Parallel\n')
try:
a = int(level)
try:
return levels[a-1]
except IndexError: #won't let player select level not in the options
print('Invalid Selection')
input()
os.system(clearVar)
except ValueError: #won't let player enter something other than a number
print('Invalid Selection')
input()
os.system(clearVar)
def snake():
"""
Main Game
"""
hiScore = 0
while True: #Start Game Loop, starts new games until the player wants to quit
os.system(clearVar)
print('+++++++++++++++++++++++++++++++')
print()
print(' ~~~~Snake!~~~~')
print()
print('+++++++++++++++++++++++++++++++')
x, y = 18, 10 #sets board size
pos1 = [x//2, y//2] #sets inital snake positions
pos2 = [pos1[0]+1, pos1[1]]
pos3 = [pos1[0]+2, pos1[1]]
positions = [pos3, pos2, pos1]
blocked = levelSelect()
score = 0
delay = 150
startTurn = int(round(time.time()*1000))
checked = 0
direction = 'wait'
os.system(clearVar)
apple = applePlacer(x,y,positions, blocked) #places starting apple
gridSet(x, y, positions, apple, blocked) #sets up initial grid
print('Score:', score)
print('High Score:', hiScore)
while direction == 'wait': #waits to start game until player starts moving
direction = directionChanger(direction)
if direction == 'right': #can't move right because the snake starts facing left
direction = 'wait'
while True: #Main Game Loop. Cycles through drawing grid and getting player input
if checked == False:
directionTemp = directionChanger(direction) #Checks for player input until a valid change is detected
if directionTemp != direction:
direction = directionTemp
checked = True #if the player changes direction, disables player input until the board is redrawn. Otherwise playe can run into themselves between screen draws
currentTime = int(round(time.time()*1000))
if currentTime > startTurn+delay: #Checks if the delay time has passed, if so starts the new turn
checked = False
direction = directionTemp
try: #if moveChar returns False, will give a TypeError. This means a Game Over has happened
positions, direction, apple, score = moveChar(x, y, positions, direction, apple, score, blocked)
os.system(clearVar)
gridSet(x, y, positions, apple, blocked)
print('Score:', score)
print('High Score:', hiScore)
startTurn = int(round(time.time()*1000)) #sets the start time for the turn
except TypeError:
print('Game Over!')
if score >hiScore:
hiScore = score
print('New High Score!')
input()
break
print('Would you like to play again? y/n') #prompt player to play again if they lose
again = input()
if again == 'n':
print('Bye!')
input()
break
def main():
snake()
if __name__ == "__main__":
main()