diff --git a/src/ConsoleRenderer.java b/src/ConsoleRenderer.java index 8388013..547179e 100644 --- a/src/ConsoleRenderer.java +++ b/src/ConsoleRenderer.java @@ -1,16 +1,48 @@ - public class ConsoleRenderer extends GomokuRenderer { - public ConsoleRenderer() {} + public ConsoleRenderer() { + } @Override public void init(GomokuGame game) { - System.out.println("Console Renderer initialized."); + this.game = game; + System.out.println("ConsoleRenderer initialized"); } @Override public void update() { - // TODO: draw the board + // Print the board to the console + + String[] board = game.getBoard().toString().split("\n"); + String horizontalLine = getHorizontalLine(); + int width = game.getBoard().getWidth(); + int height = game.getBoard().getHeight(); + + // Print a separator line, followed by the game infos + System.out.println(horizontalLine); + System.out.println("|" + String.format(" %-" + (width - 1) + "s", "Gomoku Game!") + "|"); + // System.out.println("Current player: " + game.getCurrentPlayer().getName()); + // System.out.println("Number of tokens left: " + game.getCurrentPlayer().getTokensLeft()); + + // Print the board + System.out.println(horizontalLine); + for (int i = 0; i < height; i++) { + System.out.print("|"); + System.out.print(board[i]); + System.out.println("|"); + } + System.out.println(horizontalLine); + + } + + private String getHorizontalLine() { + StringBuilder sb = new StringBuilder(); + sb.append("+"); + for (int i = 0; i < game.getBoard().getWidth(); i++) { + sb.append("-"); + } + sb.append("+"); + return sb.toString(); } } diff --git a/src/GomokuAI.java b/src/GomokuAI.java index 33fceb8..e3a8a2e 100644 --- a/src/GomokuAI.java +++ b/src/GomokuAI.java @@ -1,16 +1,15 @@ +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; -import java.util.HashMap; public class GomokuAI extends Player { // ------------------Constructors-------------------------- /** - * The constructor of the Human. - * - * @param name The name of the player. + * The constructor of the GomokuAI. + * @param name The name of the player. * @param color The color of the player. */ public GomokuAI(String name, Color color) { diff --git a/src/GomokuBoard.java b/src/GomokuBoard.java index 2bd412b..6f469be 100644 --- a/src/GomokuBoard.java +++ b/src/GomokuBoard.java @@ -32,13 +32,13 @@ public class GomokuBoard{ System.out.println(Cardinal.NE.inverse()); System.out.println(test); - test.expandBoardv2(Cardinal.N); + test.expandBoard(Cardinal.N); System.out.println(test); - test.expandBoardv2(Cardinal.S); + test.expandBoard(Cardinal.S); System.out.println(test); - test.expandBoardv2(Cardinal.W); + test.expandBoard(Cardinal.W); System.out.println(test); - test.expandBoardv2(Cardinal.SE); + test.expandBoard(Cardinal.SE); System.out.println(test); } @@ -105,7 +105,23 @@ public class GomokuBoard{ } //------------------Gets-------------------------- - + + /** + * Returns the width of the board. + * @return The width of the board. + */ + public int getWidth() { + return this.boardWidth; + } + + /** + * Returns the height of the board. + * @return The height of the board. + */ + public int getHeight() { + return this.boardHeight; + } + /** * This method get a cell in specific position in the board. * @param x The position x on the board. @@ -165,6 +181,25 @@ public class GomokuBoard{ return output; } + + //------------------Gets-------------------------- + + /** + * Set the width of the board. + * @param width The new width of the board. + */ + public void setWidth(int width) { + this.boardWidth = width; + } + + /** + * Set the height of the board. + * @param height The new height of the board. + */ + public void setHeight(int height) { + this.boardHeight = height; + } + //------------------Methods-------------------------- /** @@ -202,112 +237,6 @@ public class GomokuBoard{ return max; } - /** - * This method create one line/column in a specific direction. This method is used in expandBoard, it's no recommended to - * used it in other context. - * @param act Is the cell of the start of the line/column. - * @param top Is the cell of the start of the line/column already existing. - * @param topDir The direction of the line top in relation of the line/column we create. - * @param m The direction topDir - 1. - * @param p The direction topDir + 1. - * @param dir Direction where to add the next cell. - * @param maxLen Number of cell ton gen. - */ - private void genLineOrColumn(GomokuCell act, GomokuCell top, Cardinal topDir, Cardinal m, Cardinal p, Cardinal dir, int maxLen){ - for (int i = 0; i < maxLen; i++) { - if (top != null) { - GomokuCell.link(act, top.getNeighbour(topDir),m); - GomokuCell.link(act, top, topDir); - top = top.getNeighbour(dir); - GomokuCell.link(act, top , m); - - } - if (i != maxLen -1 ){ - GomokuCell right = new GomokuCell(Color.NIL); - GomokuCell.link(act, right, dir); - act = right; - } - } - - } - - /** - * This method expand the board. - * @param direction Is the direction where the method expand the board. - */ - public void expandBoard(Cardinal direction){ - switch (direction) { - case Cardinal.SE: - this.expandBoard(Cardinal.S); - this.expandBoard(Cardinal.E); - return; - - case Cardinal.NE: - this.expandBoard(Cardinal.N); - this.expandBoard(Cardinal.E); - return; - - case Cardinal.SW: - this.expandBoard(Cardinal.S); - this.expandBoard(Cardinal.W); - return; - - case Cardinal.NW: - this.expandBoard(Cardinal.N); - this.expandBoard(Cardinal.W); - return; - - default: - break; - } - - List cardinals = Arrays.asList(Cardinal.values()); - Cardinal topDirection = cardinals.get((cardinals.indexOf(direction) + 4)%8); - - GomokuCell act = new GomokuCell(Color.NIL); - int maxLen = 0; - GomokuCell top = null; - GomokuCell newOrigin = null; - switch (direction) { - case Cardinal.N: - top = this.get(0, 0); - maxLen = this.boardWidth; - newOrigin = act; - this.genLineOrColumn(act, top, topDirection, Cardinal.SW, Cardinal.SE, Cardinal.E, maxLen); - this.boardHeight += 1; - break; - - case Cardinal.W: - top = this.get(0,0); - maxLen = this.boardHeight; - newOrigin = act; - this.genLineOrColumn(act, top, topDirection, Cardinal.NE, Cardinal.SE, Cardinal.S, maxLen); - this.boardWidth += 1; - break; - - case Cardinal.S: - top = this.get(this.boardHeight-1, 0); - maxLen = this.boardWidth; - newOrigin = this.get(0, 0); - this.genLineOrColumn(act, top, topDirection, Cardinal.NW, Cardinal.NE, Cardinal.E, maxLen); - this.boardHeight += 1; - break; - - case Cardinal.E: - top = this.get(0, this.boardWidth-1); - maxLen = this.boardHeight; - newOrigin = this.get(0, 0); - this.genLineOrColumn(act, top, topDirection, Cardinal.NW, Cardinal.SW, Cardinal.S, maxLen); - this.boardWidth += 1; - break; - - default: - throw new IllegalStateException("Why are you here ?"); - } - this.firstCell = newOrigin; - } - - /** * Expands the board in the specified direction. * This method is used to add a new row, column, or both to the board. @@ -315,16 +244,15 @@ public class GomokuBoard{ * It also updates the board dimensions accordingly. * @param direction The cardinal direction in which to expand the board. * @see Cardinal - * @version 2.0 */ - public void expandBoardv2(Cardinal direction) { + public void expandBoard(Cardinal direction) { // for composed directions, expand in both components // e.g. SE -> expand in S and E if ((direction.asInt() % 2) != 0) { // if the direction is not even, it is a composed direction // call the same function in both components - this.expandBoardv2(direction.rotate(-1)); - this.expandBoardv2(direction.rotate(1)); + this.expandBoard(direction.rotate(-1)); + this.expandBoard(direction.rotate(1)); return; } diff --git a/src/GomokuGame.java b/src/GomokuGame.java index 08ca719..d2a74c6 100644 --- a/src/GomokuGame.java +++ b/src/GomokuGame.java @@ -1,10 +1,10 @@ + +import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Random; -import java.io.IOException; -import java.io.BufferedReader; public class GomokuGame { @@ -15,10 +15,10 @@ public class GomokuGame { private Player player1; private Player player2; - private int boardWidth; - private int boardHeight; private GomokuBoard board; + private GomokuRenderer renderer; + Color colorP1; int currP; int nbTokens1, nbTokens2; @@ -27,15 +27,11 @@ public class GomokuGame { // Test GomokuGame g = new GomokuGame(); System.out.println(g.load(Path.of(".cache/test.dat"))); - System.out.println(g.getBoard()); - System.out.println(g.save(Path.of(".cache/save.dat"))); - - for (int i = 0; i < g.boardHeight; ++i) { - for (int j = 0; j < g.boardWidth; ++j) { - System.out.print(g.getBoard().get(i, j)); - } - System.out.println(); - } + g.renderer = new ConsoleRenderer(); + g.renderer.init(g); + g.renderer.update(); + g.board.expandBoard(Cardinal.SE); + g.renderer.update(); } public void newGame(boolean bot, String name1, String name2) { @@ -64,6 +60,29 @@ public class GomokuGame { public void startGame() { } + /** + * Place the token on the cell where the player play. + * @param turn the turn of the player. + */ + public void play(int turn) { + + GomokuCell cellToPlay = null; + switch (turn) { + case 1: + cellToPlay = player1.chooseMove(board); + break; + case 2: + cellToPlay = player2.chooseMove(board); + break; + default: + throw new IllegalArgumentException("Invalid turn: " + turn); + } + + cellToPlay.setState(colorP1); + } + + + public boolean save(Path filename) { // save the game state to the file // 1. Open the file @@ -81,12 +100,18 @@ public class GomokuGame { try (BufferedWriter writer = Files.newBufferedWriter(filename)) { // Write the first line writer.write(String.format("%d %d %s %d %d %d%n", - this.boardWidth, this.boardHeight, colorP1, currP, nbTokens1, nbTokens2)); + this.getBoard().getWidth(), + this.getBoard().getHeight(), + colorP1, + currP, + nbTokens1, + nbTokens2 + )); // Write the board - for (int i = 0; i < boardHeight; ++i) { - for (int j = 0; j < boardWidth; ++j) { - char c; + for (int i = 0; i < this.getBoard().getHeight(); ++i) { + for (int j = 0; j < this.getBoard().getWidth(); ++j) { + char c = ' '; switch (board.get(i, j).getState()) { case BLACK: c = 'X'; @@ -193,8 +218,6 @@ public class GomokuGame { } // Initialize the board with the read values - this.boardWidth = w; - this.boardHeight = h; this.board = new GomokuBoard(w, h, colors); return true; diff --git a/src/RenderBoard.java b/src/RenderBoard.java index a406c06..f184c3b 100644 --- a/src/RenderBoard.java +++ b/src/RenderBoard.java @@ -3,13 +3,32 @@ import java.awt.Graphics; class RenderBoard { - private int width; - private int height; - private int[][] boardState; // Example representation of the board state + private int boardWidth; + private int boardHeight; + public int renderWidth; + public int renderHeight; + private int cellSize; + private int borderThickness; + // private int[][] boardState; - public RenderBoard(int width, int height) { - this.width = width; - this.height = height; + public RenderBoard(int width, int height, int renderWidth, int renderHeight) { + this.boardWidth = width; + this.boardHeight = height; + this.renderWidth = renderWidth; + this.renderHeight = renderHeight; + this.borderThickness = 5; + int cellWidth = renderWidth / width; + int cellHeight = renderHeight / height; + this.cellSize = Math.min(cellWidth, cellHeight); + } + + public RenderBoard(int renderWidth, int renderHeight) { + this( + GomokuGame.DEFAULT_BOARD_WIDTH, + GomokuGame.DEFAULT_BOARD_HEIGHT, + renderWidth, + renderHeight + ); } public void update(GomokuGame game) { @@ -17,17 +36,59 @@ class RenderBoard { // This method should be called whenever the game state changes } - public void drawBoard(Graphics g, int x, int y, int w, int h) { - // Draw the board here + public void drawBoard(Graphics g, int x, int y) { + // Draw the global border g.setColor(Color.LIGHT_GRAY); - int cellSize = w / this.width; + g.fillRect( + x, + y, + this.renderWidth + 2 * this.borderThickness, + this.renderHeight + 2 * this.borderThickness + ); + g.setColor(Color.WHITE); + g.fillRect( + x + this.borderThickness, + y + this.borderThickness, + this.renderWidth, + this.renderHeight + ); - for (int i = 0; i < this.width; i++) { - for (int j = 0; j < this.height; j++) { - g.drawRect(x + i * cellSize, y + j * cellSize, cellSize, cellSize); - // Draw the tokens here - g.fillOval(x + i * cellSize, y + j * cellSize, cellSize, cellSize); + int i, j; + int cy = y + this.borderThickness; + for (i = 0; i < this.boardHeight; i++) { + int cx = x + this.borderThickness; + for (j = 0; j < this.boardWidth; j++) { + // Draw the border + g.setColor(Color.LIGHT_GRAY); + g.fillRect( + cx, + cy, + this.cellSize, + this.cellSize + ); + g.setColor(Color.WHITE); + g.fillRect( + cx + this.borderThickness, + cy + this.borderThickness, + this.cellSize - 2 * this.borderThickness, + this.cellSize - 2 * this.borderThickness + ); + // Draw the cell + this.drawToken(g, x, y, Color.BLUE); + cx += this.cellSize; } + cy += this.cellSize; } } + + public void drawToken(Graphics g, int x, int y, Color color) { + // Draw the token at the specified position + g.setColor(color); + g.fillRect( + x + 2 * this.borderThickness, + y + 2 * this.borderThickness, + cellSize - 2 * borderThickness, + cellSize - 2 * borderThickness + ); + } } \ No newline at end of file diff --git a/src/SwingRenderer.java b/src/SwingRenderer.java index 30b1670..444981d 100644 --- a/src/SwingRenderer.java +++ b/src/SwingRenderer.java @@ -50,7 +50,7 @@ class RenderCanvas extends JPanel { public RenderCanvas() { setBorder(BorderFactory.createLineBorder(Color.black)); setBackground(Color.white); - board = new RenderBoard(8, 8); // Example board size + board = new RenderBoard(15, 15, 600, 600); } public Dimension getPreferredSize() { @@ -62,11 +62,9 @@ class RenderCanvas extends JPanel { int midX = getWidth() / 2; int midY = getHeight() / 2; - int boardWidth = 400; // Example board width - int boardHeight = 400; // Example board height - int x = midX - (boardWidth / 2); - int y = midY - (boardHeight / 2); - board.drawBoard(g, x, y, boardWidth, boardHeight); + int x = midX - (this.board.renderWidth / 2); + int y = midY - (this.board.renderHeight / 2); + board.drawBoard(g, x, y); } public void draw(GomokuGame game) {