1

I am relatively new to JavaScript and I am writing some test code to check win lines in a TicTacToe (Noughts and Crosses) game.

After several iterations this is what I have come up with, but I still feel that it is unwieldy and relies too much on global variables.

Is there a better way to write this code?

const wins = [[0,1,2],[3,4,5],[6,7,8],
[0,3,6],[1,4,7],[2,5,8],
[0,4,8],[2,4,6]];

const moves = [0,5,2,4,3]; // example list of moves

var winLine = [];
const won = [true, true, true];

wins.forEach(function (win) {
win.forEach((square) => winLine.push(moves.some((move) => square == move)));
if(JSON.stringify(winLine) == JSON.stringify(won)){
  logWin();
 } else {
  winLine =[];
 }
});

 function logWin() {
  console.log("win");
 }
Dave022
  • 43
  • 3
  • This is **always** a bad idea: `JSON.stringify(winLine) == JSON.stringify(won)`. In this case, you can just use `winLine.every((value, index) => value === won[index])`. If it were more complex: https://stackoverflow.com/questions/201183/how-to-determine-equality-for-two-javascript-objects – T.J. Crowder Sep 07 '22 at 17:24

2 Answers2

0

You could filter the winning positions and get an array of lines.

If this array is empty, no win.

This code utilizes some array methods:

const
    wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]],
    moves = [0, 5, 2, 4, 3],
    winLines = wins.filter(p => p.every(v => moves.includes(v)));

console.log(winLines);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you, this is where I was trying to get to, and what I had conceptually in my mind. I knew about filter but was missing the relationship with every and includes. – Dave022 Sep 08 '22 at 14:33
0

You could go for a completely different approach where you first apply the moves on a bit board (of 9 bits), and then verify via bit operations whether there is a win:

// Patterns of winning lines
const wins = [0x7, 0x38, 0x1C0, 0x49, 0x92, 0x124, 0x111, 0x54];

const moves = [0,5,2,4,3]; // example list of moves

// Convert moves to bit board
const pattern = moves.reduce((acc, i) => acc | (1 << i), 0);
// Overlay each winning line pattern to see if there is a match
const hasWon = wins.some(win => (win & pattern) === win);

console.log(hasWon);
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I have to take my hat off to here; I haven't seen bitboards before and it has been a long time since I have dealt with binary so it took me about four hours of breaking the code down and even using a pencil and paper to work out what is happening here! I think I will build a version to include this for future reference for myself, I can see how it works now I have reverse engineered it but how did you work out the (1 << i) shift in the first place? – Dave022 Sep 08 '22 at 13:53