练手项目 - 贪吃蛇

贪吃蛇思路

  1. tkinter的基本使用
  2. 定义画布(格子)
  3. 创建蛇的一节
  4. 用方向键控制这一节走动
  5. 定义一个egg
  6. 实现蛇吃蛋的逻辑
  7. 实现蛇变长的逻辑
  8. 实现蛇碰壁死亡的逻辑、
  9. 蛇咬到自己死亡

以下为完整代码:

import tkinter as tk
import random

import time

background = 'gray'
egg_color = 'red'
snake_color = 'black'
score = 0
gameover = False

grid_size = 20
grid_num = 30

width = grid_size * grid_num + 150
height = grid_size * grid_num


# 创建蛇
class Snake(object):
    def __init__(self, canvas, x, y, distx=0, disty=1, length=1, color='black'):
        self.canvas = canvas
        self.length = length
        self.color = color
        self.x = x
        self.y = y
        self.head = canvas.create_rectangle(self.x * grid_size, self.y * grid_size, (self.x + 1) * grid_size,
                                            (self.y + 1) * grid_size, fill=self.color)
        # 蛇的整个身体
        self.section = [[self.head, self.x, self.y]]
        # 移动的方向
        self.distx = distx
        self.disty = disty
        self.grid()
        self.canvas.bind_all("", self.move)
        self.canvas.bind_all("", self.move)
        self.canvas.bind_all("", self.move)
        self.canvas.bind_all("", self.move)
        self.draw()
        self.collision()

    def grid(self):
        """
        画格子
        :return:
        """
        for i in range(grid_num + 1):
            self.canvas.create_line(grid_size * i, 0, grid_size * i, height)
            self.canvas.create_line(0, grid_size * i, width - 150, grid_size * i)

    def draw(self):
        """
        画整个蛇
        :return:
        """
        # 更新头部
        # self.canvas.move(self.head, self.distx * grid_size, self.disty * grid_size)
        # self.upforward()
        # self.x += self.distx
        # self.y += self.disty
        print('头部位置:', self.x, self.y)
        idx = len(self.section) - 1
        while idx > 0:
            curItem = self.section[idx]
            lastItem = self.section[idx - 1]
            # print('身体移动:', curItem, '-->',lastItem)
            # 把curItem移動到lastItem的位置,並且變換座標
            dx = lastItem[1] - curItem[1]
            dy = lastItem[2] - curItem[2]
            self.canvas.move(curItem[0], dx * grid_size, dy * grid_size)
            curItem[1] = lastItem[1]
            curItem[2] = lastItem[2]
            idx -= 1
        # 更新頭部
        head = self.section[0]
        self.canvas.move(self.head, self.distx * grid_size, self.disty * grid_size)
        self.x += self.distx
        self.y += self.disty
        head[1] = self.x
        head[2] = self.y
        self.collision()

    def lengthen(self):
        """
        蛇变长
        :return:
        """
        x = self.section[-1][1]
        y = self.section[-1][2] + 1
        idn = self.canvas.create_rectangle(x * grid_size, y * grid_size, (x + 1) * grid_size, (y + 1) * grid_size,
                                           fill=self.color)
        self.section.append([idn, x, y])
        # print('idn', idn, '初始位置:', x, y)
        self.length += 1

    def move(self, event):
        """
        按钮按下的事件处理函数
        :param event:
        :return:
        """
        if self.distx==0 and self.disty==-1:
            if event.keysym == "Up":
                self.distx = 0
                self.disty = -1
            elif event.keysym == "Left":
                self.distx = -1
                self.disty = 0
            elif event.keysym == "Right":
                self.distx = 1
                self.disty = 0
            else:
                pass
        if self.distx==0 and self.disty==1:
            if event.keysym == "Left":
                self.distx = -1
                self.disty = 0
            elif event.keysym == "Down":
                self.distx = 0
                self.disty = 1
            elif event.keysym == "Right":
                self.distx = 1
                self.disty = 0
            else:
                pass
        if self.distx==-1 and self.disty==0:
            if event.keysym == "Left":
                self.distx = -1
                self.disty = 0
            elif event.keysym == "Down":
                self.distx = 0
                self.disty = 1
            elif event.keysym == "Up":
                self.distx = 0
                self.disty = -1
            else:
                pass
        if self.distx==1 and self.disty==0:
            if event.keysym == "Up":
                self.distx = 0
                self.disty = -1
            elif event.keysym == "Down":
                self.distx = 0
                self.disty = 1
            elif event.keysym == "Right":
                self.distx = 1
                self.disty = 0
            else:
                pass




    def collision(self):
        """
        撞墙 及是否咬到自己 判断
        :return:
        """
        global gameover
        if (self.x == 0 and self.distx == -1) or (self.x == grid_num - 1 and self.distx == 1) or (
                        self.y == 0 and self.disty == -1) or (self.y == grid_num - 1 and self.disty == 1):
            gameover = True


        cnt=len(self.section)-1
        while cnt>0:
            curItem=self.section[cnt]
            # print('cunItem:', curItem)
            if self.x==curItem[1] and self.y==curItem[2]:
                gameover = True
                break
            cnt -=1


class Egg(object):
    def __init__(self, canvas, x, y, color='red'):
        self.cvs = canvas
        self.x = x
        self.y = y
        # print('egg: ', self.x, self.y)
        self.color = color
        # self.draw(self.color)
        self.id=self.cvs.create_rectangle(grid_size * self.x, grid_size * self.y, grid_size * (self.x + 1),
                                  grid_size * (self.y + 1),
                                  fill=color)

    # def draw(self, color):
    #     self.cvs.create_rectangle(grid_size * self.x, grid_size * self.y, grid_size * (self.x + 1),
    #                               grid_size * (self.y + 1),
    #                               fill=color)

    def new_egg(self):
        # self.draw('gray')
        x = random.randint(1, grid_num - 2)
        y = random.randint(1, grid_num - 2)
        dx=x-self.x
        dy=y-self.y
        # print('移动: ', dx, dy)
        self.cvs.move(self.id, dx * grid_size, dy * grid_size)
        self.x = x
        self.y = y
        # print('egg: ',self.x, self.y)


def scored(x):
    global background
    # 计分区刷新
    cvs.create_rectangle(width - 150, 0, width, 200, fill=background)
    cvs.create_text(670, 100, text=['score:', str(x)],
                    fill='black', font=('Courier', 16))


def eat_egg(snake_x, snake_y, egg_x, egg_y):
    global score
    if snake_x == egg_x and snake_y == egg_y:
        score += 1
        scored(score)
        egg.new_egg()
        snake.lengthen()


root = tk.Tk()
root.title('snake')
root.geometry(
    '%dx%d+%d+%d' % (width, height, (root.winfo_screenwidth() - width) / 2, (root.winfo_screenheight() - height) / 2))
# 窗口最大值
root.maxsize(width, height)
# 窗口最小值
root.minsize(width, height)
cvs = tk.Canvas(root, width=width, height=height, bg='grey')
cvs.pack()
root.update()

snake = Snake(cvs, 5, 5)
egg = Egg(cvs, 10, 10)
idx = 0
while not (gameover):
    if idx % 20 == 0:
        snake.draw()
        eat_egg(snake.x, snake.y, egg.x, egg.y)
    root.update_idletasks()
    root.update()
    time.sleep(0.01)
    idx += 1

cvs.create_text(670, 400, text='GameOver!',
                            fill='red', font=('Courier', 16))

root.mainloop()

你可能感兴趣的:(python)