python 贪吃蛇_python简易贪吃蛇

python简易贪吃蛇

前言

开始

献上代码

from tkinter.messagebox import showinfo as msg

from random import randint as rand

from pygame.locals import *

import tkinter as tk

import pygame

import time

win = tk.Tk()

win.withdraw()

pygame.init()

def render(surf,blocks):

for x,y in blocks.keys():

renderingf = (x * 40,y * 40)

color = blocks[(x,y)]

pygame.draw.rect(surf,color,Rect(renderingf,(40,40)))

def render_snake(surf,pos):

def unique(pos):

for i in pos:

if(pos.count(i) > 1):

return False

return True

if(not unique(pos)):

return False

d = {}

for i in pos:

d[tuple(i)] = (255,255,255)

d[pos[-1]] = (0,0,255)

render(surf,d)

return True

def main(size):

scr = pygame.display.set_mode((40 * size[0],40 * size[1]))

stop = False

l = 3

pos = [(0,0),(1,0),(2,0)]

last = 'd'

dir = {'w':(0,-1),'s':(0,1),'a':(-1,0),'d':(1,0)}

oppsite = {'w':'s','s':'w','a':'d','d':'a'}

food = (rand(0,size[0] - 1),rand(0,size[1] - 1))

n = 1

speed = 30

while(1):

if((food in pos) and (not stop)):

l += 1

food = (rand(0,size[0] - 1),rand(0,size[1] - 1))

if(l == size[0] * size[1]):

return l

if(pos[-1][0] < 0 or pos[-1][1] < 0 or pos[-1][0] >= size[0] or pos[-1][1] >= size[1]):

return l

pygame.display.update()

speed = 30 - int(l / (1 - 3 / (size[0] * size[1])))

n += 1

n %= speed

pos = pos[-l:]

if((not n) and (not stop)):

t = (pos[-1][0] + dir[last][0],pos[-1][1] + dir[last][1])

pos.append(t)

scr.fill((0,0,0))

for ev in pygame.event.get():

if(ev.type == QUIT):

exit()

elif(ev.type == KEYDOWN and ev.unicode in 'aAwWsSdD' and ev.unicode):

if(ev.unicode == oppsite[last]):

return l

t = (pos[-1][0] + dir[ev.unicode.lower()][0],

pos[-1][1] + dir[ev.unicode.lower()][1])

pos.append(t)

last = str(ev.unicode.lower())

elif(ev.type == MOUSEBUTTONDOWN):

stop = not stop

elif(ev.type == KEYDOWN and ev.key == K_ESCAPE and stop):

return l

if(stop):

img = pygame.image.load('pause.jpg')

img = pygame.transform.scale(img,(40 * size[0],40 * size[1]))

scr.blit(img,(0,0))

else:

render(scr,{food:(0,255,0)})

if(not render_snake(scr,pos)):

return l

if(__name__ == '__main__'):

size = [15,15]

while(1):

l = main(size)

msg("GAMEOVER!","GAMEOVER! score:%s"%l)

代码剖析

from tkinter.messagebox import showinfo as msg

from random import randint as rand

from pygame.locals import *

import tkinter as tk

import pygame

import time

win = tk.Tk()

win.withdraw()

pygame.init()

导入库并初始化

注意⚠️:tkinter一定要在pygame之前初始化

def render(surf,blocks):

for x,y in blocks.keys():

renderingf = (x * 40,y * 40)

color = blocks[(x,y)]

pygame.draw.rect(surf,color,Rect(renderingf,(40,40)))

渲染格子,surf是要渲染的Surface对象,blocks是要渲染的位置和颜色

def render_snake(surf,pos):

def unique(pos):

for i in pos:

if(pos.count(i) > 1):

return False

return True

if(not unique(pos)):

return False

d = {}

for i in pos:

d[tuple(i)] = (255,255,255)

d[pos[-1]] = (0,0,255)

render(surf,d)

return True

渲染蛇,即为render(点击跳转)的包装。surf为要渲染的Surface对象,pos是蛇身子的每个格子的坐标列表。其中unique为蛇是否碰到自己的检测,其思路是,如果pos中有重复的,蛇就否碰到自己,所以,unique就是检测数组中是否有重复数据的

def main(size):

scr = pygame.display.set_mode((40 * size[0],40 * size[1]))

stop = False

l = 3

pos = [(0,0),(1,0),(2,0)]

last = 'd'

dir = {'w':(0,-1),'s':(0,1),'a':(-1,0),'d':(1,0)}

oppsite = {'w':'s','s':'w','a':'d','d':'a'}

food = (rand(0,size[0] - 1),rand(0,size[1] - 1))

n = 1

speed = 30

while(1):

if((food in pos) and (not stop)):

l += 1

food = (rand(0,size[0] - 1),rand(0,size[1] - 1))

if(l == size[0] * size[1]):

return l

if(pos[-1][0] < 0 or pos[-1][1] < 0 or pos[-1][0] >= size[0] or pos[-1][1] >= size[1]):

return l

pygame.display.update()

speed = 30 - int(l / (1 - 3 / (size[0] * size[1])))

n += 1

n %= speed

pos = pos[-l:]

if((not n) and (not stop)):

t = (pos[-1][0] + dir[last][0],pos[-1][1] + dir[last][1])

pos.append(t)

scr.fill((0,0,0))

for ev in pygame.event.get():

if(ev.type == QUIT):

exit()

elif(ev.type == KEYDOWN and ev.unicode in 'aAwWsSdD' and ev.unicode):

if(ev.unicode == oppsite[last]):

return l

t = (pos[-1][0] + dir[ev.unicode.lower()][0],

pos[-1][1] + dir[ev.unicode.lower()][1])

pos.append(t)

