PYTHON版贪吃蛇
本帖最后由 c03xp 于 2020-9-7 12:50 编辑我看别人发的小游戏挺有意思,自己也跃跃欲试,写了个PYTHON版贪吃蛇。原创亮点是调用win32函数随意移动光标位置,并且隐藏光标的显示。
理论上还可以继续优化,减小抖动,那样的话代码量可能会大一点。
已更新为彩色版
#!/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 =
food = list(set(foods) - set(snake))
nx = nexts
while(msvcrt.kbhit()): #清空缓冲区
msvcrt.getch()
def collision():
'''碰撞检测'''
if(snake < 0 or snake >= ww*wh): #上下出界
return not invincible
if(nx == 1 and snake%ww == 0): #撞右墙
return not invincible
if(nx == -1 and (snake + 1)%ww == 0): #撞左墙
return not invincible
if(snake in snake): #撞蛇身
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 != 0 or len(snake) < 2): #注释掉这条限制是为了无敌模式时畅行无阻
nx = nexts#按键输入映射到蛇头位移
snake.insert(0,snake + nx)
if(snake == food):
food = list(set(foods) - set(snake))
else:
snake.pop()
'''绘制当前帧'''
if(collision()):
dll.SetConsoleCursorPosition(hStdOut,COORD(0,wh + 3))
print("Game Over")
time.sleep(2)
gameInit()
clearScreen()
for el in snake: #绘制蛇身
writeCh(el,"\u25a0",12)
writeCh(snake,"◆",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 =
dll.SetConsoleCursorInfo.argtypes =
ci = CURSOR_INFO(1,0)
dll.SetConsoleCursorInfo(hStdOut,id(ci))
os.system("cls")
gameInit()
run()
涛之雨 发表于 2020-9-3 17:11
就是贪吃蛇向右移动的时候按左键应该是没有效果的,
而这个会直接死亡。
应该是少了一个判断吧?
明白了,多谢提醒,可以这样改一下:
if(ch in nexts.keys()):
if(nx + nexts != 0 or len(snake) < 2):
nx = nexts#按键输入映射到蛇头位移 运行了一下,挺好的,
有个bug(算是吧)
这种不可能存在的情况也会出现
(向右走的时候按左键,其他同理)
此外可以用
os.system("mode con:cols=23 lines=22")
设置窗口大小
当然主要是前来学习算法(哈哈哈哈哈) 666,已收藏,正需要这个 厉害了楼主{:301_993:} 感谢分享 这个好,感谢分享。 感谢分享 哈哈,很厉害 贪吃蛇 编程学习常遇到的例子 100行,厉害 感谢你的分享支持一下