commit 8d3fce2829fbf043747770f52b7b76fa84e82efc Author: Gergely Polonkai Date: Thu Oct 29 17:04:25 2015 +0100 Table and Field classes diff --git a/battleship.py b/battleship.py new file mode 100644 index 0000000..ae8b54d --- /dev/null +++ b/battleship.py @@ -0,0 +1,189 @@ +from enum import Enum + +class FieldType(Enum): + empty = 1 + water = 2 + ship = 3 + +class Field(object): + def __init__(self, fieldtype, fixed=False): + if not isinstance(fieldtype, FieldType): + raise AttributeError("fieldtype must be a FieldType instance") + + self.fixed = fixed + self.hidden_type = fieldtype + self.player_type = fieldtype if fixed else FieldType.empty + + def is_ship(self, from_fixed=False): + return ((self.fixed or from_fixed) \ + and self.hidden_type == FieldType.ship) \ + or self.player_type == FieldType.ship + + def is_water(self, from_fixed=False): + return ((self.fixed or from_fixed) \ + and self.hidden_type == FieldType.water) \ + or self.player_type == FieldType.water + + def __repr__(self): + return '<{} field>'.format(self.hidden_type.name) + +class Table(object): + def __init__(self, width, height): + self.__fields = [] + self.width = width + self.height = height + + for x in range(1, width + 1): + self.__fields.append([]) + + for y in range(1, height + 1): + self.__fields[x - 1].append(Field(FieldType.water)) + + def __border_row(self): + ret = '+' + + for i in range(0, self.width): + ret += '--+' + + ret += "\n" + + return ret + + def __field(self, row, col): + if row < 0 \ + or row >= self.height \ + or col < 0 \ + or col >= self.width: + return None + + return self.__fields[row][col] + + def col_ship_count(self, col): + return len([r[col] for r in self.__fields \ + if r[col].hidden_type == FieldType.ship]) + + def row_ship_count(self, row): + return len([r for r in self.__fields[row] \ + if r.hidden_type == FieldType.ship]) + + def __neighbours(self, row, col): + return ( + self.__field(row - 2, col -1), + self.__field(row - 1, col), + self.__field(row, col - 1), + self.__field(row - 1, col - 2) + ) + + def __str__(self): + ret = self.__border_row() + + for row in range(0, self.height): + ret += '|' + + for col in range(0, self.width): + field = self.__fields[row][col] + + typ = field.hidden_type if field.fixed else field.player_type + + if typ == FieldType.empty: + ret += ' ' + elif typ == FieldType.water: + ret += '~~' + elif typ == FieldType.ship: + # Check neighbours + + # upper, right, lower, left + neighbours = self.__neighbours(row + 1, col + 1) + + all_waters = True + + for n in neighbours: + all_waters = all_waters and \ + (n is None \ + or n.is_water(from_fixed=field.fixed)) + + neighs = [False if n is None \ + else n.is_ship(from_fixed=field.fixed) \ + for n in neighbours] + + # Ship above and below or left and right + if (neighs[0] and neighs[2]) \ + or (neighs[1] and neighs[3]): + ret += 'XX' + elif neighs[0]: # Ship above, not below + ret += 'vv' + elif neighs[2]: # Ship below, not above + ret += '^^' + elif neighs[1]: # Ship right, not left + ret += ' <' + elif neighs[3]: # Ship on left, not right + ret += '> ' + elif all_waters: + ret += 'oo' + else: + ret += '??' + + ret += '|' + + ret += " {}\n".format(self.row_ship_count(row)) + ret += self.__border_row() + + for col in range(0, self.width): + ret += " {:<2}".format(self.col_ship_count(col)) + + ret += "\n" + + return ret + + def add_ship(self, start_row, start_col, length, vertical): + row, col = start_row - 1, start_col - 1 + + for i in range(0, length): + self.__fields[row][col].hidden_type = FieldType.ship + + if vertical: + row += 1 + else: + col += 1 + + def clean(self): + for row in self.__fields: + for field in row: + field.hidden_type = FieldType.water + field.player_type = FieldType.empty + field.fixed = False + + def reveal(self, row, col): + self.__fields[row - 1][col - 1].fixed = True + + def reveal_all(self): + for row in self.__fields: + for field in row: + field.fixed = True + + @property + def solved(self): + # Check if all fileds have been marked + for row in self.__fields: + for field in row: + if field.player_type == FieldType.empty: + return False + + # TODO: Check if marked ships are placed sanely + # TODO: Check if side-numbers equal the number of marked ship-parts + + return True + +t = Table(6, 6) +t.add_ship(1, 3, 1, False) +t.add_ship(2, 5, 2, False) +t.add_ship(3, 1, 3, False) +t.add_ship(5, 1, 1, False) +t.add_ship(5, 3, 2, True) +t.add_ship(6, 5, 1, False) +t.reveal(1, 2) +t.reveal(3, 3) +t.reveal(5, 1) +t.reveal(5, 2) + +print(str(t))