Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from tkinter import*
- from random import randint
- # Константы для созд. сетки.................
- GRADUATION = 40
- PIXEL = 10
- STEP = 2 * PIXEL
- WD = PIXEL * GRADUATION
- HT = PIXEL * GRADUATION
- # cons для фигур ...........................
- OB_SIZE_FACTOR = 1
- SN_SIZE_FACTOR = 0.9
- OB_SIZE = PIXEL * OB_SIZE_FACTOR
- SN_SIZE = PIXEL * SN_SIZE_FACTOR
- # Цвета конст.
- BG_COLOR = 'black'
- OB_COLOR = 'red'
- SN_COLOR = 'white'
- # Словарь для облегчения доступа к типу фигуры в класе Shape
- SN = 'snake'
- OB = 'obstacle'
- SIZE = {SN: SN_SIZE, OB: OB_SIZE}
- # const для ввода с клавиатуры
- UP = 'Up'
- DOWN = 'Down'
- RIGHT = 'Right'
- LEFT = 'Left'
- # словарь для облегчения доступа к «указаниям»
- DIRECTIONS = {UP: [0, -1], DOWN: [0, 1], RIGHT: [1, 0], LEFT: [-1, 0]}
- AXES = {UP: 'Vertical', DOWN: 'Vertical', RIGHT: 'Horizontal', LEFT: 'Horizontal'}
- # Время обновления для движения
- REFRESH_TIME = 150
- class Master(Canvas):
- """создать игровой холст, змею, препятствие, следить за счетом"""
- def __init__(self, boss=None):
- super().__init__(boss)
- self.configure(width=WD, height=HT, bg=BG_COLOR)
- self.running = 0
- self.snake = None
- self.obstacle = None
- self.direction = None
- self.current = None
- self.score = Scores(boss)
- def start(self):
- """Начало игры"""
- if self.running == 0:
- self.snake = Snake(self)
- self.obstacle = Obstacle(self)
- self.direction = RIGHT
- self.current = Movement(self, RIGHT)
- self.current.begin()
- self.running = 1
- def clean(self):
- """Рестарт"""
- if self.running == 1:
- self.score.reset()
- self.current.stop()
- self.running = 0
- self.obstacle.delete()
- for block in self.snake.blocks:
- block.delete()
- def redirect(self, event):
- """Считывание клавиш и и движение земли соотвественно клавиши"""
- if 1 == self.running and \
- event.keysym in AXES.keys() and\
- AXES[event.keysym] != AXES[self.direction]:
- self.current.flag = 0
- self.direction = event.keysym
- self.current = Movement(self, event.keysym) # новый экземпляр на каждом шагу
- self.current.begin() # защита от двойного наж
- class Scores:
- """Отслеживание счёта, и сохранение наилучщего"""
- def __init__(self, boss=None):
- self.counter = StringVar(boss, '0')
- self.maximum = StringVar(boss, '0')
- def increment(self):
- score = int(self.counter.get()) + 1
- maximum = max(score, int(self.maximum.get()))
- self.counter.set(str(score))
- self.maximum.set(str(maximum))
- def reset(self):
- self.counter.set('0')
- class Shape:
- """Это шаблон для создания препятствий и частей тела змеи"""
- def __init__(self, can, a, b, kind):
- self.can = can
- self.x, self.y = a, b
- self.kind = kind
- if kind == SN:
- self.ref = Canvas.create_rectangle(self.can,
- a - SN_SIZE, b - SN_SIZE,
- a + SN_SIZE, b + SN_SIZE,
- fill=SN_COLOR,
- width=2)
- elif kind == OB:
- self.ref = Canvas.create_oval(self.can,
- a - OB_SIZE, b - OB_SIZE,
- a + SN_SIZE, b + SN_SIZE,
- fill=OB_COLOR,
- width=2)
- def modify(self, a, b):
- self.x, self.y = a, b
- self.can.coords(self.ref,
- a - SIZE[self.kind], b - SIZE[self.kind],
- a + SIZE[self.kind], b + SIZE[self.kind])
- def delete(self):
- self.can.delete(self.ref)
- class Obstacle(Shape):
- """Еда"""
- def __init__(self, can):
- """создавать еду, там где нету тела змеи"""
- self.can = can
- p = int(GRADUATION/2 - 1)
- n, m = ra
- ndint(0, p), randint(0, p)
- a, b = PIXEL * (2 * n + 1), PIXEL * (2 * m + 1)
- while [a, b] in [[block.x, block.y] for block in self.can.snake.blocks]:
- n, m = randint(0, p), randint(0, p)
- a, b = PIXEL * (2 * n + 1), PIXEL * (2 * m + 1)
- super().__init__(can, a, b, OB)
- class Block(Shape):
- """Змеиные части тела"""
- def __init__(self, can, a, y):
- super().__init__(can, a, y, SN)
- class Snake:
- """Слежение за частями тела змеи"""
- def __init__(self, can):
- """Исходная позиция"""
- self.can = can
- a = PIXEL + 2 * int(GRADUATION/4) * PIXEL
- self.blocks = [Block(can, a, a), Block(can, a, a + STEP)]
- def move(self, path):
- """элементарный шаг, состоящий из помещения хвоста змеи в первое положение"""
- a = (self.blocks[-1].x + STEP * path[0]) % WD
- b = (self.blocks[-1].y + STEP * path[1]) % HT
- if a == self.can.obstacle.x and b == self.can.obstacle.y: # Проверка на еду
- self.can.score.increment()
- self.can.obstacle.delete()
- self.blocks.append(Block(self.can, a, b))
- self.can.obstacle = Obstacle(self.can)
- elif [a, b] in [[block.x, block.y] for block in self.blocks]: # Проверка на врезание в тело
- self.can.clean()
- else:
- self.blocks[0].modify(a, b)
- self.blocks = self.blocks[1:] + [self.blocks[0]]
- class Movement:
- """объект, который вводит змею в постоянное состояние движения в заданном направлении"""
- def __init__(self, can, direction):
- self.flag = 1
- self.can = can
- self.direction = direction
- def begin(self):
- """Начать движение "Вечное""""
- if self.flag > 0:
- self.can.snake.move(DIRECTIONS[self.direction])
- self.can.after(REFRESH_TIME, self.begin)
- def stop(self):
- """Остановление"""
- self.flag = 0
- root = Tk()
- root.title("Змейка ТОП")
- game = Master(root)
- game.grid(column=1, row=0, rowspan=3)
- root.bind("<Key>", game.redirect)
- buttons = Frame(root, width=35, height=3*HT/5)
- Button(buttons, text='Старт', command=game.start).grid()
- Button(buttons, text='Очистка', command=game.clean).grid()
- Button(buttons, text='Выход', command=root.destroy).grid()
- buttons.grid(column=0, row=0)
- scoreboard = Frame(root, width=35, height=2*HT/5)
- Label(scoreboard, text='Счёт').grid()
- Label(scoreboard, textvariable=game.score.counter).grid()
- Label(scoreboard, text='Лучший счёт').grid()
- Label(scoreboard, textvariable=game.score.maximum).grid()
- scoreboard.grid(column=0, row=2)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement