简体   繁体   中英

What is a simpler way to check for diagonals on a grid?

I'm trying to find all diagonally valid squares on a grid and set their value to 1. Diagonal is defined like Bishop's movement in chess.

I've got something that works, currently, but it feels very clunky. Mostly since I am doing a lot of checking to make sure the diagonal squares in question are within the bounds of the array.

The grid is 8x8...

eliminate diagonals

        for j in range (1,8):
            diagx1 = randx + j
            diagx2 = randx - j
            diagy1 = randy + j
            diagy2 = randy - j
            if diagx1 <= 7:
                if diagy1 <= 7:
                    setSquare(squares, diagx1, diagy1, 1)
                if diagy2 >= 0:
                    setSquare(squares, diagx1, diagy2, 1)
            if diagx2 >= 0:
                if diagy1 <= 7:
                    setSquare(squares, diagx2, diagy1, 1)
                if diagy2 >= 0:
                    setSquare(squares, diagx2, diagy2, 1)

Basically your method is about as simple as it can be. You have to do bounds checks and you have to add and subtract an offset. What you can change is the syntax.

def in_bounds(coords: tuple) -> bool:
    """Ensures both x and y values are in range(8)"""
    return all( 0 <= coord <= 7 for coord in coords)

origin = (3, 3)
diagonals = []
for offset in range(-8, 8):    # -8, -7, -6, ..., 6, 7
    if offset == 0:  continue  # skip origin
    new_location = origin[0] + offset, origin[1] + offset
    if in_bounds(new_location):
        diagonals.append(in_bounds)

Or even more simply:

origin = (3, 3)
diagonals = [new_location for offset in range(-8, 8)
                          for new_location in [(origin[0] + offset,
                                                origin[1] + offset)]
                          if offset != 0 and in_bounds(new_location)]

Your only other option is to pre-calculate what your range should be in order to keep yourself in bounds. Something like:

origin = (5, 3)
# diagonals should be
# # x  y     offset
# # 2, 0     -3
# # 3, 1     -2
# # 4, 2     -1
# # 6, 4      1
# # 7, 5      2

other_origin = (1, 1)
# diagonals should be
# # x  y     offset
# # 0, 0     -1
# # 2, 2      1
# # ...       ...
# # 7, 7      6

get_range(origin:tuple) -> range:
    """returns the range of offsets to produce diagonals"""
    small, large = min(origin), max(origin)
    from = 0 - small
    to = 8 - large
    return range(from, to)

origin = (3, 3)
diagonals = [(origin[0] + offset, origin[1] + offset) 
             for offset in get_range(origin)]

Note that it might be worth your while to build squares that can find their own diagonals.

class Square(object):
    def __init__(self, x, y, parent=None):
        """A square in a coordinate plane"""
        self.x = x
        self.y = y
        self.parent = parent  # might be a larger container of squares?

    def __add__(self, other):
        if isinstance(other, tuple) and len(other) == 2:
            # hack the tuple into a square so we can add them easily
            other = Square(*tuple)
        try:
            return self.__class__((self.x + other.x, self.y + other.y))
        except AttributeError:
            raise TypeError("type Square can only add to other coordinate plane types")

    def __iter__(self):
        yield self.x
        yield self.y

    def __repr__(self):
        return "Square({}, {})".format(self.x, self.y)

    @staticmethod
    def find_diagonals(origin):
        diagonals = []
        for offset in range(1, 8):
            trial_vectors = [(offset, offset), (-offset, -offset),
                             (offset, -offset), (-offset, offset)]
            result_coords = [origin + vector for vector in trial_vectors]
            diagonals.extend(list(filter(
                origin._in_bounds, result_coords)))
        return diagonals

    @staticmethod
    def _in_bounds(coords):
        return all( 0 <= coord <= 7 for coord in coords)

origin = Square(3, 3)
diagonals = origin.find_diagonals(origin)
# [ Square(2, 2), Square(4, 4), Square(2, 4), Square(4, 2),
#   Square(1, 1), Square(5, 5), Square(1, 5), Square(5, 1),
#   Square(0, 0), Square(6, 6), Square(0, 6), Square(6, 0),
#                 Square(7, 7) ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM