hier mal ein Snake-Game - hatte ich schon im Showcase. Man sollte doch hier besser die Logik von der UI trennen. Bedeutet in diesem Script wäre die Trennung nicht gegeben und die mittels "__iter__" oder "___getitem___" besser - oder ?
Code: Alles auswählen
#! /usr/bin/env python
# -*- coding: utf-8
FIELD_WIDTH = 400
FIELD_HEIGHT = 400
import Tkinter as tk
from functools import partial
import random
class Snake(object):
def __init__(self, field_width, field_height, number_of_tails,
tails_width):
self.field_width = field_width
self.field_height = field_height
self.number_of_tails = number_of_tails
self.tails_width = tails_width
self.x = 0
self.y = 0
self.tails = list()
self.food = list()
self.positions = list()
self.alive = True
self.head = (self.field_width / 2, self.field_height / 2)
for tail in xrange(self.number_of_tails):
x, y = self.head
self.tails.append((x, y))
self.food = self.get_food()
def set_move_direction(self, x, y):
if self.x == y:
self.x, self.y = x, y
elif self.y == x:
self.x, self.y = x, y
def set_position(self):
head_x, head_y = self.head
new_head_x, new_head_y = head_x + self.x, head_y + self.y
self.head = (new_head_x, new_head_y)
if (len(self.tails) > self.number_of_tails
and (new_head_x, new_head_y) in self.tails
or new_head_x == -self.tails_width
or new_head_x == self.field_width
or new_head_y == -self.tails_width
or new_head_y == self.field_height):
self.alive = False
elif self.head == self.food:
for tail in xrange(self.number_of_tails):
self.tails.append(self.head)
self.food = self.get_food()
self.tails.pop()
self.tails.insert(0, self.head)
def get_food(self):
food_positions = list()
for x in xrange(self.tails_width, self.field_width, self.tails_width):
for y in xrange(self.tails_width, self.field_height,
self.tails_width):
if (x, y) not in self.tails:
food_positions.append((x, y))
return random.choice(food_positions)
class SnakeGui(tk.Canvas):
SPEED = 50
FIELD_COLOR = "lightgreen"
NUMBER_OF_TAILS = 5
TAILS_WIDTH = 5
TAILS_COLOR = "green"
FOOD_COLOR = "red"
SNAKE_UP = "<KeyPress-Up>"
SNAKE_DOWN = "<KeyPress-Down>"
SNAKE_RIGHT = "<KeyPress-Right>"
SNAKE_LEFT = "<KeyPress-Left>"
def __init__(self, root, field_width, field_height):
tk.Canvas.__init__(self, root, width = field_width,
height = field_height, bg = self.FIELD_COLOR)
self.root = root
self.field_width = field_width
self.field_height = field_height
self.control = ((self.SNAKE_UP, 0, -self.TAILS_WIDTH),
(self.SNAKE_DOWN, 0, self.TAILS_WIDTH),
(self.SNAKE_RIGHT, self.TAILS_WIDTH, 0),
(self.SNAKE_LEFT, -self.TAILS_WIDTH, 0))
for button, x, y in self.control:
self.root.bind(button, partial(self.move_snake, x, y))
self.after_id = None
self.start_game()
def start_game(self):
self.snake = Snake(self.field_width, self.field_height,
self.NUMBER_OF_TAILS, self.TAILS_WIDTH)
if self.after_id:
self.after_cancel(self.after_id)
self.run()
def move_snake(self, x, y, event):
self.snake.set_move_direction(x, y)
def run(self):
if self.snake.alive:
self.delete("snake_tail", "snake_food")
self.snake.set_position()
for x, y in self.snake.tails:
self.create_oval(x, y, x + self.TAILS_WIDTH, y
+ self.TAILS_WIDTH,tag="snake_tail",
fill=self.TAILS_COLOR)
x, y = self.snake.food
self.create_oval(x, y, x + self.TAILS_WIDTH, y + self.TAILS_WIDTH,
fill=self.FOOD_COLOR, tag="snake_food")
self.after_id = self.after(self.SPEED, self.run)
else:
self.delete("snake_food", "snake_tail")
self.start_game()
def main():
root = tk.Tk()
gui = SnakeGui(root, FIELD_WIDTH, FIELD_HEIGHT)
gui.pack()
root.mainloop()
if __name__ == "__main__": main()