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.

4 Comments

Categories: Tools and Techniques

Tags: ,

4 Replies 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.