queen_attack.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
BOARD_SIZE = 8


class Queen:
    def __init__(self, pos):
        if not all(0 <= dim < BOARD_SIZE for dim in pos):
            raise ValueError('Coordinate out of range')

        self.row, self.col = pos

    def __eq__(self, other):
        """
        Check whether equal to another queen position
        """
        return self.row == other.row and self.col == other.col

    @property
    def main_diagonal(self):
        """
        Get representation of main diagonal
        (top left to bottom right)
        Two queens are on same main diagonal if row - col difference is the same
        """
        return self.row - self.col

    @property
    def anti_diagonal(self):
        """
        Get representation of anti diagonal
        (top right to bottom left)
        Two queens are on same anti diagonal if row + col sum is the same
        """
        return self.row + self.col

    def on_same_row_as(self, other):
        """Is this in same row as another queen?"""
        return self.row == other.row

    def on_same_col_as(self, other):
        """Is this in same col as another queen?"""
        return self.col == other.col

    def on_same_diagonal_as(self, other):
        """Is this in on same diagonal as another queen?"""
        return ((self.main_diagonal == other.main_diagonal) or
                (self.anti_diagonal == other.anti_diagonal))

    def in_line_with(self, other):
        return (
            self.on_same_row_as(other) or
            self.on_same_col_as(other) or
            self.on_same_diagonal_as(other)
        )


class ChessBoard:
    """Representation of a chess board with just two queens"""

    def __init__(self, white, black):
        """Initialize with (row, col) positions of white and black queens"""
        if white == black:
            raise ValueError('Queens cannot be on same square')

        self._white = Queen(white)
        self._black = Queen(black)

    def empty(self):
        """Return an empty (mutable) grid"""
        return [
            list('_' * BOARD_SIZE)
            for i in range(BOARD_SIZE)
        ]

    def display(self):
        """Return an ascii representation of the board"""
        grid = self.empty()
        grid[self._white.row][self._white.col] = 'W'
        grid[self._black.row][self._black.col] = 'B'
        return [''.join(row) for row in grid]

    @property
    def can_attack(self):
        """Return true if queens are aligned such that attack is possible"""
        return self._white.in_line_with(self._black)


def board(white, black):
    board = ChessBoard(white, black)
    return board.display()


def can_attack(white, black):
    board = ChessBoard(white, black)
    return board.can_attack

@cds-amal thinks this looks great

Comments

Maybe I went a little crazy on the OO approach here ;P - but at least I learned the names of the two diagonals.

helenst commented 27 May 2016 at 15:41 UTC

Not crazy. well done.

cds-amal commented 27 May 2016 at 16:09 UTC

You're not logged in right now. Please login via GitHub to comment