python 实现贪吃蛇

需要实现的几个基本功能

	# 1.随机出生点, 随机果实
	# 2.死亡判断
	# 3.速度变快
	# 4.吃果实增长
	# 5.监听上下左右按键, 改变运动方向

代码实现

# -*- coding: utf-8 -*-
# @Date    : 2019-12-22 11:02:27
# @Author  : Flying Hu (1152598046@qq.com)
# @Link    : http://www.flyinghu.cn
# @name    : 贪吃蛇
# @Version : 0.1
from pynput import keyboard
from pynput.keyboard import Key
from random import randint
import threading
import time
import os


r = threading.Lock()


class Win(object):
    '''窗口类'''

    # 单例设计
    __instance = None

    def __new__(cls, width=20, height=20):
        '''判断是否已经实例化'''
        if cls.__instance is None:
            obj = super().__new__(cls)
            obj.char = '█'
            obj.width = width
            obj.height = height
            obj.current_win = [
                [obj.char for col in range(width)] for row in range(height)]
            obj.stop = False  # 用来停止线程
            cls.__instance = obj
        return cls.__instance

    def show(self):
        '''显示'''
        # print(self.win)
        while True:
            if self.stop:
                # 停止
                break
            r.acquire()
            self.cls()
            for i in self.current_win:
                for j in i:
                    print(j, end='')
                print()
            r.release()
            time.sleep(1/60)
    
    def show_win(self):
        self.cls()
        for i in self.current_win:
            for j in i:
                print(j, end='')
            print()

    def refresh(self):
        self.current_win = [[self.char for col in range(
            self.width)] for row in range(self.height)]

    def cls(self):
        '''清空控制台输出'''
        os.system('cls')


class Snake(object):
    '''贪吃蛇类'''
    # 单例设计
    __instance = None

    def __new__(cls, win, de_speed=5):
        '''判断是否已经实例化'''
        if cls.__instance is None:
            obj = super().__new__(cls)
            obj.char = '●'
            obj.fruit_char = '★'
            obj.win = win
            obj.direction = randint(0, 3)  # 方向 上:0 左:1 下:2 右:3
            obj.de_speed = de_speed
            obj.statu = True
            # 随机生成初始位置, 为避免初始为边框周围
            obj.current_snake = [
                [
                    randint(int(1/4 * (obj.win.height - 1)),
                            int(3/4 * (obj.win.height - 1))),
                    randint(int(1/4 * (obj.win.width - 1)),
                            int(3/4 * (obj.win.width - 1)))
                ]
            ]
            cls.__instance = obj
        return cls.__instance

    def load(self):
        '''加载蛇到地图中'''
        # 加载果实
        self.win.refresh()
        row, col = self.fruit
        self.win.current_win[row][col] = self.fruit_char
        for row, col in self.current_snake:
            self.win.current_win[row][col] = self.char

    def gen_fruit(self):
        '''生成果实'''
        while True:
            self.fruit = [randint(0, self.win.height - 1),
                          randint(0, self.win.width - 1)]
            # 避免果实在蛇身体里面
            if self.fruit not in self.current_snake:
                break

    def move(self):
        # if (self.current_snake[0][0] == self.fruit[0]) and (self.current_snake[0][1] == self.fruit[1]):
        if self.current_snake[0] == self.fruit:
            # 吃果实
            if self.direction == 0:
                self.current_snake.append(
                    [self.current_snake[-1][0] + 1, self.current_snake[-1][1]])
            elif self.direction == 1:
                self.current_snake.append(
                    [self.current_snake[-1][0], self.current_snake[-1][1] + 1])
            elif self.direction == 2:
                self.current_snake.append(
                    [self.current_snake[-1][0] - 1, self.current_snake[-1][1]])
            else:
                self.current_snake.append(
                    [self.current_snake[-1][0], self.current_snake[-1][1] - 1])
            self.gen_fruit()
        self.current_snake[1:] = self.current_snake[:-1]
        if self.direction == 0:
            self.current_snake[0] = [self.current_snake[0]
                                     [0] - 1, self.current_snake[0][1]]
        elif self.direction == 1:
            self.current_snake[0] = [self.current_snake[0]
                                     [0], self.current_snake[0][1] - 1]
        elif self.direction == 2:
            self.current_snake[0] = [self.current_snake[0]
                                     [0] + 1, self.current_snake[0][1]]
        else:
            self.current_snake[0] = [self.current_snake[0]
                                     [0], self.current_snake[0][1] + 1]

    def press(self, key):
        '''监听上下左右键盘事件'''
        if self.statu:
            # 防止按键过快
            if key == Key.up and self.direction != 2:
                self.direction = 0
                self.statu = False
            elif key == Key.left and self.direction != 3:
                self.direction = 1
                self.statu = False
            elif key == Key.down and self.direction != 0:
                self.direction = 2
                self.statu = False
            elif key == Key.right and self.direction != 1:
                self.direction = 3
                self.statu = False
            else:
                pass

    def run(self):
        try:
            # 开启监听键盘
            keyboard.Listener(on_press=self.press).start()
            # 开启单独屏幕刷新线程, 两种刷新方式, 运动完刷新和单独线程刷新
            # t = threading.Thread(target=self.win.show)
            # t.setDaemon(True)
            # t.start()
            self.gen_fruit()
            while True:
                self.move()
                self.statu = True
                # 运动后判断当前是否死亡
                if self.current_snake[0][0] < 0 or self.current_snake[0][0] >= self.win.height or self.current_snake[0][1] < 0 or self.current_snake[0][1] > self.win.width:
                    # 超出上下左右边界
                    self.win.stop = True
                    break
                elif self.current_snake[0] in self.current_snake[1:]:
                    # 咬到身体死亡
                    self.win.stop = True
                    break
                self.load()
                # 根据当前蛇的长度来提高速度 改变初始速度就相当于改变难度
                self.speed = self.de_speed * \
                    (1 + len(self.current_snake) ** 2 /
                     (self.win.width * self.win.height))
                # 移动完刷新屏幕
                self.win.show_win()
                time.sleep(1/self.speed)
            time.sleep(0.5)
            print('Game over')
            print('得分:', len(self.current_snake))
        except Exception as e:
            print(repr(e))


Snake(Win(width=20, height=20)).run()

运行环境

使用cmd终端运行, 本人使用powershell和编辑器直接终端运行总会有点问题

源码下载

g_snake.py–>https://download.csdn.net/download/flyinghu123/12046308

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值