Doing some code clean-up on Battleships this morning, I was reminded of a detail of C# logic precedence that I’ve used to my benefit elsewhere (including within the program), but which caused a brief hiccup in one instance. Specifically, while the logical and and or operators are transitive, that’s not strictly true of && and ||.
In this case, I had broken my large and increasingly complex ResetGrid method into several smaller ones. I have a boolean variable, blnAllDone, which indicates whether the current puzzle has been solved. I created the subroutines which count the remaining cells and the remaining ships to return a boolean value, which would be true if the remaining cells or ships is zero, false otherwise. This was the original code:
bool blnAllDone = CalcRemainVals(); blnAllDone = blnAllDone && CalcRemainShips();
However, the CalcRemainShips method only ran if the puzzle was complete. As soon as I looked again at the code, I realized why: C# stops assessing x && y if x is false (since x && y can’t be true if x is false), and returns false. Likewise, c# stops assessing x || y if x is true, and returns true. This is a useful feature if you want to shortcut situations where a variable might not be set, for instance, but in this case it led to unexpected results.
I made a minor change, and all was well with the world again:
bool blnAllDone = CalcRemainVals(); blnAllDone = CalcRemainShips() && blnAllDone;