Finding neighbor cells in a grid with the same value. Ideas how to improve this function?

Here’s an approach that involves less copying and pasting — hopefully it gives you some idea of how to break things down into the smallest number of the most reusable pieces possible. 🙂

The general idea here is to come up with a way of expressing the concept of scanning a line across the board in different directions in such a way that you can just express the direction and then let the same block of code handle the scan regardless of what the direction is.

from typing import List, Optional, Tuple


def do_we_have_a_winner(board: List[List[Optional[str]]], length: int) -> Optional[str]:
    """Returns the 'mark' of the player with a row of the given length."""
    width = range(len(board))
    height = range(len(board[0]))
    # Do four scans across the board -- right, down, and diagonals.
    for dx, dy in [(0, 1), (1, 0), (1, 1), (1, -1)]:
        edges: List[Tuple[int, int]] = []
        if dx > 0:
            # scanning right, start from left edge
            edges += [(0, y) for y in height]
        if dy > 0:
            # scanning down, start from top edge
            edges += [(x, 0) for x in width]
        if dy < 0:
            # scanning up, start from bottom edge
            edges += [(x, height[-1]) for x in width]
        for ex, ey in edges:
            mark: Optional[str] = None
            row = 0
            x, y = ex, ey
            while x in width and y in height:
                if board[x][y] == mark:
                    row += 1
                else:
                    mark = board[x][y]
                    row = 1
                if mark is not None and row >= length:
                    return mark
                x, y = x + dx, y + dy
    return None


print(do_we_have_a_winner([
    ['X', 'O', 'O'],
    ['O', 'X', 'O'],
    ['O', 'O', 'X'],
], 3))  # X

Note that this function assumes one at most winner, so if there are multiple winners, it will only return one of them — I’ll leave it as an exercise for the reader to figure out how to change it to handle that situation better. 🙂

Leave a Comment