Христина обнови решението на 14.05.2013 15:24 (преди над 11 години)
+class Death(Exception):
+ pass
+
+
+class Vec2D():
+ def __init__(self, x, y):
+ self.vector = (x, y)
+
+ def __add__(self, other):
+ return Vec2D(self.vector[0] + other.vector[0],
+ self.vector[1] + other.vector[1])
+
+ def __sub__(self, other):
+ return Vec2D(self.vector[0] - other.vector[0],
+ self.vector[1] - other.vector[1])
+
+ def __neg__(self):
+ return Vec2D(-self.vector[0], -self.vector[1])
+
+ def __mul__(self, scalar):
+ return Vec2D(scalar * self.vector[0], scalar * self.vector[1])
+
+ def __rmul__(self, scalar):
+ return Vec2D(scalar * self.vector[0], scalar * self.vector[1])
+
+ def __getitem__(self, key):
+ return self.vector[key]
+
+
+class Cell:
+ FOOD = 'Food'
+ HEAD = 'Head'
+ BODY_PART = 'Body part'
+ EMPTY = None
+
+ def __init__(self, contents=None):
+ if contents and not isinstance(contents, WorldObject):
+ raise TypeError
+ self.contents = contents
+
+ def is_empty(self):
+ return not self.contents
+
+ def place_python_part(self, coords, part):
+ if self.contains == self.HEAD or self.contains == self.BODY_PART:
+ raise Death
+ elif not self.is_empty() and part.head:
+ part.energy += self.contents.energy
+ self.contents = part
+ part.set_coords(coords)
+
+ def remove_python_part(self, part):
+ part.unset_coords()
+ self.contents = None
+
+ def contains(self):
+ if self.contents:
+ if isinstance(self.contents, Food):
+ return self.FOOD
+ elif isinstance(self.contents, PythonHead):
+ return self.HEAD
+ else:
+ return self.BODY_PART
+
+ return self.EMPTY
+
+
+class PositiveIndexList:
+ def __init__(self, list_):
+ self.list_ = list_
+
+ def __getitem__(self, key):
+ if key < 0:
+ raise IndexError
+
+ return self.list_.__getitem__(key)
+
+ def __setitem__(self, key, value):
+ if key < 0:
+ raise IndexError
+ self.list_.__setitem__(key, value)
+
+
+class World:
+ CELL_TO_STR = {Cell.FOOD: ':3', Cell.HEAD: '@@',
+ Cell.BODY_PART: '##', Cell.EMPTY: '..'}
+
+ def __init__(self, width):
+ self.width = width
+ self.world = [[Cell() for j in range(width)] for i in range(width)]
+
+ def __getitem__(self, key):
+ if key < 0:
+ raise IndexError
+
+ return PositiveIndexList(self.world[key])
+
+ def __len__(self):
+ return self.width
+
+ def __str__(self):
+ world_to_str = ''
+ for i in range(len(self.world)):
+ for cell in self.world[i]:
+ world_to_str += self.CELL_TO_STR[cell.contains()]
+ world_to_str += '\n'
+
+ return world_to_str
+
+ def fill_cell(self, coords, part):
+ self.world[coords[0]][coords[1]].place_python_part(coords, part)
+
+ def empty_cell(self, part):
+ self.world[part.coords[0]][part.coords[1]].remove_python_part(part)
+
+ def is_cell_empty(self, coords):
+ return self.world[coords[0]][coords[1]].is_empty()
+
+ def out_of_range(self, coords):
+ return any([coord > self.width - 1 or coord < 0 for coord in coords])
+
+
+class WorldObject:
+ def __init__(self):
+ pass
+
+
+class Food(WorldObject):
+ def __init__(self, energy):
+ self.energy = energy
+
+
+class PythonPart(WorldObject):
+ def __init__(self):
+ self.coords = Vec2D(None, None)
+ self.head = False
+
+ def set_coords(self, coords):
+ self.coords = coords
+
+ def unset_coords(self):
+ self.coords = Vec2D(None, None)
+
+
+class PythonHead(PythonPart):
+ def __init__(self):
+ super(PythonHead, self).__init__()
+ self.head = True
+ self.energy = 0
+
+
+class Python:
+ RIGHT = Vec2D(0, 1)
+ DOWN = Vec2D(1, 0)
+ LEFT = -RIGHT
+ UP = -DOWN
+
+ def __init__(self, world, coords, size, direction):
+ self.size = size
+ self.world = world
+ self.direction = direction
+ self._place_head(coords)
+ self.body = list()
+
+ for part_index in range(self.size, 0, -1):
+ next_part_coords = coords - part_index * self.direction
+ if self.world.out_of_range(next_part_coords):
+ raise Death
+
+ self._place_body_part(self.size - part_index, next_part_coords)
+
+ def _place_head(self, coords):
+ self.py_head = PythonHead()
+ self.world.fill_cell(coords, self.py_head)
+
+ def _place_body_part(self, index, coords):
+ self.body.append(PythonPart())
+ self.world.fill_cell(coords, self.body[index])
+
+ def move(self, direction):
+ new_coords = self.py_head.coords + direction
+
+ if (self.world.out_of_range(new_coords) or not
+ self.world.is_cell_empty(new_coords)):
+ raise Death
+
+ if self.direction == -direction:
+ raise ValueError
+
+ if self.world.is_cell_empty(new_coords):
+ self.world.empty_cell(self.body.pop(False))
+
+ self._place_body_part(self.size - 1, self.py_head.coords)
+ self._place_head(new_coords)
+ self.direction = direction