# Need help understanding React Tic Tac Toe "Winner" function

Can someone please help me understand the “Winner” helper function from the React Tic Tac Toe tutorial?

This is taken from the official React tutorial. The problem I have is understand the for loop. Thanks.

``````function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}``````
2 Likes

Hello.

First, calculateWinner() function, declares a multidimensional array ‘lines’, that holds all the winning combinations.

Second, a ‘for’ loop iterate through all the combinations, and adds the board’s squares indexes in constants ‘a’, ‘b’ and ‘c’.

Finally, and ‘if’ conditional statement will compare the current combination of the iteration with the board’s clicked squares combinations, and if there is a match, it returns the current combination, otherwise it returns null.

This is my first time on this forum. Hope I could help you.

3 Likes

It didn’t help But I did managed to figure out while I was showering. The test is on the value or the props. If the value of a, b, c are the same, return the value of a (either X or O).

Thanks.

1 Like

I was confused at first too, but breaking it down everything makes sense.

See fiddle with detailed explanation: https://jsfiddle.net/nh_codes/tyck2j64/

2 Likes
``````function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
``````

understand what the logical operators are doing.

``````const [a, b, c] = lines[i];
``````

lets us only look at winning combination lines while we start comparing Square’s values.
Square’s values can only be `'X'` , `'O'` , or `null`.
if the value can be converted to `false` (if the value is `null`) the `if` statement returns `false`.

``````if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
``````

`&&` is checking for `null` values;
( why is `&&` used twice `¯\_(ツ)_/¯` );
`===` is comparing the values of `[a]` , `[b]` , and `[c]` to see if they are all `'X'`'s or all `'O'`'s;
`return squares[a]` can only be `'X'` or `'O'` after passing the `if` statement.

1 Like

but what i don’t understand is why in this line

if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {

why square[a] has to be by itself. isn’t

if (squares[a] === squares[b] && squares[a] === squares[c]) {

sufficient?

No. The squares[a] by itself is checking if there is a value in that particular square and the remainder of the condition makes sure they are all the same type (either X or O).

What if a was not an X or O, b was not an X or O, and c was not an X or O? If you just tested the following condition, it would evaluate to true when you do not want it to.

``````squares[a] === squares[b] && squares[a] === squares[c]
``````
1 Like

but isn’t null a falsy value?

Yes, null is a falsy value, which is why if a, b, or c is null, the original if you questioned (below) would evaluate to false. This is exactly why you must have the separate squares[a] in the expression.

``````if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
``````

If a, b, and c are all null values, you do not want to return squares[a]. The if statement would look like:

``````if (null && null === null && null === null) {
``````

The above reduces further to:

``````if (false && true && true) { // this will evaluate to false
``````

However, if we did not include the extra squares[a] at the beginning you would be left with:

``````if (true && true) { // this evaluates to true, but none of the squares are Xs or Os which is a problem.
``````
2 Likes

Yeah, I basically read that in my head as “are we even dealing with a real ‘a’ here to begin with?”

If not, then there is not point to the rest of it!

–ok i got it all wrong

I think you understand, but I am not exactly sure what you are trying to say in the last part (above).

I was confused, i have it right now i guess :slight_smile, rereading it your explanation makes total sense.
The first a is needed, we have to test the truthness of [a] first because null==null is returning true.
Thank you!

1 Like