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 /** * Represents an empty slot. */ private static final int EMPTY = 0; /** * Represents a coin dropped by the player. */ public static final int PLAYER = 1; /** * Represent a coin dropped by the computer. */ 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.setSlots(new int[Model.ROW][Model.COLUMN]); } /** * Returns the slots. * * @return the slots. */ private int[][] getSlots() { return this.slots; } /** * Sets the slots to the given slots. * * @param slots the slots. */ private void setSlots(int[][] slots) { this.slots = slots; } /** * Returns the player whose coin occupies the slot with the given * row and column number. * * @param row the row number. * @pre. row >= 0 && row < Model.ROW * @param column the column number. * @pre. column >= 0 && column < Model.COLUMN * @return the player whose coin occupies the slot with the given * row and column number. */ private int getSlot(int row, int column) { return this.getSlots()[row][column]; } /** * Sets the slot with the given row and column number to the * given player. * * @param row the row number. * @pre. row >= 0 && row < Model.ROW * @param column the column number. * @pre. column >= 0 && column < Model.COLUMN * @param player the player. * @pre. player == Model.PLAYER || player == Model.COMPUTER */ private void setSlot(int row, int column, int player) { this.getSlots()[row][column] = player; } /** * Tests if all slots are filled. * * @return true if all slots are filled, false otherwise. */ public boolean isFilled() { return this.isFilledRecursive(0); } /** * Tests if all the slots of all columns with the given number and higher are filled. * * @param column column number. * @pre. column >= 0 && column <= Model.COLUMN * @return true if all the slots of all columns with the given number and higher are * filled, false otherwise. */ public boolean isFilledRecursive(int column) { } /** * 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 { return this.dropRecursive(column, Model.ROW - 1, player); } } /** * Find the first empty slot of the given column with row * smaller than or equal to the given row number and drop * the coin. * * @param column column number. * @pre. column >= 0 && column < Model.COLUMN * @param row row number. * @pre. row >= 0 && row < Model.ROW * @param player The player that drops the coin. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @return the row number at which the coin drops. */ private int dropRecursive(int column, int row, int player) { } /** * 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) { return this.horizontalRecursive(player, 0); } /** * Tests if the given player has enough coins connected horizontally to win * in a row whose number is greater than or equal to the given row number. * * @param player A player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param row a row number * @pre. row >= 0 && row <= Model.ROW * @return true if the given player has enough coins connected horizontally to win, * false otherwise. */ private boolean horizontalRecursive(int player, int row) { } /** * Tests if the given player has enough coins connected horizontally * in the given row to win. * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param row a row number. * @pre. row >= 0 && row < Model.ROW * @return true if the given player has enough coins connected horizontally * in the given row to win, false otherwise. */ private boolean horizontal(int player, int row) { boolean won = false; int column = 0; int count = 0; while (column < Model.COLUMN && !won) { if (player == this.getSlot(row, column)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } column++; } 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.getSlot(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.getSlot(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.getSlot(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.getSlot(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.getSlot(r + i, c + i)) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } return won; } /** * Returns the column number of a randomly chosen column that is * not filled. * * @return the column number of a randomly chosen column that is * not filled. */ public int move() { Random random = new Random(System.currentTimeMillis()); int column; do { column = random.nextInt(Model.COLUMN); } while (this.isFilled(column)); return column; } }