Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given a 0-indexed 8 x 8 grid board, where board[r][c] represents the cell (r, c) on a game board. On the board, free cells are represented by '.', white cells are represented by 'W', and black cells are represented by 'B'.
Each move in this game consists of choosing a free cell and changing it to the color you are playing as (either white or black). However, a move is only legal if, after changing it, the cell becomes the endpoint of a good line (horizontal, vertical, or diagonal).
A good line is a line of three or more cells (including the endpoints) where the endpoints of the line are one color, and the remaining cells in the middle are the opposite color (no cells in the line are free). You can find examples for good lines in the figure below:
Given two integers rMove and cMove and a character color representing the color you are playing as (white or black), return true if changing cell (rMove, cMove) to color color is a legal move, or false if it is not legal.
Example 1:
Input: board = [[".",".",".","B",".",".",".","."],[".",".",".","W",".",".",".","."],[".",".",".","W",".",".",".","."],[".",".",".","W",".",".",".","."],["W","B","B",".","W","W","W","B"],[".",".",".","B",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","W",".",".",".","."]], rMove = 4, cMove = 3, color = "B" Output: true Explanation: '.', 'W', and 'B' are represented by the colors blue, white, and black respectively, and cell (rMove, cMove) is marked with an 'X'. The two good lines with the chosen cell as an endpoint are annotated above with the red rectangles.
Example 2:
Input: board = [[".",".",".",".",".",".",".","."],[".","B",".",".","W",".",".","."],[".",".","W",".",".",".",".","."],[".",".",".","W","B",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".","B","W",".","."],[".",".",".",".",".",".","W","."],[".",".",".",".",".",".",".","B"]], rMove = 4, cMove = 4, color = "W" Output: false Explanation: While there are good lines with the chosen cell as a middle cell, there are no good lines with the chosen cell as an endpoint.
Constraints:
board.length == board[r].length == 80 <= rMove, cMove < 8board[rMove][cMove] == '.'color is either 'B' or 'W'.Problem summary: You are given a 0-indexed 8 x 8 grid board, where board[r][c] represents the cell (r, c) on a game board. On the board, free cells are represented by '.', white cells are represented by 'W', and black cells are represented by 'B'. Each move in this game consists of choosing a free cell and changing it to the color you are playing as (either white or black). However, a move is only legal if, after changing it, the cell becomes the endpoint of a good line (horizontal, vertical, or diagonal). A good line is a line of three or more cells (including the endpoints) where the endpoints of the line are one color, and the remaining cells in the middle are the opposite color (no cells in the line are free). You can find examples for good lines in the figure below: Given two integers rMove and cMove and a character color representing the color you are playing as (white or black), return true if
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
[[".",".",".","B",".",".",".","."],[".",".",".","W",".",".",".","."],[".",".",".","W",".",".",".","."],[".",".",".","W",".",".",".","."],["W","B","B",".","W","W","W","B"],[".",".",".","B",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","W",".",".",".","."]] 4 3 "B"
[[".",".",".",".",".",".",".","."],[".","B",".",".","W",".",".","."],[".",".","W",".",".",".",".","."],[".",".",".","W","B",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".","B","W",".","."],[".",".",".",".",".",".","W","."],[".",".",".",".",".",".",".","B"]] 4 4 "W"
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1958: Check if Move is Legal
class Solution {
public boolean checkMove(char[][] board, int rMove, int cMove, char color) {
for (int a = -1; a <= 1; ++a) {
for (int b = -1; b <= 1; ++b) {
if (a == 0 && b == 0) {
continue;
}
int i = rMove, j = cMove;
int cnt = 0;
while (0 <= i + a && i + a < 8 && 0 <= j + b && j + b < 8) {
i += a;
j += b;
if (++cnt > 1 && board[i][j] == color) {
return true;
}
if (board[i][j] == color || board[i][j] == '.') {
break;
}
}
}
}
return false;
}
}
// Accepted solution for LeetCode #1958: Check if Move is Legal
func checkMove(board [][]byte, rMove int, cMove int, color byte) bool {
for a := -1; a <= 1; a++ {
for b := -1; b <= 1; b++ {
if a == 0 && b == 0 {
continue
}
i, j := rMove, cMove
cnt := 0
for 0 <= i+a && i+a < 8 && 0 <= j+b && j+b < 8 {
i += a
j += b
cnt++
if cnt > 1 && board[i][j] == color {
return true
}
if board[i][j] == color || board[i][j] == '.' {
break
}
}
}
}
return false
}
# Accepted solution for LeetCode #1958: Check if Move is Legal
class Solution:
def checkMove(
self, board: List[List[str]], rMove: int, cMove: int, color: str
) -> bool:
for a in range(-1, 2):
for b in range(-1, 2):
if a == 0 and b == 0:
continue
i, j = rMove, cMove
cnt = 0
while 0 <= i + a < 8 and 0 <= j + b < 8:
cnt += 1
i, j = i + a, j + b
if cnt > 1 and board[i][j] == color:
return True
if board[i][j] in (color, "."):
break
return False
// Accepted solution for LeetCode #1958: Check if Move is Legal
/**
* [1958] Check if Move is Legal
*
* You are given a 0-indexed 8 x 8 grid board, where board[r][c] represents the cell (r, c) on a game board. On the board, free cells are represented by '.', white cells are represented by 'W', and black cells are represented by 'B'.
* Each move in this game consists of choosing a free cell and changing it to the color you are playing as (either white or black). However, a move is only legal if, after changing it, the cell becomes the endpoint of a good line (horizontal, vertical, or diagonal).
* A good line is a line of three or more cells (including the endpoints) where the endpoints of the line are one color, and the remaining cells in the middle are the opposite color (no cells in the line are free). You can find examples for good lines in the figure below:
* <img alt="" src="https://assets.leetcode.com/uploads/2021/07/22/goodlines5.png" style="width: 500px; height: 312px;" />
* Given two integers rMove and cMove and a character color representing the color you are playing as (white or black), return true if changing cell (rMove, cMove) to color color is a legal move, or false if it is not legal.
*
* Example 1:
* <img alt="" src="https://assets.leetcode.com/uploads/2021/07/10/grid11.png" style="width: 350px; height: 350px;" />
* Input: board = [[".",".",".","B",".",".",".","."],[".",".",".","W",".",".",".","."],[".",".",".","W",".",".",".","."],[".",".",".","W",".",".",".","."],["W","B","B",".","W","W","W","B"],[".",".",".","B",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","W",".",".",".","."]], rMove = 4, cMove = 3, color = "B"
* Output: true
* Explanation: '.', 'W', and 'B' are represented by the colors blue, white, and black respectively, and cell (rMove, cMove) is marked with an 'X'.
* The two good lines with the chosen cell as an endpoint are annotated above with the red rectangles.
*
* Example 2:
* <img alt="" src="https://assets.leetcode.com/uploads/2021/07/10/grid2.png" style="width: 350px; height: 351px;" />
* Input: board = [[".",".",".",".",".",".",".","."],[".","B",".",".","W",".",".","."],[".",".","W",".",".",".",".","."],[".",".",".","W","B",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".","B","W",".","."],[".",".",".",".",".",".","W","."],[".",".",".",".",".",".",".","B"]], rMove = 4, cMove = 4, color = "W"
* Output: false
* Explanation: While there are good lines with the chosen cell as a middle cell, there are no good lines with the chosen cell as an endpoint.
*
*
* Constraints:
*
* board.length == board[r].length == 8
* 0 <= rMove, cMove < 8
* board[rMove][cMove] == '.'
* color is either 'B' or 'W'.
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/check-if-move-is-legal/
// discuss: https://leetcode.com/problems/check-if-move-is-legal/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
// Credit: https://leetcode.com/problems/check-if-move-is-legal/solutions/3241963/just-a-runnable-solution/
pub fn check_move(board: Vec<Vec<char>>, r_move: i32, c_move: i32, color: char) -> bool {
let x_arr = [0, 0, 1, -1, 1, -1, -1, 1];
let y_arr = [1, -1, 0, 0, 1, -1, 1, -1];
for i in 0..8 {
let mut x = r_move + x_arr[i];
let mut y = c_move + y_arr[i];
let mut count = 0;
while x < board.len() as i32 && x >= 0 && y < board[i].len() as i32 && y >= 0 {
if board[x as usize][y as usize] == '.' {
break;
} else if board[x as usize][y as usize] != color {
count += 1;
} else if board[x as usize][y as usize] == color && count < 1 {
break;
} else if board[x as usize][y as usize] == color && count >= 1 {
return true;
}
x += x_arr[i];
y += y_arr[i];
}
}
false
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1958_example_1() {
let board = vec![
vec!['.', '.', '.', 'B', '.', '.', '.', '.'],
vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
vec!['W', 'B', 'B', '.', 'W', 'W', 'W', 'B'],
vec!['.', '.', '.', 'B', '.', '.', '.', '.'],
vec!['.', '.', '.', 'B', '.', '.', '.', '.'],
vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
];
let r_move = 4;
let c_move = 3;
let color = 'B';
let result = true;
assert_eq!(Solution::check_move(board, r_move, c_move, color), result);
}
#[test]
fn test_1958_example_2() {
let board = vec![
vec!['.', '.', '.', '.', '.', '.', '.', '.'],
vec!['.', 'B', '.', '.', 'W', '.', '.', '.'],
vec!['.', '.', 'W', '.', '.', '.', '.', '.'],
vec!['.', '.', '.', 'W', 'B', '.', '.', '.'],
vec!['.', '.', '.', '.', '.', '.', '.', '.'],
vec!['.', '.', '.', '.', 'B', 'W', '.', '.'],
vec!['.', '.', '.', '.', '.', '.', 'W', '.'],
vec!['.', '.', '.', '.', '.', '.', '.', 'B'],
];
let r_move = 4;
let c_move = 4;
let color = 'W';
let result = false;
assert_eq!(Solution::check_move(board, r_move, c_move, color), result);
}
}
// Accepted solution for LeetCode #1958: Check if Move is Legal
function checkMove(board: string[][], rMove: number, cMove: number, color: string): boolean {
for (let a = -1; a <= 1; ++a) {
for (let b = -1; b <= 1; ++b) {
if (a === 0 && b === 0) {
continue;
}
let [i, j] = [rMove, cMove];
let cnt = 0;
while (0 <= i + a && i + a < 8 && 0 <= j + b && j + b < 8) {
i += a;
j += b;
if (++cnt > 1 && board[i][j] === color) {
return true;
}
if (board[i][j] === color || board[i][j] === '.') {
break;
}
}
}
}
return false;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.