python snack_python 贪吃蛇

#!/usr/bin/python3

'''项目分析:

-构成

-蛇Snake

-实物Food

-世界World

-蛇和食物属于整个世界

class world:

self.snake

self.food

-上面代码不太友好

-我们用另外一个思路来分析

-我们的分析思路:

-食物是一个独立的事物

-蛇也是一个独立的事物

-世界也是,但世界负责显示'''

importrandomimporttimeimportthreadingfrom tkinter import *

importqueueclassFood():'''功能:

1.出现在画面的某一个地方

2.一旦被吃则增加蛇的分数'''

def __init__(self,queue):'''自动产生一个食物'''self.queue=queue

self.new_food()defnew_food(self):'''功能:产生一个食物

产生一个食物的过程也就是随机产生一个食物坐标的过程'''

#注意横坐标产生的位置

x = random.randrange(10,490,10)#同理产生y坐标

y = random.randrange(10,290,10)#需要注意的是,我们的正规游戏屏幕一般不需要把他设置成正方形

self.position = x,y #position存放食物的位置

#队列,就是一个不能随意访问内部元素,只能从头弹出一个元素,并只能从队尾追加一个元素的list

#把一个食物产生的消息放入队列

#消息的格式,自己定义

#我的定义是:消息是一个dict,k代表消息类型,v代表此类型的数据

self.queue.put({"food":self.position}) #queue.put方法中有两个参数,第一个为item必填,第二个为block,默认为1

classSnake(threading.Thread):'''蛇的功能:

1.蛇能动,由我们上下左右按键控制

2.蛇每次动都需要重新计算蛇头的位置

3.检测游戏是否完事的功能'''

def __init__(self,world,queue):

threading.Thread.__init__(self)

self.world=world

self.queue=queue

self.direction= "Up"self.points_earned= 0 #游戏分数

self.food =Food(self.queue)

self.snake_points= [(490,50),(480,50),(470,50),(460,50)] #蛇身各点

self.start()defrun(self):'''一旦启用多线程,调用此函数

要要蛇一直在跑'''

ifself.world.is_game_over:

self._delete()while notself.world.is_game_over:

self.queue.put({"move":self.snake_points})if self.points_earned < 10:

time.sleep(0.3)elif 10 <= self.points_earned < 15:

time.sleep(0.2)elif 15 <= self.points_earned < 20:

time.sleep(0.1)elif 20 <= self.points_earned < 25:

time.sleep(0.05)elif 25 <= self.points_earned < 100:

time.sleep(0.04)else:

time.sleep(0.03)

self.move()defmove(self):'''负责蛇的移动:

1.重新计算蛇头的坐标

2.当蛇头跟食物相遇,则加分,重新生成食物,通知world,加分

3.否则,蛇需要动'''new_snake_point= self.cal_new_position() #重新计算蛇头位置

#蛇头位置跟食物位置相同

if self.food.position ==new_snake_point:

self.points_earned+=1self.queue.put({"points_earned":self.points_earned})

self.food.new_food()#旧的食物被吃掉产生新的食物

self.snake_points.append(new_snake_point)else:#需要注意蛇的信息的保存方式

#每次移动是删除蛇的最前位置,并在后面追加

self.snake_points.pop(0)#判断程序是否退出,因为新的蛇可能撞墙

self.check_game_over(new_snake_point)

self.snake_points.append(new_snake_point)defcal_new_position(self):'''计算新的蛇头位置'''last_x,last_y= self.snake_points[-1]if self.direction == "Up": #direction负责存储蛇移动的方向

new_snake_point = last_x,last_y - 10 #每次移动的跨度是10像素

elif self.direction == "Down":

new_snake_point= last_x,last_y + 10

elif self.direction == "Left":

new_snake_point= last_x - 10,last_yelse:#self.direction == "Right":

new_snake_point = last_x + 10,last_yreturn(new_snake_point)defkey_pressed(self,event):#keysym是按键名称

self.direction =event.keysymdefcheck_game_over(self,snake_point):'''判断的依据是蛇是否撞墙

把蛇头的坐标拿出来跟墙判断'''x,y= snake_point[0],snake_point[1]if not 0

self.queue.put({"game_over":True})classWorld(Tk):'''用来模拟整个游戏画板'''

def __init__(self,queue):

Tk.__init__(self)

self.queue=queue

self.is_game_over=False#定义画板

self.canvas = Canvas(self,width = 500,height = 300,bg = 'gray')

self.canvas.pack()#画出蛇和食物

self.snake = self.canvas.create_line((0,0),(0,0),fill = 'black',width = 10)

self.food= self.canvas.create_rectangle(0,0,0,0,fill = '#FFCC4C',width = 10)

self.points_earned= self.canvas.create_text(450,20,fill = 'white',text = 'SCORE: 0')

self.queue_handler()defqueue_handler(self):try:#需要不断从消息队列拿到消息,所以使用死循环

whileTrue:

task= self.queue.get(block =False)if task.get("game_over"):

self.game_over()if task.get('move'):

points= [x for point in task["move"] for x inpoint]#重新绘制蛇

self.canvas.coords(self.snake,*points)#同样道理,还需要处理食物、得分

if task.get('food'):

self.canvas.coords(self.food,*task['food'],*task['food'])if task.get('points_earned'):

self.canvas.itemconfigure(self.points_earned,text= 'SCORE: {}'.format(task['points_earned']))except queue.Empty: #爆出队列为空异常

if notself.is_game_over:#after的含义是,在多少毫秒后调用后面的函数

self.canvas.after(100,self.queue_handler)defgame_over(self):'''游戏结束,清理现场'''self.is_game_over=True

self.canvas.create_text(250,150,fill = 'red',text = "Game Over !!!")

qb= Button(self,text = 'Quit',command =self.destroy)

rb= Button(self,text = 'Again',command = self.__init__)if __name__ == "__main__":

q=queue.Queue()

world=World(q)

world.title("^_^john家的贪吃蛇* _ *")

snake=Snake(world,q)

world.bind('',snake.key_pressed)#同样绑定右、上、下键

world.bind('',snake.key_pressed)

world.bind('',snake.key_pressed)

world.bind('',snake.key_pressed)

world.mainloop()#消息循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值