I'm wanting to add a horizontal check for a winning move in my connect 4 game - However I'm completely flumoxed with how to proceed.
There are already working checks for horizontal and vertical.
You can see that we are checking with a regex test against a stringified version of the array matrix.
A winning vertical array looks like this:
Array and joined array passed to the test function:
A winning horiontal array looks like this:
Array and joined array passed to the horizontal test function:
A winning diagonal array looks like this:
const testWin = (arr: number[]): boolean => /1{4}|2{4}/.test(arr.join(""));
const usePlayPiece = () => {
const [board, setBoard] = useState(boardState);
const [player, setPlayerTurn] = useState(playerState);
const [gameOver, setGameOver] = useState(gameOverState);
return (col: number) => {
// Play piece (non mutating)
const newBoard = board.map((column, i) => (i === col) ? [...column, player] : column);
const row = newBoard[col].length - 1;
if (
testWin(newBoard[col]) // Did win vertically
|| testWin(newBoard.map((col) => col[row] || 0)) // Did win horizontally
// || testWin() // Did win diagonally
) {
setGameOver(true);
} else {
// Keep playing
}
setBoard(newBoard);
};
};
CodePudding user response:
You could temporarily pad your columns with zeroes so they are equally sized (typically to length 6). Then turn that 2D array to a string, where the columns are separated with an extra character, and then use a one-for-all regular expression on it:
const testWin = (arr: number[][]): boolean => =>
/([12])(\1{3}|(.{5}\1){3}|(.{6}\1){3}|(.{7}\1){3})/.test(
arr.map(col => col.join("").padEnd(6, "0")).join(",")
);
And just have one call where you pass the complete board as argument:
if (testWin(newBoard)) {
// game over...
}
CodePudding user response:
Keeping in with the string version of your array, you need to test the full matrix through so you will need to pad out numbers after the last entry in all columns. This will allow you to test for a consistent pattern.
Using a 6 * 7 array you would end up with 6 numbers between each number you are testing for. The regex then will look like
1\d{6}1\d{6}1\d{6}1|2\d{6}2\d{6}2\d{6}2
For the opposite direction you will swap the {6} for {4}.