[Python] 纯文本查看 复制代码
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading, os, msvcrt, ctypes, time, sys, random, math, copy
class COORD(ctypes.Structure):
_fields_ = [("X",ctypes.c_short),("Y",ctypes.c_short)]
class CURSOR_INFO(ctypes.Structure):
_fields_ = [("dwSize",ctypes.c_uint),("bVisible",ctypes.c_uint)]
ww = 9 #列数
wh = 16 #行数
interval = 0.15 #帧间隔
invincible = False #无敌模式:off
xboundary = 2
yboundary = 2
title = "\u3000"*int( (ww + xboundary/2 - 3)/2) + "贪吃蛇\n"
ceiling = "\u3000" + "▁"*ww + "\u3000\n"
floor = "\u3000" + "▔"*ww + "\u3000\n"
middle = ("▕"+"\u3000"*ww + "▏\n")*wh
bkground = title + ceiling + middle + floor + "\u3000"*30 #背景数据,最后是信息提示区
nexts = {b"d":1,b"a":-1,b"s":ww,b"w":-ww} #按键-蛇头位移 映射表
snake = food = nx = None
foods = []
for i in range(ww*wh):
foods.append(i)
def writeCh(idx,ch,color=7):
'''写入一个字符。写屏范围是一个矩形空间,可用一维坐标idx或二维坐标x,y定位'''
if(0 <= idx < ww*wh):
dll.SetConsoleCursorPosition(hStdOut,COORD( (idx % ww)*2 + xboundary,int( idx / ww ) + yboundary)) #定位光标时,将矩形空间坐标转换成命令行坐标
dll.SetConsoleTextAttribute(hStdOut,color)
print(ch,end="")
sys.stdout.flush()
dll.SetConsoleTextAttribute(hStdOut,7)
def clearScreen():
'''清除内容并重画背景'''
dll.SetConsoleCursorPosition(hStdOut,COORD(0,0))
print(bkground)
def gameInit():
'''初始化游戏数据'''
global snake,food,nx
clearScreen()
snake = [int(wh/2)*ww]
food = list(set(foods) - set(snake))[random.randint(0,len(list(set(foods) - set(snake)))-1)]
nx = nexts[b"d"]
while(msvcrt.kbhit()): #清空缓冲区
msvcrt.getch()
def collision():
'''碰撞检测'''
if(snake[0] < 0 or snake[0] >= ww*wh): #上下出界
return not invincible
if(nx == 1 and snake[0]%ww == 0): #撞右墙
return not invincible
if(nx == -1 and (snake[0] + 1)%ww == 0): #撞左墙
return not invincible
if(snake[0] in snake[1:]): #撞蛇身
return not invincible
return False
def run():
'''主循环'''
global snake,food,nx
'''计算当前帧'''
if(msvcrt.kbhit()):
while(msvcrt.kbhit()): #获取按键输入
ch = msvcrt.getch()
if(ch in nexts.keys()):
#if(nx + nexts[ch] != 0 or len(snake) < 2): #注释掉这条限制是为了无敌模式时畅行无阻
nx = nexts[ch] #按键输入映射到蛇头位移
snake.insert(0,snake[0] + nx)
if(snake[0] == food):
food = list(set(foods) - set(snake))[random.randint(0,len(list(set(foods) - set(snake)))-1)]
else:
snake.pop()
'''绘制当前帧'''
if(collision()):
dll.SetConsoleCursorPosition(hStdOut,COORD(0,wh + 3))
print("Game Over")
time.sleep(2)
gameInit()
clearScreen()
for el in snake[1:]: #绘制蛇身
writeCh(el,"\u25a0",12)
writeCh(snake[0],"◆",12) #绘制蛇头
writeCh(food,"\u2605",10) #绘制食物
threading.Timer(interval,run).start()
'''''''''''''''''主程序'''''''''''''''''''''
dll = ctypes.WinDLL("Kernel32.dll")
hStdOut = dll.GetStdHandle(-11) #GetStdHandle(STD_OUTPUT_HANDLE)
dll.SetConsoleCursorPosition.argtypes = [ctypes.c_int,COORD]
dll.SetConsoleCursorInfo.argtypes = [ctypes.c_int,ctypes.c_void_p]
ci = CURSOR_INFO(1,0)
dll.SetConsoleCursorInfo(hStdOut,id(ci))
os.system("cls")
gameInit()
run()