【python学习笔记】使用类封装实现贪吃蛇

使用类


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 

说明:以上内容若有不足、错误之处欢迎各位指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值