Николай обнови решението на 15.05.2013 03:44 (преди над 11 години)
+from collections import deque
+
+
+class StrictList:
+
+ def __init__(self, contents=[]):
+ self.storage = list(contents)
+
+ def __getitem__(self, index):
+ if index < 0 or index >= len(self.storage):
+ raise IndexError
+ else:
+ return self.storage[index]
+
+ def __setitem__(self, index, value):
+ if index < 0 or index >= len(self.storage):
+ raise IndexError
+ else:
+ self.storage[index] = value
+
+ def __len__(self):
+ return len(self.storage)
+
+ def append(self, value):
+ self.storage.append(value)
+
+
+class World:
+
+ def __init__(self, width):
+ self.width = width
+
+ self.board = StrictList()
+ for x in range(0, self.width):
+ self.board.append(StrictList())
+ for y in range(0, self.width):
+ self.board[x].append(Cell())
+
+ def __len__(self):
+ return self.width
+
+ def __getitem__(self, x):
+ if x < 0 or x > self.width:
+ raise IndexError
+
+ return self.board[x]
+
+ def are_valid_coords(self, x, y):
+ return x >= 0 and x < self.width and y >= 0 and y < self.width
+
+
+class Cell:
+
+ def __init__(self, contents=None):
+ if contents is None or isinstance(contents, WordObject):
+ self.contents = contents
+ else:
+ raise TypeError
+
+ def is_empty(self):
+ return self.contents is None
+
+
+class WordObject:
+ pass
+
+
+class Food(WordObject):
+
+ def __init__(self, energy=0):
+ self.energy = energy
+
+
+class PythonPart(WordObject):
+ pass
+
+
+class PythonHead(PythonPart):
+ pass
+
+
+class Death(Exception):
+ pass
+
+
+class Vec2D:
+
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def __eq__(self, other):
+ return self.x == other.x and self.y == other.y
+
+ def __neg__(self):
+ return Vec2D(-self.x, -self.y)
+
+ def __add__(self, other):
+ return Vec2D(self.x + other.x, self.y + other.y)
+
+ def __sub__(self, other):
+ return Vec2D(self.x - other.x, self.y - other.y)
+
+ def __mul__(self, number):
+ return Vec2D(self.x * number, self.y * number)
+
+ def __iter__(self):
+ yield self.x
+ yield self.y
+
+ def __str__(self):
+ return "({}, {}".format(self.x, self.y)
+
+
+class Python:
+
+ LEFT = Vec2D(-1, 0)
+ RIGHT = Vec2D(+1, 0)
+ UP = Vec2D(0, +1)
+ DOWN = Vec2D(0, -1)
+
+ @staticmethod
+ def __is_oposite_direction(dir1, dir2):
+ return dir1 + dir2 == Vec2D(0, 0)
+
+ def __init__(self, world, coords, size, direction):
+ self.world = world
+ self.size = size
+ self.energy = 0
+ self.body = PythonBody(world, coords, size, direction)
+
+ def move_body(self, direction, nextx, nexty):
+ cell_contents = self.world[nextx][nexty].contents
+ if isinstance(cell_contents, Food):
+ self.energy += cell_contents.energy
+ else:
+ self.body.remove_tail()
+ self.size -= 1
+
+ self.body.move_head(Vec2D(nextx, nexty))
+ self.size += 1
+ self.body.head_direction = direction
+
+ def move(self, direction):
+ if Python.__is_oposite_direction(direction, self.body.head_direction):
+ raise ValueError
+
+ nextx, nexty = self.body.head_position + direction
+ if not self.world.are_valid_coords(nextx, nexty):
+ raise Death
+
+ if isinstance(self.world[nextx][nexty].contents, PythonPart):
+ raise Death
+
+ self.move_body(direction, nextx, nexty)
+
+
+class PythonBody:
+
+ def __init__(self, world, coords, size, direction):
+ self.__head_direction = direction
+ self.world = world
+ self.body = deque([coords - direction * x for x in range(size + 1)])
+ self.__fill_world_with_body()
+
+ def __fill_world_with_body(self):
+ for pos in self.body:
+ x, y = pos
+ self.world[x][y].contents = PythonPart()
+
+ head_x, head_y = self.body[0]
+ self.world[head_x][head_y].contents = PythonHead()
+
+ @property
+ def head_position(self):
+ return self.body[0]
+
+ def move_head(self, new_head_coords):
+ old_head_x, old_head_y = self.head_position
+ new_head_x, new_head_y = new_head_coords
+
+ self.world[old_head_x][old_head_y].contents = PythonPart()
+ self.world[new_head_x][new_head_y].contents = PythonHead()
+
+ self.body.appendleft(new_head_coords)
+
+ @property
+ def head_direction(self):
+ return self.__head_direction
+
+ @head_direction.setter
+ def head_direction(self, value):
+ self.__head_direction = value
+
+ def remove_tail(self):
+ old_tail_x, old_tail_y = self.body.pop()
+ self.world[old_tail_x][old_tail_y] = Cell()