The best solution for solving issues like this is to write down how you would solve the problem, identify the logical conditions involved, formalise that into pseudocode and then turn that into proper C++ code.
(That’s pretty much what most programmers do, but usually they do it in their head unless it’s a particularly hard problem.)
E.g. You might describe the solution as:
- Look at every cell from top left to bottom right
- if any cell is empty, it’s not a draw
- else, it’s a draw
Or to put it another way, you know that there’s a draw if no cells are empty and it’s not a draw if there are any empty cells, so what you’re really asking is “are there any empty cells?”.
The first bit is your loop, the second parts are what the condition would be.
// Look at every cell
for (uint8_t y; y < 3; y++)
for (uint8_t x; x < 3; x++)
// If a cell is empty...
if (grid[y][x] == Cell::Empty)
// Found an empty
Then you can do:
sound.tone(200, 100, 150, 100);
sound.tone(400, 100, 300, 100, 200, 100);
gstate = 2;
Note that you could turn that loop into its own “isADraw()” function, or more accurately “hasNoEmptyCells” (or invert the logic and call it “hasEmptyCells”).
I was going to blather on about how this loop is effectively a more optimal generic version of the
|| operator combined with a
!, but I’ll leave that for now.
Basically the short circuiting logic operators
&& can be generalised to work over the entire contents of a data structure.
(Normal C++ has a thing for doing that in its stdlib, but Arduino doesn’t have a version of the stdlib for various reasons.)
Lastly: if you find yourself wanting to call a variable
is something, then it should probably be a
bool. If it shouldn’t, you’ve probably picked the wrong name.