使用类
snake.py
#!/usr/bin/env python
"""
file: snake.py
run: python snake.py
written by Zhao Jie at 2016-1-16
"""
from snake_module import *
def main_loop():
# create snake instance
game_inst = Snake()
pre_food = False
first_run = True
game_inst.drawEdge()
game_inst.printInfo(flag=True)
while game_inst.key != 'p':
game_inst.makeFood(pre_food, first_run)
pre_food = game_inst.moveSnake()
first_run = False
# snake hits the wall or itself, exit
if not game_inst.detectPos():
game_inst.printInfo('GAME OVER', flag=False)
gameExit()
game_inst.drawSnake()
game_inst.printInfo(flag=True)
#time.sleep(pnt_interval)
game_inst.getKeys()
game_inst.getDir()
if game_inst.key == ' ':
game_inst.key = ''
while game_inst.key != ' ':
game_inst.getKeys()
game_inst.key = ''
else:
game_inst.printInfo('GAME EXIT', flag=False)
gameExit()
# self-test or be a module
if __name__ == '__main__':
main_loop()
snake_module.py
#!/usr/bin/env python
# file: snake_module.py
"""
The module of snake.py
"""
from __future__ import print_function
import sys, time, termios, random, select
def gameExit():
# restore cursor and exit py
print('\033[?25h')
exit()
class Snake:
def __init__(self):
# map size (40+23)x20
self.width, self.high, self.info= 41, 21, 23
# body of snake, initailize position
self.body = [(self.width // 2, 1)]
# move direction
self.dir_x, self.dir_y = 0, 1
# chars of snake, wall, food
self.ch_snake, self.ch_wall, self.ch_food, self.key = 'X', '#', '@', '-'
# food map
self.food = [[False for fd_y in range(self.high + 1)] for fd_x in range(self.width + 1)]
# other
self.pnt_interval, self.key_interval, self.food_ct = 0.2, 0.01, 0
# x and y start from 1
def gotoXY(self, x, y):
print('\033[%s;%sH' % (y, x), end='', sep='')
# draw map's edge, the wall and info display box
def drawEdge(self):
# clear screen and hide cursor
print('\033[2J\033[?25l')
for x in range(self.high):
self.gotoXY(self.width, x)
print(self.ch_wall, end='', sep='')
self.gotoXY(self.width + self.info, x)
print(self.ch_wall, end='', sep='')
self.gotoXY(0, self.high)
print(self.ch_wall * (self.width + self.info))
def drawSnake(self):
for pos in self.body:
self.gotoXY(pos[0], pos[1])
print(self.ch_snake, end='', sep='')
def getKeys(self):
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
new = termios.tcgetattr(fd)
# turn off echo and enter
new[3] = new[3] & ~termios.ECHO & ~termios.ICANON
count, times = 0, self.pnt_interval // self.key_interval
try:
termios.tcsetattr(fd, termios.TCSADRAIN, new)
while count < times:
# sleep time second
time.sleep(self.key_interval)
# support non-blocking input
if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
self.key = sys.stdin.read(1)
if self.key == 'p': break
count += 1
except KeyboardInterrupt:
print('get: ctrl-c')
gameExit()
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
def moveSnake(self):
new_x, new_y = self.body[-1][0] + self.dir_x, self.body[-1][1] + self.dir_y
# snake can't turn around
if len(self.body) > 1 and (new_x, new_y) == self.body[-2]:
new_x, new_y = self.body[-1][0] - self.dir_x, self.body[-1][1] - self.dir_y
if self.food[new_x][new_y]:
self.body.append((new_x, new_y))
self.food[new_x][new_y] = False
self.food_ct += 1
return True
else:
self.body.append((new_x, new_y))
tail_x, tail_y = self.body.pop(0)
self.gotoXY(tail_x, tail_y)
# cut the tail of snake
print(' ', end='', sep='')
return False
def makeFood(self, pre_food=False, first_run=False):
def mk_food():
while True:
food_x = random.randrange(1, self.width)
food_y = random.randrange(1, self.high)
# food can't appear on body of snake
if not (food_x, food_y) in self.body:
self.food[food_x][food_y] = True
self.gotoXY(food_x, food_y)
print(self.ch_food, end='', sep='')
break
if first_run:
mk_food()
elif pre_food:
mk_food()
def getDir(self):
if self.key == 'w':
self.dir_x, self.dir_y = 0, -1
elif self.key == 's':
self.dir_x, self.dir_y = 0, +1
elif self.key == 'a':
self.dir_x, self.dir_y = -1, 0
elif self.key == 'd':
self.dir_x, self.dir_y = +1, 0
def detectPos(self):
x, y = self.body[-1][0], self.body[-1][1]
if (x > 0 and x < self.width) and (y > 0 and y < self.high) and (not (x, y) in self.body[:-1]):
return True
else:
return False
def printInfo(self, info='', flag=True):
if flag:
self.gotoXY(self.width + 2, 4)
print('[w/s/a/d] to move')
self.gotoXY(self.width + 2, 5)
print('[p] to quit')
self.gotoXY(self.width + 2, 6)
print('[space] to pause/run')
self.gotoXY(self.width + 2, 8)
print('score:', self.food_ct)
self.gotoXY(self.width + 2, 10)
print('length of snake: %03d' % len(self.body))
self.gotoXY(self.width + 2, 12)
print('get:', self.key)
else:
print('\033[2J')
self.gotoXY(0, 0)
print('#' * 13)
print('# %s #' % info)
print('#' * 13)
run
# snake.py and snake_module.py must be in the same dir
python snake.py
说明:以上内容若有不足、错误之处欢迎各位指正。