last = str(ev.unicode.lower())

elif(ev.type == MOUSEBUTTONDOWN):

stop = not stop

elif(ev.type == KEYDOWN and ev.key == K_ESCAPE and stop):

return l

if(stop):

img = pygame.image.load('pause.jpg')

img = pygame.transform.scale(img,(40 * size[0],40 * size[1]))

scr.blit(img,(0,0))

else:

render(scr,{food:(0,255,0)})

if(not render_snake(scr,pos)):

return l

这里分开分析

def main(size):

scr = pygame.display.set_mode((40 * size[0],40 * size[1]))

stop = False

l = 3

pos = [(0,0),(1,0),(2,0)]

last = 'd'

dir = {'w':(0,-1),'s':(0,1),'a':(-1,0),'d':(1,0)}

oppsite = {'w':'s','s':'w','a':'d','d':'a'}

food = (rand(0,size[0] - 1),rand(0,size[1] - 1))

n = 1

speed = 30

创建窗口,初始化是否暂停,蛇长,身体个块坐标,最后一个操作,方向与偏移量的关系字典,相反动作字典,食物位置,轮回数,速度(住:这里speed越大,速度越慢,请记住这件事情,后面会用到)

while(1):

if((food in pos) and (not stop)):

l += 1

food = (rand(0,size[0] - 1),rand(0,size[1] - 1))

if(l == size[0] * size[1]):

return l

if(pos[-1][0] < 0 or pos[-1][1] < 0 or pos[-1][0] >= size[0] or pos[-1][1] >= size[1]):

return l

进入游戏循环,处理吃到食物,蛇占满格子的问题

pygame.display.update()

speed = 30 - int(l / (1 - 3 / (size[0] * size[1])))

n += 1

n %= speed

pos = pos[-l:]

if((not n) and (not stop)):

t = (pos[-1][0] + dir[last][0],pos[-1][1] + dir[last][1])

pos.append(t)

scr.fill((0,0,0))

刷新窗口,清屏,这里中间的代码的作用向↓

\downarrow↓看

speed = 30 - int(l / (1 - 3 / (size[0] * size[1])))

n += 1

n %= speed

pos = pos[-l:]

if((not n) and (not stop)):

t = (pos[-1][0] + dir[last][0],pos[-1][1] + dir[last][1])

pos.append(t)

scr.fill((0,0,0))

第一行更新速度,这里公式是由速

=

÷

[

(

)

÷

]

速度=蛇长 \p [(最长长度 - 初始长度) \p 最长长度]速度=蛇长÷[(最长长度−初始长度)÷最长长度],将(

)

÷

(最长长度 - 初始长度) \p 最长长度(最长长度−初始长度)÷最长长度改成最

÷

÷

最长长度 \p 最长长度 - 初始长度 \p 最长长度最长长度÷最长长度−初始长度÷最长长度也就是1

3

/

(

s

i

z

e

[

0

]

s

i

z

e

[

1

]

)

1 - 3 / (size[0] * size[1])1−3/(size[0]∗size[1]),整理一下,变成s

p

e

e

d

=

l

÷

[

1

3

/

(

s

i

z

e

[

0

]

s

i

z

e

[

1

]

)

]

speed=l \p [1 - 3 / (size[0] * size[1])]speed=l÷[1−3/(size[0]∗size[1])],由于速度是整数,所以去一下整。

再往后就要解释一下为什么speed越大,速度越快了,因为speed指的就是经过speed个轮回之后蛇就自动挪一下,那么换句话说,speed 越大,不挪的轮回数就越多,挪动的时间间隔就越长

所以每次n

=

n

+

1

n = n + 1n=n+1就指的是又轮回了一次(因为n

nn这的就是轮回数),如果n

=

s

p

e

e

d

n = speedn=speed了,那么n

%

s

p

e

e

d

n~\%~speedn%speed就等于0,于是每次经过n

=

(

n

+

1

)

%

s

p

e

e

d

n = (n + 1)~\%~speedn=(n+1)%speed之后如果n

=

0

n = 0n=0,就代表改挪一下了。

for ev in pygame.event.get():

if(ev.type == QUIT):

exit()

elif(ev.type == KEYDOWN and ev.unicode in 'aAwWsSdD' and ev.unicode):

if(ev.unicode == oppsite[last]):

return l

t = (pos[-1][0] + dir[ev.unicode.lower()][0],

pos[-1][1] + dir[ev.unicode.lower()][1])

pos.append(t)

last = str(ev.unicode.lower())

elif(ev.type == MOUSEBUTTONDOWN):

stop = not stop

elif(ev.type == KEYDOWN and ev.key == K_ESCAPE and stop):

return l

处理事件

点x就退出

点awsd就按照方向移动

点击鼠标暂停或继续

暂停时点ESC就再来一局

if(stop):

img = pygame.image.load('pause.jpg')

img = pygame.transform.scale(img,(40 * size[0],40 * size[1]))

scr.blit(img,(0,0))

else:

render(scr,{food:(0,255,0)})

if(not render_snake(scr,pos)):

return l

如果是没有在玩(暂停),那么将图片与窗口调成同样大小后显示,显示的图片向↓

\downarrow↓看

ccbe78bd12cbacbec136fcd3b9841f5e.png

不难看出就是暂停继续的图案

如果在玩(没暂停),那么调用render_snake(点击跳转)渲染蛇,如果返回False,也就是撞自己上了,游戏结束。

if(__name__ == '__main__'):

size = [15,15]

while(1):

l = main(size)

msg("GAMEOVER!","GAMEOVER! score:%s"%l)

运行游戏,size中的两个值表明区域大小,可自行更改(推荐≤

15

\le15≤15)。

项目github

作者

hit-road

拜拜,下课!

回到顶部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值