diff --git a/board-shared/src/board.rs b/board-shared/src/board.rs index 4844622..7f4cca5 100644 --- a/board-shared/src/board.rs +++ b/board-shared/src/board.rs @@ -29,31 +29,29 @@ impl Board { diff } + /// Determines whether the given positions are contiguous. + /// + /// Contiguous means that the positions are adjacent in a straight line, either + /// horizontally or vertically. pub fn is_contiguous(positions: &[Position2d]) -> Option { let mut it = positions.iter(); let first = *it.next()?; let mut second = *it.next()?; - if first.x == second.x { - // Vertical - for &pos in it { - if pos.x != first.x || pos.y != second.y + 1 { - return Some(false); - } - second = pos; - } - Some(true) - } else if first.y == second.y { - // Horizontal - for &pos in it { - if pos.y != first.y || pos.y != second.y + 1 { - return Some(false); - } - second = pos; + + let orientation = match (second.x.checked_sub(first.x), second.y.checked_sub(first.y)) { + (Some(0), Some(1)) => (0, 1), + (Some(1), Some(0)) => (1, 0), + (_, _) => return Some(false), + }; + + for &pos in it { + if pos.x != second.x + orientation.0 || pos.y != second.y + orientation.1 { + return Some(false); } - Some(true) - } else { - Some(false) + second = pos; } + + Some(true) } } @@ -80,10 +78,22 @@ mod tests { fn test_is_contiguous() { assert_eq!(Board::is_contiguous(&[]), None); assert_eq!(Board::is_contiguous(&positions(&[(0, 0)])), None); + assert_eq!( + Board::is_contiguous(&positions(&[(0, 0), (0, 2)])), + Some(false) + ); + assert_eq!( + Board::is_contiguous(&positions(&[(0, 0), (2, 0)])), + Some(false) + ); assert_eq!( Board::is_contiguous(&positions(&[(0, 0), (0, 1), (0, 2)])), Some(true) ); + assert_eq!( + Board::is_contiguous(&positions(&[(1, 0), (2, 0), (3, 0), (4, 0)])), + Some(true) + ); assert_eq!( Board::is_contiguous(&positions(&[(0, 0), (0, 1), (1, 3)])), Some(false)