本帖最后由 Cool_Breeze 于 2021-7-22 10:18 编辑
#增加Color,长按加速
[Python] 纯文本查看 复制代码 # coding=utf-8
# author Cool_Breeze
import ctypes
import msvcrt
from time import sleep
from os import system
from random import randrange
from collections import deque
from threading import Thread
# 位置信息结构体
class point(ctypes.Structure):
_fields_ = [('x', ctypes.c_short),
('y', ctypes.c_short)]
class CharSnake(object):
def __init__(self):
self.HIGHT = 26
self.WIDTH = 60
self.MAINHANDLE = ctypes.windll.kernel32.GetStdHandle(-11)
self.SNAKE = deque([])
self.HEADICON = 'O'
self.FOODICON = '$'
self.FOODPOINT = point()
self.InputThead = None
self.__exit = False
self.DIRECTION = 'K'
system(f'mode con cols={self.WIDTH} lines={self.HIGHT}')
system("title 贪吃蛇游戏")
# 隐藏光标
ctypes.windll.kernel32.SetConsoleCursorInfo(
self.MAINHANDLE, ctypes.byref(point(1,0)))
self.SPEED = 0.1
self.ORDKEY = None
def Move(self):
system("cls")
self.SNAKE.clear()
self.side()
self.createSnake()
self.createFood()
self.__exit = False
self.InputThead = Thread(target=self.Speed, daemon=True)
self.InputThead.start()
while True:
if self.moveSnake(): break
sleep(self.SPEED)
def gotoXYPrint(self, coord, char):
ctypes.windll.kernel32.SetConsoleCursorPosition(
self.MAINHANDLE, coord)
if char == self.HEADICON:
ctypes.windll.kernel32.SetConsoleTextAttribute(
self.MAINHANDLE, 14)
elif char == self.FOODICON:
ctypes.windll.kernel32.SetConsoleTextAttribute(
self.MAINHANDLE, 12)
else:
ctypes.windll.kernel32.SetConsoleTextAttribute(
self.MAINHANDLE, 11)
print(char, end='', flush=True)
# 边框
def side(self):
for n in range(self.WIDTH-1):
self.gotoXYPrint(point(n,0), '+')
self.gotoXYPrint(point(n,self.HIGHT-1), '+')
for n in range(self.HIGHT-1):
self.gotoXYPrint(point(0,n), '+')
self.gotoXYPrint(point(self.WIDTH-1,n), '+')
def createFood(self):
off = False
while True:
x = randrange(1, self.WIDTH-1)
y = randrange(1, self.HIGHT-1)
for n in self.SNAKE:
if n.x == x and n.y == y:
continue
else:
self.FOODPOINT.x = x
self.FOODPOINT.y = y
self.gotoXYPrint(self.FOODPOINT, self.FOODICON)
off = True
if off: break
def createSnake(self):
x, y = self.WIDTH//2, self.HIGHT//2
for n in range(3):
t = point(x+n, y)
self.SNAKE.append(t)
self.gotoXYPrint(t, self.HEADICON)
def update(self):
for i in self.SNAKE:
self.gotoXYPrint(i, self.HEADICON)
def _exit(self, info):
input(info)
self.__exit = True
self.SPEED = 0.1
def collision(self):
head = self.SNAKE[0]
count = 0
for n in self.SNAKE:
count += 1
if count == 1: continue
if n.x == head.x and n.y == head.y:
self._exit('游戏结束!')
return True
if head.x == 0 or head.y == 0 or \
head.x == self.WIDTH-1 or head.y == self.HIGHT-1:
self._exit('游戏结束!')
return True
def moveSnake(self):
'''
K == ←
M == →
H == ↑
P == ↓
'''
if self.DIRECTION == 'K':
self.SNAKE.appendleft(point(self.SNAKE[0].x-1, self.SNAKE[0].y))
elif self.DIRECTION == 'M':
self.SNAKE.appendleft(point(self.SNAKE[0].x+1, self.SNAKE[0].y))
elif self.DIRECTION == 'H':
self.SNAKE.appendleft(point(self.SNAKE[0].x, self.SNAKE[0].y-1))
elif self.DIRECTION == 'P':
self.SNAKE.appendleft(point(self.SNAKE[0].x, self.SNAKE[0].y+1))
# 其他按键不做任何动作
else: return None
if self.collision(): return True
# 是否吃到食物
if self.SNAKE[0].x != self.FOODPOINT.x or self.SNAKE[0].y != self.FOODPOINT.y:
self.gotoXYPrint(self.SNAKE.pop(), ' ')
else:
self.createFood()
self.update()
# 长按加速
def Speed(self):
while True:
if self.__exit: break
sleep(0.001)
if msvcrt.kbhit():
inputKey = msvcrt.getwch()
# 特殊按键
if inputKey == '\000' or inputKey == '\xe0':
inputKey = msvcrt.getwch()
if self.DIRECTION == 'K' and inputKey == 'M': continue
elif self.DIRECTION == 'M' and inputKey == 'K': continue
elif self.DIRECTION == 'H' and inputKey == 'P': continue
elif self.DIRECTION == 'P' and inputKey == 'H': continue
if self.DIRECTION == inputKey:
if self.SPEED >= 0.02:
self.SPEED -= 0.02
else:
self.DIRECTION = inputKey
self.SPEED = 0.1
if __name__ == '__main__':
while True:
CharSnake().Move() |