TicTacToe

Jeff Langr requested a Blog Pair for a tic-tac-toe program that he says “screams out for refactoring.” I looked at the code, and didn’t see an easy way to refactor it given the fragment posted. I did, however see a different solution.

To me, the code screamed out for a table-driven solution rather than an algorithmic one. Rather than have four different methods for detecting a winner, I built one. Here’s my solution:

  boolean isWinner(Player currentPlayer) {
    Position[][] winningCombinations = {
        {new Position(0,0), new Position(0,1), new Position(0,2)},
        {new Position(1,0), new Position(1,1), new Position(1,2)},
        {new Position(2,0), new Position(2,1), new Position(2,2)},
        {new Position(0,0), new Position(1,0), new Position(2,0)},
        {new Position(0,1), new Position(1,1), new Position(2,1)},
        {new Position(0,2), new Position(1,2), new Position(2,2)},
        {new Position(0,0), new Position(1,1), new Position(2,2)},
        {new Position(0,2), new Position(1,1), new Position(2,0)}
        };
    for (int i = 0; i < winningCombinations.length; i++) {
      Position[] aCombination = winningCombinations[i];
      boolean winner = true;
      for (int j = 0; j < aCombination.length; j++) {
        Position aPosition = aCombination[j];
        if (!currentPlayer.equals(grid[aPosition.x][aPosition.y])) {
          winner = false;
          break;
        }
      }
      if (winner) return winner;
    }
    return false;
  }

This solution reminds me of C code I’ve written. To see the tests and the steps along the way, browse the code in Subversion. You’ll also see a stupid mistake I made by rushing (it’s late) and not following my normal coding standards (“Always put a conditional clause in curly braces”). Fortunately, a test gave a surprising result and I found the problem.

In retrospect, I could have refactored to this from Jeff’s code. The key would have been to wrap the four “is…Winner()” methods with one, and then use the sort of “strangler refactor” that I used on my own code to get from conditionals to table-driven decision-making.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to MySpace Post to Ping.fm Post to Reddit Post to StumbleUpon

Comments (3) to “TicTacToe”

  1. An alternative way to think of the game is to fill in the board with a magic square.

    4 9 2
    3 5 7
    8 1 6

    Then the game becomes pick three numbers between 1 and 9 that add up to 15.

  2. I like both solutions (George’s and the magic number solution) for thinking outside the box, something we probed at; we had some similar thoughts. Both seem “less maintainable” if you look at extrapolating to a larger grid, and a game like connect 4. YAGNI, I suppose.

  3. […] AM === Jeff, I couldn’t figure out how to leave a trackback, but I posted my solution at http://blog.gdinwiddie.com/2008/07/29/tictactoe/ rather than put into a comment here. I went for a table-driven […]

Post a Comment
*Required
*Required (Never published)