1 37 package net.sourceforge.cruisecontrol.sampleproject.connectfour; 38 39 44 public class PlayingStand { 45 private static final int MAX_ROWS = 6; 46 private static final int MAX_COLUMNS = 7; 47 48 private final Chip[][] stand = new Chip[MAX_COLUMNS][MAX_ROWS]; 49 private boolean gameOver; 50 private Chip winner = null; 51 private Chip lastPlayed; 52 private WinningPlacement winningPlacement; 53 54 public void dropRed(int columnNumber) throws GameOverException { 55 dropChip(Chip.RED, columnNumber); 56 } 57 58 public void dropBlack(int columnNumber) throws GameOverException { 59 dropChip(Chip.BLACK, columnNumber); 60 } 61 62 private void dropChip(Chip player, int columnNumber) { 63 if (gameOver) { 64 throw new GameOverException(); 65 } 66 67 if (lastPlayed == player) { 68 throw new OutOfTurnException(); 69 } 70 71 if (columnNumber < 0 || columnNumber >= MAX_COLUMNS) { 72 throw new InvalidColumnException(); 73 } 74 75 if (stand[columnNumber][MAX_ROWS - 1] != null) { 76 throw new FullColumnException(); 77 } 78 79 Chip[] column = stand[columnNumber]; 80 for (int i = 0; i < column.length; i++) { 81 Chip nextChip = column[i]; 82 if (nextChip == null) { 83 column[i] = player; 84 break; 85 } 86 } 87 88 lastPlayed = player; 89 gameOver = areFourConnected() || isFull(); 90 } 91 92 public boolean isFull() { 93 94 for (int nextColumnNum = 0; nextColumnNum < stand.length; nextColumnNum++) { 95 if (stand[nextColumnNum][MAX_ROWS - 1] == null) { 96 return false; 97 } 98 } 99 100 return true; 101 } 102 103 public boolean areFourConnected() { 104 for (int i = 0; i < stand.length; i++) { 105 Chip[] column = stand[i]; 106 for (int j = 0; j < column.length; j++) { 107 Chip nextCell = column[j]; 108 if (nextCell != null && (hasVerticalMatch(i, j) || 109 hasUpwardDiagonalMatch(i, j) || 110 hasDownwardDiagonalMatch(i, j) || 111 hasHorizontalMatch(i, j))) { 112 winner = nextCell; 113 return true; 114 } 115 } 116 } 117 118 return false; 119 } 120 121 private boolean hasHorizontalMatch(int column, int row) { 122 Chip chip = stand[column][row]; 123 winningPlacement = new WinningPlacement(column, row, Direction.HORIZONTAL); 124 125 try { 126 return stand[column + 1][row] == chip && stand[column + 2][row] == chip && stand[column + 3][row] == chip; 127 } catch (ArrayIndexOutOfBoundsException e) { 128 return false; 129 } 130 } 131 132 private boolean hasUpwardDiagonalMatch(int column, int row) { 133 Chip chip = stand[column][row]; 134 winningPlacement = new WinningPlacement(column, row, Direction.UPWARD_DIAGONAL); 135 try { 136 return stand[column + 1][row + 1] == chip && stand[column + 2][row + 2] == chip && 137 stand[column + 3][row + 3] == chip; 138 } catch (ArrayIndexOutOfBoundsException e) { 139 return false; 140 } 141 } 142 143 private boolean hasDownwardDiagonalMatch(int column, int row) { 144 Chip chip = stand[column][row]; 145 winningPlacement = new WinningPlacement(column, row, Direction.DOWNWARD_DIAGONAL); 146 try { 147 return stand[column + 1][row - 1] == chip && stand[column + 2][row - 2] == chip && 148 stand[column + 3][row - 3] == chip; 149 } catch (ArrayIndexOutOfBoundsException e) { 150 return false; 151 } 152 } 153 154 private boolean hasVerticalMatch(int column, int row) { 155 Chip chip = stand[column][row]; 156 winningPlacement = new WinningPlacement(column, row, Direction.VERTICAL); 157 try { 158 return stand[column][row + 1] == chip && stand[column][row + 2] == chip && stand[column][row + 3] == chip; 159 } catch (ArrayIndexOutOfBoundsException e) { 160 return false; 161 } 162 } 163 164 public Chip getWinner() { 165 return winner; 166 } 167 168 public boolean isGameOver() { 169 return gameOver; 170 } 171 172 public WinningPlacement getWinningPlacement() { 173 if (!gameOver) { 174 throw new GameNotOverException(); 175 } 176 if (isFull() && !areFourConnected()) { 177 throw new StalemateException(); 178 } 179 180 return winningPlacement; 181 } 182 183 public class WinningPlacement { 184 private final Direction direction; 185 private final Cell startingCell; 186 187 public WinningPlacement(int column, int row, Direction direction) { 188 startingCell = new Cell(column, row); 189 this.direction = direction; 190 } 191 192 public Cell getStartingCell() { 193 return startingCell; 194 } 195 196 public Direction getDirection() { 197 return direction; 198 } 199 } 200 201 202 } 203 | Popular Tags |