I'd like to DRY up this code:
YourConsultant.GameState gameState() {
for (int i = 0; i < 3; i++) {
// an 'xxx' column returns 'x', an 'ooo' returns 'o', a mixed row returns '0'
char c = areTheSame(board[i][0], board[i][1], board[i][2]);
if (c == 'x') {return YourConsultant.GameState.WON_BY_X;}
else if (c == 'o') {return YourConsultant.GameState.WON_BY_O;}
}
for (int i = 0; i < 3; i++) {
char c = areTheSame(board[0][i], board[1][i], board[2][i]);
if (c == 'x') {return YourConsultant.GameState.WON_BY_X;}
else if (c == 'o') {return YourConsultant.GameState.WON_BY_O;}
}
{
char c = areTheSame(board[0][0], board[1][1], board[2][2]);
if (c == 'x') {return YourConsultant.GameState.WON_BY_X;}
else if (c == 'o') {return YourConsultant.GameState.WON_BY_O;}
}
{
char c = areTheSame(board[0][2], board[1][1], board[2][0]);
if (c == 'x') {return YourConsultant.GameState.WON_BY_X;}
else if (c == 'o') {return YourConsultant.GameState.WON_BY_O;}
}
...
}
For that end, I want to write a short method which does this:
if (c == 'x') {return YourConsultant.GameState.WON_BY_X;}
else if (c == 'o') {return YourConsultant.GameState.WON_BY_O;}
But this would make the new method return. I suppose I cannot do something like super.return
? I could check the return value again, but it wouldn't make my code DRY. What do you suggest? (Sorry if it's been asked before, I found this difficult to search for)
UPDATE: I cannot simply pass the values, because if areTheSame == 0 then I should not return (yet).
UPDATE 2: I modified the code, replacing each two lines with this:
if (c == 'x' || c == 'o') return declareWinner(c);
It works fine, and does the same. Still have some repetition, but much better IMO.
No, a method cannot perform a return for its caller, but the caller can directly return the value returned by a called method. It does not appear that that would serve your purpose, however, for you want to return only conditionally.
I'd approach the problem with a deeper change. Note how similar your four stanzas are: it's not just the conditional returns that are a little wet. The tests you want to perform are few enough to be enumerable, so you could consider something along these lines:
private final static int[][][] TRIPLES = new int[][][] {
{ {0, 0}, {0, 1}, {0, 2} },
{ {1, 0}, {1, 1}, {1, 2} },
{ {2, 0}, {2, 1}, {2, 2} },
{ {0, 0}, {1, 0}, {2, 0} },
{ {0, 1}, {1, 1}, {2, 1} },
{ {0, 2}, {1, 2}, {2, 2} },
{ {0, 0}, {1, 1}, {2, 2} },
{ {0, 2}, {1, 1}, {2, 0} },
};
YourConsultant.GameState gameState() {
for (int i = 0; i < TRIPLES.length; i++) {
char c = areTheSame(
board[TRIPLES[i][0][0]][TRIPLES[i][0][1]],
board[TRIPLES[i][1][0]][TRIPLES[i][1][1]],
board[TRIPLES[i][2][0]][TRIPLES[i][2][1]]
);
if (c == 'x') {
return YourConsultant.GameState.WON_BY_X;
} else if (c == 'o') {
return YourConsultant.GameState.WON_BY_O;
}
}
return YourConsultant.GameState.NO_WINNER;
}