package lab.games; import java.util.Random; /** * The Model of the GUI. */ public class Model { private int[][] slots; // slots[r][c]: whose token in r-th row and c-th column public static final int EMPTY = 0; public static final int PLAYER = 1; public static final int COMPUTER = 2; /** * The number of rows. */ public static final int ROW = 6; /** * The number of columns. */ public static final int COLUMN = 7; /** * Number of coins that need to be connected to win. * This constant has to be smaller than or equals to the constants * Model.ROW and Model.COLUMN. */ public static final int CONNECTED = 4; /** * Initializes this model. */ public Model() { this.slots = new int[Model.ROW][Model.COLUMN]; } /** * Tests if all slots are filled. * * @return true if all slots are filled, false otherwise. */ public boolean isFilled() { boolean isFilled = true; for (int c = 0; c < Model.COLUMN && isFilled; c++) { isFilled = this.isFilled(c); } return isFilled; } /** * Tests if all slots of the given column is filled. * * @param column The number of the column. * @pre. 0 <= colummn < Model.COLUMN. * @return true if all slots of the given column are filled, * false otherwise. */ public boolean isFilled(int column) { return this.slots[0][column] != Model.EMPTY; } /** * Drop a coin of the given player in the specified column. * * @param column The number of the column in which the coin is dropped. * @pre. 0 <= colummn < Model.COLUMN * @param player The player that drops the coin. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @throws Exception if the given column is filled. */ public int drop(int column, int player) throws Exception { if (this.isFilled(column)) { throw new Exception("You cannot drop a coin in this column"); } else { int r = Model.ROW - 1; while (this.slots[r][column] != Model.EMPTY) { r--; } this.slots[r][column] = player; return r; } } /** * Returns the player of the coin with the specified column and * row number of this board. * ** @param row The row number. * @pre. 0 <= row < Model.ROW. * @param column The column number. * @pre. 0 <= colummn < Model.COLUMN. * @return The player of the coin with the specified column and * row number. */ public int get(int row, int column) { return this.slots[row][column]; } /** * Determine if the given player has won. * * @param player A player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @return true if the given player has won, false otherwise. */ public boolean hasWon(int player) { return this.horizontal(player) || this.vertical(player) || this.diagonalDown(player) || this.diagonalUp(player); } /** * Tests if the given player has enough coins connected horizontally to win. * * @param player A player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @return true if the given player has enough coins connected horizontally to win, * false otherwise. */ private boolean horizontal(int player) { boolean won = false; for (int r = 0; r < Model.ROW && !won; r++) { int c = 0; int count = 0; while (c < Model.COLUMN && !won) { if (player == this.get(r, c)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } c++; } } return won; } /** * Tests if the given player has enough coins connected vertically to win. * * @param player A player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @return true if the given player has enough coins connected vertically to win, * false otherwise. */ private boolean vertical(int player) { boolean won = false; for (int c = 0; c < Model.COLUMN && !won; c++) { int r = 0; int count = 0; while (r < Model.ROW && !won) { if (player == this.get(r, c)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } r++; } } return won; } /** * Tests if the given player has enough coins connected along a diagonal downwards to win. * * @param player A player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @return true if the given player has enough coins connected along a diagonal downwards to win, * false otherwise. */ private boolean diagonalDown(int player) { boolean won = false; for (int r = Model.CONNECTED; r < Model.ROW && !won; r++) { int c = 0; int i = 0; int count = 0; while (r - i >= 0 & c + i < Model.COLUMN && !won) { if (player == this.get(r - i, c + i)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } for (int c = 0; c <= Model.COLUMN - Model.CONNECTED && !won; c++) { int r = Model.ROW - 1; int i = 0; int count = 0; while (r - i >= 0 & c + i < Model.COLUMN && !won) { if (player == this.get(r - i, c + i)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } return won; } /** * Tests if the given player has enough coins connected along a diagonal upwards to win. * * @param player A player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @return true if the given player has enough coins connected along a diagonal upwards to win, * false otherwise. */ private boolean diagonalUp(int player) { boolean won = false; for (int r = 0; r <= Model.ROW - Model.CONNECTED && !won; r++) { int c = 0; int i = 0; int count = 0; while (r + i < Model.ROW & c + i < Model.COLUMN && !won) { if (player == this.get(r + i, c + i)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } for (int c = 0; c <= Model.COLUMN - Model.CONNECTED && !won; c++) { int r = 0; int i = 0; int count = 0; while (r + i < Model.ROW & c + i < Model.COLUMN && !won) { if (player == this.get(r + i, c + i)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } return won; } public int move() { Random random = new Random(System.currentTimeMillis()); int column; do { column = random.nextInt(Model.COLUMN); } while (this.isFilled(column)); return column; } }