I'm trying to code an Othello game, and now I'm trying to code the algorithm that does return the valid positions. I started by retrieving the directions of the empty squares where there's a black or white stone right next to it, but my code doesn't run. I don't know if I did something wrong but it seems that when I launch the program, the code runs slow because the algorithm is overkill. What can I do for that?
Here's my Code(By the way, I use React.js):
Here's the data structure of the square array:
history: [{
squares: [
Array(8).fill(null),
Array(8).fill(null),
Array(8).fill(null),
[null,null,null,'black','white',null,null,null],
[null,null,null,'white','black',null,null,null],
Array(8).fill(null),
Array(8).fill(null),
Array(8).fill(null)
]
}],
The Algorithm(for now, just returns the squares that have a stone right next to it(up, up & right , down, left, etc.)):
checkMoveValidity(isBlack) {
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[history.length - 1];
const squares = current.squares.slice()
// Get all the empty spaces
const emptySpaces = []
for (var row=1;row<squares.length-1;row++) {
for (var col=1;col<squares[row].length-1;col++) {
if (!squares[row][col]) {
emptySpaces.push([row,col])
}
}
}
const cordAndDirs = []
for (var sp=0;sp<emptySpaces.length;sp++) {
const element = emptySpaces[sp]
const elObject = {
coordinates: element,
directions: []
}
if (element === [0,0])
{
// Check down
if (squares[1][0]) {
const downEls = []
for (var i=1;i<squares.length;i++) {
downEls.push([i,0])
}
elObject.directions.push(downEls)
}
// Check down right (diagonal)
if (squares[1][1]) {
const drEls = []
for (var i=1;i<squares.length;i++) {
drEls.push([i,i])
}
elObject.directions.push(drEls)
}
// Check right
if (squares[0][1]) {
const rightEls = []
for (var i=1;i<squares.length;i++) {
rightEls.push([0,i])
}
elObject.directions.push(rightEls)
}
}
else if (emptySpaces[sp] === [0,7])
{
// Check down
if (squares[1][7]) {
const downEls = []
for (var i=1;i<squares.length;i++) {
downEls.push([i,7])
}
elObject.directions.push(downEls)
}
// Check down left (diagonal)
if (squares[1][6]) {
const drEls = []
for (var i=1;i<squares.length;i++) {
drEls.push([i,7 - i])
}
elObject.directions.push(drEls)
}
// Check left
if (squares[0][6]) {
const leftEls = []
for (var i=1;i<squares.length;i++) {
leftEls.push([0,7 - i])
}
elObject.directions.push(leftEls)
}
}
else if (emptySpaces[sp] === [7,0])
{
// Check up
if (squares[6][0]) {
const upEls = []
for (var i=1;i<squares.length;i++) {
upEls.push([7 - i,0])
}
elObject.directions.push(upEls)
}
// Check up right
if (squares[6][1]) {
const urEls = []
for (var i=1;i<squares.length;i++) {
urEls.push([7 - i,i])
}
elObject.directions.push(urEls)
}
// Check right
if (squares[7][1]) {
const rightEls = []
for (var i=1;i<squares.length;i++) {
rightEls.push([7,i - 1])
}
elObject.directions.push(rightEls)
}
}
else if (emptySpaces[sp] === [7,7])
{
//Check up
if (squares[6][7]) {
const upEls = []
for (var i=1;i<squares.length;i++) {
upEls.push([7 - i,7])
}
elObject.directions.push(upEls)
}
// Check up left
if (squares[6][6]) {
const ulEls = []
for (var i=1;i<squares.length;i++) {
ulEls.push([7 - i,7 - i])
}
elObject.directions.push(ulEls)
}
// Check left
if (squares[7][6]) {
const leftEls = []
for (var i=1;i<squares.length;i++) {
leftEls.push([7,7 - i])
}
elObject.directions.push(leftEls)
}
}
else
{
const crdsY = emptySpaces[sp][0]
const crdsX = emptySpaces[sp][1]
//Check up
if (squares[crdsY - 1][crdsX]) {
const upEls = []
var i = 1
while (crdsY - i >= 0) {
upEls.push([crdsY - i,crdsX])
i++;
}
elObject.directions.push(upEls)
}
// Check up right
if (squares[crdsY - 1][crdsX + 1]) {
const urEls = []
var i = 1
while (crdsY - i >= 0 && crdsX + i <= 7) {
urEls.push([crdsY - i,crdsX + i])
i++;
}
elObject.directions.push(urEls)
}
// Check right
if (squares[crdsY][crdsX + 1]) {
const rightEls = []
var i = 1
while (crdsX + i <= 7) {
rightEls.push([crdsY,crdsX + i])
i++;
}
elObject.directions.push(rightEls)
}
// Check down right
if (squares[crdsY + 1][crdsX + 1]) {
const rightEls = []
var i = 1
while (crdsY + i <= 7 && crdsX + i <= 7) {
rightEls.push([crdsY + i,crdsX + i])
i++;
}
elObject.directions.push(rightEls)
}
// Check down
if (squares[crdsY + 1][crdsX]) {
const rightEls = []
var i = 1
while (crdsY + i <= 7) {
rightEls.push([crdsY + i,crdsX])
i++;
}
elObject.directions.push(rightEls)
}
// Check down left
if (squares[crdsY + 1][crdsX - 1]) {
const rightEls = []
var i = 1
while (crdsY + i <= 7 && crdsX - i >= 0) {
rightEls.push([crdsY + i,crdsX - i])
i++;
}
elObject.directions.push(rightEls)
}
// Check left
if (squares[crdsY][crdsX - 1]) {
const rightEls = []
var i = 1
while (crdsX - i >= 0) {
rightEls.push([crdsY,crdsX - i])
i++;
}
elObject.directions.push(rightEls)
}
// Check up left
if (squares[crdsY - 1][crdsX - 1]) {
const rightEls = []
var i = 1
while (crdsY - i >= 0 && crdsX - i >= 0) {
rightEls.push([crdsY - i,crdsX - i])
}
elObject.directions.push(rightEls)
}
}
if (elObject.directions.length === 0) {
continue
} else {
cordAndDirs.push(elObject)
}
}
return cordAndDirs
}
And this is where I'm trying to implement it:
render() {
const history = this.state.history
const current = history[this.state.stepNumber]
// Return the game scene here
return (
<div className="master-container">
<GameBoard squares={current.squares} onClick={(row,col) => {
const elems = this.checkMoveValidity(this.state.blackIsNext)
console.log(elems)
}}/>
</div>
)
}
By the way, I checked whether the command has reached to the elements inside the GameBoard component. It does not have any problem, the problem occurred when I implemented the algorithm.
I did it. It was quite simple though, I even simplified the code a bit. I forgot to add i++;
to the last while loop, I was stuck forever, and then I had to handle the borders so that I don't get an error. For example, I can't //Check up
when the upper border squares have no squares beneath them.
This is how I changed the conditional statements:
for (var sp=0;sp<emptySpaces.length;sp++) {
const element = emptySpaces[sp]
const elObject = {
coordinates: element,
directions: []
}
// You apply the same methods for all the other squares here (can't use constant numbers in 'squares' now...)
const crdsY = emptySpaces[sp][0]
const crdsX = emptySpaces[sp][1]
var i;
//Check up
if (crdsY !== 0 && squares[crdsY - 1][crdsX]) {
const upEls = []
i = 1
while (crdsY - i >= 0) {
upEls.push([crdsY - i,crdsX])
i++;
}
elObject.directions.push(upEls)
}
// Check up right
if (crdsX !== 7 && crdsY !== 0 && squares[crdsY - 1][crdsX + 1]) {
const urEls = []
i = 1
while (crdsY - i >= 0 && crdsX + i <= 7) {
urEls.push([crdsY - i,crdsX + i])
i++;
}
elObject.directions.push(urEls)
}
// Check right
if (crdsX !== 7 && squares[crdsY][crdsX + 1]) {
const rightEls = []
i = 1
while (crdsX + i <= 7) {
rightEls.push([crdsY,crdsX + i])
i++;
}
elObject.directions.push(rightEls)
}
// Check down right
if (crdsX !== 7 && crdsY !== 7 && squares[crdsY + 1][crdsX + 1]) {
const rightEls = []
i = 1
while (crdsY + i <= 7 && crdsX + i <= 7) {
rightEls.push([crdsY + i,crdsX + i])
i++;
}
elObject.directions.push(rightEls)
}
// Check down
if (crdsY !== 7 && squares[crdsY + 1][crdsX]) {
const rightEls = []
i = 1
while (crdsY + i <= 7) {
rightEls.push([crdsY + i,crdsX])
i++;
}
elObject.directions.push(rightEls)
}
// Check down left
if (crdsY !== 7 && crdsX !== 0 && squares[crdsY + 1][crdsX - 1]) {
const rightEls = []
i = 1
while (crdsY + i <= 7 && crdsX - i >= 0) {
rightEls.push([crdsY + i,crdsX - i])
i++;
}
elObject.directions.push(rightEls)
}
// Check left
if (crdsX !== 0 && squares[crdsY][crdsX - 1]) {
const rightEls = []
i = 1
while (crdsX - i >= 0) {
rightEls.push([crdsY,crdsX - i])
i++;
}
elObject.directions.push(rightEls)
}
// Check up left
if (crdsX !== 0 && crdsY !== 0 && squares[crdsY - 1][crdsX - 1]) {
const rightEls = []
i = 1
while (crdsY - i >= 0 && crdsX - i >= 0) {
rightEls.push([crdsY - i,crdsX - i])
i++;
}
elObject.directions.push(rightEls)
}
if (elObject.directions.length !== 0) {
cordAndDirs.push(elObject)
}
And also I changed the the game board onClick
property a bit like this:
return (
<div className="master-container">
<GameBoard squares={current.squares} onClick={(row,col) => {
const elems = this.checkElementsAround(this.checkMoveValidity(this.state.blackIsNext))
console.log(elems)
for (let el=0;el<elems.length;el++) {
if (row === elems[el].coordinates[0] && col === elems[el].coordinates[1]) {
this.handleMove(row,col);
break
}
}
}}/>
</div>
)