I'm making a tic tac toe game, I've implemented marking down the fields that aren't taken. There is a turn based system, which switches the players mark after one of the fields is marked. The problem is, I have no idea how to detect 3 marks in a row or even a draw (when all of the fields are taken). The fields are taken from a Node List and then pushed into an array called gameboard, I've done that so that I can access them easier.
What should I pay the most attention to so that I can solve that? How do I come up with an idea that's possible to implement?
Here is the codePen link: https://codepen.io/-E33/pen/eYbrbaM
here is the JS code:
const gameboard = [];
//player constructor
function Player(sign) {
this.sign = sign;
}
//field constructor
function gameboard_field(field) {
this.field = field;
this.taken = false;
let self = this
//this functions was made so that players can't play in a
//spot that's already taken, it also controls the 'players turn' system
this.field.onclick = function() {
if (self.taken === false) {
self.field.innerHTML = t;
self.taken = true;
}
if (t === player1.sign) {
t = player2.sign
} else if (t === player2.sign) {
t = player1.sign
}
};
};
const player1 = new Player('X');
const player2 = new Player('O');
let t = player1.sign
//push a gameboard field into the gameboard array
//gameboard array was made so that we can access the fields easily
for (let i = 0; i < marker_field.length; i++) {
let newField = new gameboard_field(marker_field[i]);
gameboard.push(newField);
};```
I tried to think of how to make the fields detect the mark of it's neighbor fields
Add "check_board( t, 3, 3 );" in the "onclick" function, immediately after setting the players marker and before you change the player sign. Where the 3s are the width and height of the board.
Note: Code only works with square boards.
/**
* Check board after player makes their move.
*
* @param string t the player characters
* @param int width the board width
* @param int height the board height
* @issue SOF-77190125-1 Only works with square boards.
*/
function check_board( t, width, height ){
/**
* Initialize some variables that we're going to use
*/
let index,
length;
/**
* @var string selector Class name for the buttons
*/
let selector = 'marker-field';
/**
* @var array elements_data Store the HTML DOM elements
*/
let elements_data;
/**
* @var array board_data Store the configuration of the players placements
* @var array winning_configurations Set of winning placement configurations
*/
let board_data = [],
winning_configurations = [];
/**
* Check for error in board configuration.
*/
if( width != height ){
throw new Error( 'Oh! So sorry, the board must be square. :(' );
}
/**
* Get the buttons, because we need them to know who placed what where.
*/
elements_data = document.getElementsByClassName(selector);
/**
* Get the board data. Note: We're only storing this players data.
*/
index = 0;
length = elements_data.length;
for( ; index < length; index++ ){
let marker_field_data = elements_data[ index ].innerText;
board_data[ index ] = '';
if( marker_field_data == t ){
board_data[ index ] = t;
}
}
/**
* Use the board data to create an array of would-be winning configurations.
* Note: There may be some nice mathematical way of doing this with matrices.
* @obsolete Requirements changed
* @url https://stackoverflow.com/questions/77189783/how-to-make-a-3-in-a-row-detection-system-in-tic-tac-toe/77190125#comment136080110_77190125
*/
/**
* winning_configurations = [
* board_data[0] + board_data[1] + board_data[2],
* board_data[3] + board_data[4] + board_data[5],
* board_data[6] + board_data[7] + board_data[8],
* board_data[0] + board_data[3] + board_data[6],
* board_data[1] + board_data[4] + board_data[7],
* board_data[2] + board_data[5] + board_data[8],
* board_data[0] + board_data[4] + board_data[8],
* board_data[2] + board_data[4] + board_data[6]
* ];
*/
winning_configurations = get_winning_configurations( board_data, width, height );
/**
* If any of the winning configurations width number of the players characters, then they win.
* Note: We've updated this portion of the script to create the
* string that we're looking for dynamically. This is all a bit ham-fisted.
*/
if( winning_configurations.indexOf( new Array( width + 1 ).join( t ) ) != -1 ){
alert( t + ' wins!');
}
}
/**
* Create an array of possible winning configurations.
*
* @param array board_data A one-dimensional array of dense board data.
* @param int width the board width
* @param int height the board height
* @return array
*/
function get_winning_configurations( board_data, width, height ){
/**
* Initialize some variables that we're going to use
*/
let index,
length;
/**
* @var array winning_configurations This is the return value.
*/
let winning_configurations = [];
/**
* Used throughout the function to store configuration data.
*/
let config_data;
/**
* Get the board data for the row wins
*/
index = 0;
length = height;
for( ; index < length; index++ ){
let _index = 0,
_length = width;
config_data = []
for( ; _index < _length; _index++ ){
config_data.push( board_data[ ( index * ( width ) ) + _index ] );
}
winning_configurations.push( config_data.join('') );
}
/**
* Get the board data for the column wins
*/
index = 0;
length = width;
for( ; index < length; index++ ){
let _index = 0,
_length = height;
config_data = [];
for( ; _index < _length; _index++ ){
config_data.push( board_data[ ( index ) + ( _index * height ) ] );
}
winning_configurations .push( config_data.join('') );
}
/**
* Get the board data for descending diagonal right win
*/
index = 0;
length = height;
config_data = [];
for( ; index < length; index++ ){
config_data.push( board_data[ index + ( index * width ) ] );
}
winning_configurations.push( config_data.join('') );
/**
* Get the board data for ascending diagonal left win
*/
index = height;
length = 0;
config_data = [];
for( ; index > length; index-- ){
config_data.push( board_data[ ( index - ( index * width ) ) * -1 ] );
}
winning_configurations .push( config_data.join('') );
return( winning_configurations );
}
Here's some additional information that will provide some insight into how the get_winning_configurations function works. All of that arithmetic is calculating the array keys for the board_data array.
Calculating a row of board_data array indice involves getting the consecutive number values of any row, while iterating the width and height of the board. A similar idea is used to get the column wins and diagonal wins.