贪吃蛇大作战(多人版)

  • 基本介绍
  • 代码
  • 界面截图
基本介绍

前面写过一个单人贪吃蛇游戏,作为拓展,我用Python3.7写了一个可以多人一起玩的贪吃蛇大作战,限定游戏时间为60s,根据最后得分进行排名。

代码
from tkinter import *
import random
import asyncio
import time


root = Tk()
win = Canvas(root, width=500, height=500)
win.create_rectangle(10, 10, 400, 400, fill="white")


class Snake:                                                              #定义蛇类

    num=0

    def __new__(cls, *args, **kwargs):
        cls.num+=1
        return super(cls,Snake).__new__(cls)

    def __init__(self,color):
        self.color = color
        self.id = self.num
        self.x_v = 15
        self.y_v = 0
        self.handx = 55                                                   #记录蛇头位置
        self.handy = 25
        self.coords = [
            (10,25),(25,25),(40,25),(55,25)                                  #蛇每一节的位置
        ]
        self.sel = [                                                      #在画布上创建蛇
            win.create_rectangle(11,26,24,39,fill=color),
            win.create_rectangle(26,26,39,39,fill=color),
            win.create_rectangle(41,26,54,39,fill=color),
            win.create_rectangle(56,26,69,39,fill=color),
        ]

    def __contains__(self, item):
        return item in self.coords

    def __getitem__(self, item):
        return self.coords[item]

    def __delitem__(self, key):
        del self.coords[key]

    def move(self):                                                      #蛇的移动,通过去尾加头实现
        del self[0]
        self.coords.append((self.handx+self.x_v,self.handy+self.y_v))
        win.delete(self.sel[0])
        new = win.create_rectangle(
            self.handx+self.x_v+1,
            self.handy+self.y_v+1,self.handx+self.x_v+14,
            self.handy+self.y_v+14,
            fill = self.color
        )
        del self.sel[0]
        self.sel.append(new)
        self.handx += self.x_v
        self.handy += self.y_v

    def right(self,event):                                               #蛇的转向,通过速度正交变换实现
        self.x_v,self.y_v = -self.y_v,self.x_v

    def left(self,event):
        self.x_v, self.y_v = self.y_v, -self.x_v

    def eat(self,food):                                                      #蛇的生长,通过加头不去尾实现
        self.coords.append((self.handx+self.x_v,self.handy+self.y_v))
        new = win.create_rectangle(
            self.handx + self.x_v+1,
            self.handy + self.y_v+1, self.handx + self.x_v + 14,
            self.handy + self.y_v + 14,
            fill = self.color
        )
        self.sel.append(new)
        self.handx += self.x_v
        self.handy += self.y_v
        win.delete(food)

    def die(self):
        [win.delete(item) for item in self.sel]


class Food:

    def __new__(cls):
        coord_x = random.randint(1, 22) * 15 + 10
        coord_y = random.randint(1, 22) * 15 + 10
        cls.coords = coord_x, coord_y
        x_left = coord_x + 1
        x_right = coord_x + 14
        y_left = coord_y + 1
        y_right = coord_y + 14
        return win.create_oval(x_left,y_left,x_right,y_right,fill='grey')


class Score:                                                     #计分器

    def __init__(self,snak):
        self.score=0
        self.snak=snak
        self.id = snak.id
        self.update_score()

    def update_score(self):
        self.sco = win.create_text(
            450, 15 + 40 * self.id,
            text=f"Score{self.id}:{self.score}",
            fill='green'
        )

    def __repr__(self):
        return str(self.score)

    def __next__(self):
        self.score += 20
        win.delete(self.sco)
        self.update_score()


class Time:

    def __init__(self):
        self.time_now = time.perf_counter()
        self.time_end = self.time_now + 60
        self.update_time()

    def update_time(self):
        self.ti = win.create_text(
            450, 200,
            text=f"{self.time_end-self.time_now:0.2f}s",
            fill="green"
        )

    def __next__(self):
        if self.time_now < self.time_end:
            win.delete(self.ti)
            self.update_time()
            self.time_now = time.perf_counter()
        else:
            win.delete(self.ti)
            self.time_now = self.time_end
            self.update_time()
            raise StopIteration


class Process:

    time = Time()
    snake = []
    score = []

    def add_snake(self,snake):
        self.snake.append(snake)
        self.score.append(Score(snake))

    @classmethod
    def condition(cls,snak):
        cond1 = snak[-1] not in snak[:-1]
        cond2 = snak[-1][0] < 385 and snak[-1][0] > 10
        cond3 = snak[-1][1] < 385 and snak[-1][1] > 10
        return cond1 and cond2 and cond3

    async def process(self,snake,score):
        while Process.condition(snake):
            if Food.coords in snake:
                snake.eat(self.food),next(score)
                self.food = Food()
            else:
                snake.move()
            try:
                next(self.time)
            except:
                break
            await asyncio.sleep(0.1)
            root.update()
        snake.die()

    async def start(self):
        self.food = Food()
        tasks = [asyncio.Task(self.process(sn,sc)) for sn,sc in zip(self.snake,self.score)]
        await asyncio.gather(*tasks)
        score = list(map(int,map(str , self.score)))
        import pandas as pd
        df = pd.DataFrame({"id":list(range(len(score))),"score":score})
        print(df.sort_values(by="score",ascending=False))

if __name__=='__main__':
    proc = Process()
    snake1 = Snake("blue")
    snake2 = Snake("red")
    snake3 = Snake("green")
    proc.add_snake(snake1)
    proc.add_snake(snake2)
    proc.add_snake(snake3)
    win.bind("", lambda x: asyncio.run(proc.start()) )
    win.bind("", snake1.left)
    win.bind("", snake1.right)
    win.bind("", snake2.left)
    win.bind("", snake2.right)
    win.bind("",snake3.left)
    win.bind("",snake3.right)
    win.focus_set()
    win.pack()
    root.mainloop()

注:这里以3人游戏为例,如果是多于或者少于3人,只需修改程序入口处代码即可

界面截图

贪吃蛇大作战(多人版)_第1张图片

   id  score
0   0    100
2   2     20
1   1      0

你可能感兴趣的:(python笔记)