package lab.games; import java.util.HashMap; import java.util.Map; /** * The Model of the GUI. */ public class Model { private int[][] board; // board[r][c]: whose token in r-th row and c-th column private int level; /** * 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; /** * Maximal value of a board. */ private static int MAX_VALUE = 69; /** * Initializes this model. * * @param level level of difficulty. * @pre. level >= 0 */ public Model(int level) { this.setBoard(new int[Model.ROW][Model.COLUMN]); this.setLevel(level); } /** * Returns the board. * * @return the board. */ private int[][] getBoard() { return this.board; } /** * Sets the board to the given board. * * @param board the board. */ private void setBoard(int[][] board) { this.board = board; } /** * Returns the level. * * @return the level. */ private int getLevel() { return this.level; } /** * Sets the level to the given level. * * @param level the level. * @pre. level >= 0 */ private void setLevel(int level) { this.level = level; } /** * Tests if all slots of the board are filled. * * @return true if all slots are filled, false otherwise. */ public boolean isFilled() { return Model.isFilled(this.getBoard()); } /** * Tests if all slots of the given board are filled. * * @return true if all slots of the given board are filled, * false otherwise. */ private static boolean isFilled(int[][] board) { boolean isFilled = true; for (int column = 0; column < Model.COLUMN && isFilled; column++) { isFilled = Model.isFilled(column, board); } return isFilled; } /** * Tests if all slots of the given column are 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. */ private boolean isFilled(int column) { return Model.isFilled(column, this.getBoard()); } /** * Tests if all slots of the given column of the given board are filled. * * @param column the number of the column. * @pre. 0 <= colummn < Model.COLUMN * @param board the slots. * @pre. board != null * @return true if all slots of the given column of the given board are filled, * false otherwise. */ private static boolean isFilled(int column, int[][] board) { return board[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 { return Model.drop(column, player, this.getBoard()); } /** * Drop a coin of the given player in the specified column of the given board. * * @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 * @param board the slots. * @pre. board != null * @throws Exception if the given column is filled. */ private static int drop(int column, int player, int[][] board) throws Exception { if (Model.isFilled(column, board)) { throw new Exception("You cannot drop a coin in this column"); } else { int row = Model.ROW - 1; while (board[row][column] != Model.EMPTY) { row--; } board[row][column] = player; return row; } } /** * 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 Model.hasWon(player, this.getBoard()); } /** * Determine if the given player has won for the given board. * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return true if the given player has won for the given board, * false otherwise. */ private static boolean hasWon(int player, int[][] board) { return Model.horizontal(player, board) || Model.vertical(player, board) || Model.diagonalDown(player, board) || Model.diagonalUp(player, board); } /** * Tests if the given player has enough coins connected horizontally to win * for the given board. * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return true if the given player has enough coins connected horizontally * to win for the given board, false otherwise. */ private static boolean horizontal(int player, int[][] board) { boolean won = false; for (int row = 0; row < Model.ROW && !won; row++) { int column = 0; int count = 0; while (column < Model.COLUMN && !won) { if (player == board[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 * for the given board. * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return true if the given player has enough coins connected vertically to win * for the given board, false otherwise. */ private static boolean vertical(int player, int[][] board) { boolean won = false; for (int column = 0; column < Model.COLUMN && !won; column++) { int row = 0; int count = 0; while (row < Model.ROW && !won) { if (player == board[row][column]) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } row++; } } return won; } /** * Tests if the given player has enough coins connected along a diagonal * downwards to win for the given board. * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return true if the given player has enough coins connected along a * diagonal downwards to win for the given board, false otherwise. */ private static boolean diagonalDown(int player, int[][] board) { boolean won = false; for (int row = Model.CONNECTED; row < Model.ROW && !won; row++) { int column = 0; int i = 0; int count = 0; while (row - i >= 0 & column + i < Model.COLUMN && !won) { if (player == board[row - i][column + i]) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } for (int column = 0; column <= Model.COLUMN - Model.CONNECTED && !won; column++) { int row = Model.ROW - 1; int i = 0; int count = 0; while (row - i >= 0 & column + i < Model.COLUMN && !won) { if (player == board[row - i][column + 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 for the given board. * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return true if the given player has enough coins connected along a * diagonal upwards to win for the given board, false otherwise. */ private static boolean diagonalUp(int player, int[][] board) { boolean won = false; for (int row = 0; row <= Model.ROW - Model.CONNECTED && !won; row++) { int column = 0; int i = 0; int count = 0; while (row + i < Model.ROW & column + i < Model.COLUMN && !won) { if (player == board[row + i][column + i]) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } for (int column = 0; column <= Model.COLUMN - Model.CONNECTED && !won; column++) { int row = 0; int i = 0; int count = 0; while (row + i < Model.ROW & column + i < Model.COLUMN && !won) { if (player == board[row + i][column + i]) { count++; won = (count >= Model.CONNECTED); } else { count = 0; } i++; } } return won; } /** * For the given board, return the number of combinations * (CONNECTED consecutive slots either horizontally, vertically or * diagonally) that do not contain a coin of the given player (that is, * they either do not contain a coin or contain a coin of another player). * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return the number of combinations of the given board that do not * contain a coin of the given player. */ private static int count(int player, int[][] board) { } /** * For the given board, return the number of horizontal combinations * (CONNECTED consecutive slots horizontally) that do not contain a coin * of the given player (that is, they either do not contain a coin or * contain a coin of another player). * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return the number of horizontal combinations that do not contain a coin of * the given player. */ private static int horizontalCount(int player, int[][] board) { } /** * For the given board, return the number of vertical combinations * (CONNECTED consecutive slots vertically) that do not contain a coin * of the given player (that is, they either do not contain a coin or * contain a coin of another player). * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return the number of vertical combinations that do not contain a coin of * the given player. */ private static int verticalCount(int player, int[][] board) { } /** * For the given board, return the number of diagonally downward combinations * (CONNECTED consecutive slots diagonally downward) that do not contain a coin * of the given player (that is, they either do not contain a coin or * contain a coin of another player). * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return the number of diagonally downward combinations that do not * contain a coin of the given player. */ private static int diagonalDownCount(int player, int[][] board) { } /** * For the given board, return the number of diagonally upward combinations * (CONNECTED consecutive slots diagonally upward) that do not contain a coin * of the given player (that is, they either do not contain a coin or * contain a coin of another player). * * @param player a player. * @pre. player == Model.PLAYER || player == Model.COMPUTER * @param board the board. * @pre. board != null * @return the number of diagonally upward combinations that do not * contain a coin of the given player. */ private static int diagonalUpCount(int player, int[][] board) { } /** * Returns a copy of the given board. * * @param board the board. * @pre. board != null * @return a copy of the given board. */ private static int[][] copy(int[][] board) { int[][] copy = new int[Model.ROW][Model.COLUMN]; for (int row = 0; row < Model.ROW; row++) { for (int column = 0; column < Model.COLUMN; column++) { copy[row][column] = board[row][column]; } } return copy; } /** * Returns the column number of the column that is not filled and has * the best value, given that it is the computer's turn. If multiple * columns have the best value, the smallest one is returned. * * @pre. !isFilled() * @return the column number of the column that is not filled and has * the best value, given that it is the computer's turn. */ public int move() { } /** * Returns the value of the given board for the given player and level. * * @param board the board. * @pre. board != null * @param level the number of moves that are "looked ahead". * @pre. level >= 0 * @param player the player whose turn it is. * @pre, player == Model.PLAYER || Model.COMPUTER */ private static int value(int[][] board, int level, int player) { } /** * Returns a string representation of the given board. * * @param board the board. * @pre. board != null * @return A string representation of the given board board. */ public static String toString(int[][] board) { String representation = ""; for (int row = 0; row < Model.ROW; row++) { String rowRepresentation = ""; for (int column = 0; column < Model.COLUMN; column++) { if (board[row][column] == Model.EMPTY) { rowRepresentation += "."; } else { rowRepresentation += board[row][column]; } } representation = representation + "\n" + rowRepresentation; } return representation; } }