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