Working on the code
This commit is contained in:
parent
471a1e0141
commit
9ad99579b6
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from snake.map import Map
|
||||
from snake.game import Game, PositionPlayer
|
||||
from snake.player import Player, Direction, ConstantPlayer, KeyboardPlayer
|
||||
from tron.map import Map
|
||||
from tron.game import Game, PositionPlayer
|
||||
from tron.player import Player, Direction, ConstantPlayer, KeyboardPlayer
|
||||
|
||||
def main():
|
||||
width = 40
|
||||
|
|
7
play.py
7
play.py
|
@ -20,10 +20,15 @@ def main():
|
|||
PositionPlayer(2, ConstantPlayer(Direction.LEFT), [width - 1, height - 1]),
|
||||
])
|
||||
|
||||
window = Window(game, 20)
|
||||
window = Window(game, 10)
|
||||
|
||||
game.main_loop(window)
|
||||
|
||||
if game.winner is None:
|
||||
print("It's a draw!")
|
||||
else:
|
||||
print('Player {} wins!'.format(game.winner))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
|
58
tron/game.py
58
tron/game.py
|
@ -7,7 +7,14 @@ from enum import Enum
|
|||
|
||||
from tron.map import Map
|
||||
|
||||
class Winner(Enum):
|
||||
PLAYER_ONE = 1
|
||||
PLAYER_TWO = 2
|
||||
|
||||
class Case(Enum):
|
||||
"""
|
||||
The different type of elements that can be in a map.
|
||||
"""
|
||||
EMPTY = 0
|
||||
WALL = -1
|
||||
PLAYER_ONE_BODY = 1
|
||||
|
@ -16,6 +23,9 @@ class Case(Enum):
|
|||
PLAYER_TWO_HEAD = 4
|
||||
|
||||
def color(self):
|
||||
"""
|
||||
Converts an element of a map to a nice color.
|
||||
"""
|
||||
if self == Case.EMPTY:
|
||||
return (255, 255, 255)
|
||||
elif self == Case.WALL:
|
||||
|
@ -32,6 +42,10 @@ class Case(Enum):
|
|||
return None
|
||||
|
||||
class PositionPlayer:
|
||||
"""
|
||||
A container to store a player with is id, position and boolean indicating
|
||||
whether it's still alive or not.
|
||||
"""
|
||||
def __init__(self, id, player, position):
|
||||
self.id = id
|
||||
self.player = player
|
||||
|
@ -39,17 +53,36 @@ class PositionPlayer:
|
|||
self.alive = True
|
||||
|
||||
def body(self):
|
||||
"""
|
||||
Returns the body type of the PP depending on its id.
|
||||
"""
|
||||
if self.id == 1:
|
||||
return Case.PLAYER_ONE_BODY
|
||||
elif self.id == 2:
|
||||
return Case.PLAYER_TWO_BODY
|
||||
|
||||
def head(self):
|
||||
"""
|
||||
Returns the head type of the PP depending of its id.
|
||||
"""
|
||||
if self.id == 1:
|
||||
return Case.PLAYER_ONE_HEAD
|
||||
elif self.id == 2:
|
||||
return Case.PLAYER_TWO_HEAD
|
||||
|
||||
class HistoryElement:
|
||||
"""
|
||||
An element from an history.
|
||||
|
||||
It contains the map, but also the direction of each player during the frame.
|
||||
The directions of the players will be None at the first frame.
|
||||
"""
|
||||
def __init__(self, mmap, player_one_direction, player_two_direction):
|
||||
self.map = mmap
|
||||
self.player_one_direction = player_one_direction
|
||||
self.player_two_direction = player_two_direction
|
||||
|
||||
|
||||
class Game:
|
||||
"""
|
||||
This class contains the map of the game, and the players.
|
||||
|
@ -65,14 +98,19 @@ class Game:
|
|||
"""
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.history = [Map(width, height, Case.EMPTY, Case.WALL)]
|
||||
mmap = Map(width, height, Case.EMPTY, Case.WALL)
|
||||
self.history = [HistoryElement(mmap, None, None)]
|
||||
self.pps = pps
|
||||
self.winner = None
|
||||
|
||||
for pp in self.pps:
|
||||
self.map()[pp.position[0], pp.position[1]] = pp.head()
|
||||
|
||||
def map(self):
|
||||
return self.history[-1]
|
||||
"""
|
||||
Returns the current map, the last map in the history.
|
||||
"""
|
||||
return self.history[-1].map
|
||||
|
||||
def next_frame(self, window = None):
|
||||
"""
|
||||
|
@ -84,8 +122,6 @@ class Game:
|
|||
that is already occupied or that is outside of the map, the players
|
||||
dies.
|
||||
"""
|
||||
# Clone map
|
||||
self.history.append(self.map().clone())
|
||||
|
||||
# Set previous heads to body
|
||||
for pp in self.pps:
|
||||
|
@ -103,9 +139,12 @@ class Game:
|
|||
for pp in self.pps:
|
||||
pp.player.manage_event(event)
|
||||
|
||||
player_directions = []
|
||||
|
||||
for pp in self.pps:
|
||||
|
||||
pp.position = pp.player.next_position(pp.position, self)
|
||||
(pp.position, direction) = pp.player.next_position_and_direction(pp.position, self)
|
||||
player_directions.append(direction)
|
||||
|
||||
# Check boundaries
|
||||
if pp.position[0] < 0 or pp.position[1] < 0 or \
|
||||
|
@ -120,6 +159,10 @@ class Game:
|
|||
else:
|
||||
self.map()[pp.position[0], pp.position[1]] = pp.head()
|
||||
|
||||
# Append to history
|
||||
map_clone = self.map().clone()
|
||||
self.history.append(HistoryElement(map_clone, player_directions[0], player_directions[1]))
|
||||
|
||||
|
||||
def main_loop(self, window = None):
|
||||
"""
|
||||
|
@ -151,10 +194,7 @@ class Game:
|
|||
|
||||
if alive_count <= 1:
|
||||
if alive_count == 1:
|
||||
print('Player {} win!'.format(alive + 1))
|
||||
else:
|
||||
print('It\'s a draw!')
|
||||
|
||||
self.winner = alive + 1
|
||||
break
|
||||
|
||||
if window:
|
||||
|
|
32
tron/map.py
32
tron/map.py
|
@ -18,7 +18,9 @@ class Map:
|
|||
"""
|
||||
Creates a new map from its width and its height.
|
||||
|
||||
The matrix is initialized with Nones
|
||||
The map will contain (height + 2) * (width + 2) tiles, by having a
|
||||
border. The matrix is initialized with `empty` in the inside and
|
||||
`wall` on the borders.
|
||||
"""
|
||||
self.width = w
|
||||
self.height = h
|
||||
|
@ -28,13 +30,23 @@ class Map:
|
|||
"""
|
||||
Creates a clone of the map.
|
||||
"""
|
||||
map = Map(self.width, self.height, 0, 0)
|
||||
map._data = np.copy(self._data)
|
||||
return map
|
||||
clone = Map(self.width, self.height, 0, 0)
|
||||
clone._data = np.copy(self._data)
|
||||
return clone
|
||||
|
||||
def convert(self, converter):
|
||||
map = Map(self.width, self.height, 0, 0)
|
||||
map._data = np.fromiter((converter.convert(xi) for xi in self._data), self._data.dtype)
|
||||
"""
|
||||
Converts a map by applying a function to each element.
|
||||
"""
|
||||
converted = Map(self.width, self.height, 0, 0)
|
||||
converted._data = np.array([[converter(self._data[i][j]) for i in range(self.height + 2)] for j in range(self.width + 2)])
|
||||
return converted
|
||||
|
||||
def array(self):
|
||||
"""
|
||||
Returns the inner array of the map.
|
||||
"""
|
||||
return self._data
|
||||
|
||||
def __getitem__(self, index):
|
||||
(i, j) = index
|
||||
|
@ -44,11 +56,3 @@ class Map:
|
|||
(i, j) = position
|
||||
self._data[i+1][j+1] = other
|
||||
|
||||
class Converter:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def convert(self, x):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -24,16 +24,16 @@ class Player:
|
|||
def __init__(self):
|
||||
pass
|
||||
|
||||
def next_position(self, current_position, game):
|
||||
def next_position_and_direction(self, current_position, game):
|
||||
direction = self.action(game)
|
||||
if direction == Direction.UP:
|
||||
return (current_position[0] - 1, current_position[1])
|
||||
return ((current_position[0] - 1, current_position[1]), direction)
|
||||
if direction == Direction.RIGHT:
|
||||
return (current_position[0], current_position[1] + 1)
|
||||
return ((current_position[0], current_position[1] + 1), direction)
|
||||
if direction == Direction.DOWN:
|
||||
return (current_position[0] + 1, current_position[1])
|
||||
return ((current_position[0] + 1, current_position[1]), direction)
|
||||
if direction == Direction.LEFT:
|
||||
return (current_position[0], current_position[1] - 1)
|
||||
return ((current_position[0], current_position[1] - 1), direction)
|
||||
|
||||
def action(self, game):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import unittest
|
||||
|
||||
from tron.map import Map
|
||||
|
||||
class TestMap(unittest.TestCase):
|
||||
def test_constructor(self):
|
||||
mymap = Map(3, 3, 0, -1)
|
||||
for i in range(5):
|
||||
self.assertEqual(mymap._data[0][i], -1)
|
||||
self.assertEqual(mymap._data[i][0], -1)
|
||||
self.assertEqual(mymap._data[4][i], -1)
|
||||
self.assertEqual(mymap._data[i][4], -1)
|
||||
for i in range(1, 4):
|
||||
for j in range(1, 4):
|
||||
self.assertEqual(mymap._data[i][j], 0)
|
||||
|
||||
def test_clone(self):
|
||||
original = Map(3, 3, 0, -1)
|
||||
mymap = Map(3, 3, 0, -1)
|
||||
mymap2 = mymap.clone()
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
self.assertEqual(mymap._data[i][j], mymap2._data[i][j])
|
||||
mymap._data[i][j] = 3
|
||||
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
self.assertEqual(original._data[i][j], mymap2._data[i][j])
|
||||
|
||||
def test_convert(self):
|
||||
def increment(x):
|
||||
return x + 1
|
||||
|
||||
original = Map(3, 3, 0, -1)
|
||||
converted = original.convert(increment)
|
||||
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
self.assertEqual(converted._data[i][j], original._data[i][j] + 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue