Георги обнови решението на 13.05.2013 16:17 (преди над 11 години)
+import copy
+
+
+class Vec2D:
+ def __init__(self, x_coord=0, y_coord=0):
+ self.x = x_coord
+ self.y = y_coord
+
+ def __add__(self, other):
+ if type(other) is not Vec2D:
+ raise TypeError("can only add Vec2D (not {}) to Vec2D".
+ format(type(other)))
+ return Vec2D(self.x + other.x, self.y + other.y)
+
+ def __iadd__(self, other):
+ if type(other) is not Vec2D:
+ raise TypeError("can only add Vec2D (not {}) to Vec2D".
+ format(type(other)))
+ return Vec2D(self.x + other.x, self.y + other.y)
+
+ def __sub__(self, other):
+ if type(other) is not Vec2D:
+ raise TypeError("can only subtract Vec2D (not {}) from Vec2D".
+ format(type(other)))
+ return Vec2D(self.x - other.x, self.y - other.y)
+
+ def __isub__(self, other):
+ if type(other) is not Vec2D:
+ raise TypeError("can only subtract Vec2D (not {}) from Vec2D".
+ format(type(other)))
+ return Vec2D(self.x - other.x, self.y - other.y)
+
+ def __mul__(self, scalar):
+ if type(scalar) is not int:
+ raise TypeError("can't multiply Vec2D by non-int of type {}".
+ format(type(scalar)))
+ return Vec2D(self.x * scalar, self.y * scalar)
+
+ def __rmul__(self, scalar):
+ if type(scalar) is not int:
+ raise TypeError("can't multiply Vec2D by non-int of type {}".
+ format(type(scalar)))
+ return Vec2D(self.x * scalar, self.y * scalar)
+
+ def __imul__(self, scalar):
+ if type(scalar) is not int:
+ raise TypeError("can't multiply Vec2D by non-int of type {}".
+ format(type(scalar)))
+ return Vec2D(self.x * scalar, self.y * scalar)
+
+ def __neg__(self):
+ return Vec2D(-self.x, -self.y)
+
+ def __str__(self):
+ return "Vec2D({}, {})".format(self.x, self.y)
+
+ def __eq__(self, other):
+ return self.x == other.x and self.y == other.y
+
+ def __iter__(self):
+ yield self.x
+ yield self.y
+
+
+class Array:
+ def __init__(self, size, default_values=None):
+ self.size = size
+ self.data = [copy.deepcopy(default_values)
+ for array_index in range(0, self.size)]
+
+ def __getitem__(self, key):
+ if key < 0 or key > self.size - 1:
+ raise IndexError("Array index out of range")
+ return self.data[key]
+
+ def __setitem__(self, key, value):
+ if key < 0 or key > self.size - 1:
+ raise IndexError("Array index out of range")
+ if type(self.data[key]) is Cell:
+ self.data[key].contents = value
+ else:
+ self.data[key] = value
+
+
+class Death(Exception):
+ pass
+
+
+class WorldObject:
+ def __init__(self, position=Vec2D(0, 0)):
+ self.position = position
+ self.representation = '..'
+
+ def __str__(self):
+ return self.representation
+
+
+class Food(WorldObject):
+ def __init__(self, energy, position=Vec2D(0, 0)):
+ WorldObject.__init__(self, position)
+ self.energy = energy
+ self.representation = ':3'
+
+
+class PythonPart(WorldObject):
+ def __init__(self, part_type, position, direction):
+ WorldObject.__init__(self, position)
+ self.direction = direction
+ self.type = part_type
+ self.representation = '##'
+
+ def move(self):
+ self.position += self.direction
+
+
+class PythonHead(PythonPart):
+ def __init__(self, position, direction):
+ PythonPart.__init__(self, "head", position, direction)
+ self.representation = '@@'
+
+
+class Cell:
+ def __init__(self, contents=WorldObject()):
+ if not isinstance(contents, WorldObject):
+ raise TypeError
+ self.contents = contents
+
+ def __str__(self):
+ return self.contents.__str__()
+
+ def is_empty(self):
+ return type(self.contents) is WorldObject
+
+
+class World:
+ def __init__(self, width):
+ self.size = width
+ self.matrix = Array(self.size)
+ for row in range(0, self.size):
+ self.matrix[row] = Array(self.size, Cell())
+
+ def __len__(self):
+ return self.size
+
+ def __getitem__(self, key):
+ return self.matrix[key]
+
+ def __str__(self):
+ representation = ""
+ for row in range(0, self.size):
+ for column in range(0, self.size):
+ representation += self.matrix[row][column].__str__()
+ representation += "\n"
+
+ return representation
+
+
+class Python:
+ LEFT = Vec2D(0, -1)
+ RIGHT = Vec2D(0, 1)
+ UP = Vec2D(-1, 0)
+ DOWN = Vec2D(1, 0)
+
+ def __init__(self, world, coords, size, direction):
+ self.world = world
+ self.size = size
+ self.position = coords
+ self.direction = direction
+ self.energy = 0
+
+ self.head = PythonHead(self.position, self.direction)
+ self.body = [PythonPart("tail", self.position + (-self.direction) *
+ part_position, self.direction) for part_position in
+ range(1, self.size + 1)]
+
+ self.draw_on_world()
+
+ def move(self, direction):
+ if self.direction == -direction:
+ raise ValueError("can't move backwards")
+
+ self.direction = direction
+ self.position += self.direction
+ if not self.is_in_world():
+ raise Death
+
+ self._calculate_directions()
+ self._move_python_parts()
+ self.draw_on_world()
+
+ def _calculate_directions(self):
+ for python_part in self.body[:0:-1]:
+ python_part.direction = self.body[self.body.index(python_part) -
+ 1].direction
+ self.body[0].direction = self.head.direction
+ self.head.direction = self.direction
+
+ def _move_python_parts(self):
+ self.head.move()
+ if self.world[self.position.x][self.position.y].is_empty():
+ for python_part in self.body:
+ if self.body.index(python_part) == len(self.body) - 1:
+ (self.world[python_part.position.x]
+ [python_part.position.y]) = WorldObject()
+ python_part.move()
+ elif (type(self.world[self.position.x][self.position.y].contents) is
+ Food):
+ self.energy += (self.world[self.position.x][self.position.y].
+ contents.energy)
+ self.body.insert(0, PythonPart("tail", self.position -
+ self.direction, self.body[0].direction))
+ self.size += 1
+ else:
+ raise Death
+
+ def draw_on_world(self):
+ self.world[self.head.position.x][self.head.position.y] = self.head
+ for python_part in self.body:
+ self.world[python_part.position.x][python_part.position.y] = \
+ python_part
+
+ def is_in_world(self):
+ if (self.position.x < 0 or self.position.x > self.world.size - 1 or
+ self.position.y < 0 or self.position.y > self.world.size - 1):
+ return False
+ return True