Tutorial: Gomoku en Java (Parte 2)

En la Entrada anterior desarrollamos gran parte del juego Gomoku, pueden ver la entrada aquí:
Parte 1

En la parte 2 desarrollaremos lo restante del proyecto Gomoku. Recuerda que el código fuente descargable se encuentra al final del tutorial.


gomoku

Game.java

Esta clase sigue la lógica de que en el juego existe una tabla (Board), se puede inciar un nuevo juego, terminarlo, obtener un ganador, etc.

Atributos:
board.- De acceso privado y estático, es la tabla, solo puede haber una.




Constructor:
Inicializa la tabla proporcionado número de filas y columnas e inicia un nuevo juego.

Métodos:
  • isFinished: Método booleano para saber si el juego terminó por no movimientos disponibles.
  • startANewGame.- Limpia la tabla.
  • getWinner.- Invoca el método isThereAFiveChain de la clase board y retorna True o False si hay o no un ganador del color proporcionado.
  • place.- Invoca el método place de la clase board.
  • isCorrectStep.- Invoca el método isCorrectStep de la clase board.
  • getBoard.- Obtiene la tabla y sus valores actuales.



package model;

public class Game {
 private static Board board;
 
 public Game(int numberRows,int numberCols) {
  Game.board = new Board(numberRows,numberCols);
  startANewGame();
 }
 
  public boolean isFinished()
  {
   //The game fisnish when there are no more movements availables
   return !Game.board.isThereAtLeastOneSquareEmpty();
  }
  
  public void startANewGame(){
   Game.board.cleanTheBoard();
  }
  
  public boolean getWinner(StoneColor color)
  {
   return Game.board.isThereAFiveChain(color);
  }
  
  public void place(int row, int col ,StoneColor stoneColor)
  {
   Game.board.place(row, col, stoneColor);
  }
  
  public boolean isCorrectStep(int row, int col)
  {
   return Game.board.isCorrectStep(row, col);
  }

 public Board getBoard() {
  return board;
 }
}


GomokuFrame.java

Clase para dibujar el front-end,
gomoku board

Contiene varios paneles, textFields para contar movimientos y turno del jugador, esto es básicamente dibujar a través de código la imágen de arriba por lo que acortaré esa explicación.

Importante a resaltar:
En el constructor se crea el juego y la tabla por medio de la linea
game = new Game(numberRows, numberCols);

Método drawBoard, dibuja la tabla y agrega un actionListener a cada bloque, el actionListener es una clase que definiremos luego. Esto hace que se ejecute una acción o evento al presionar click sobre algún bloque.


package view;

import java.awt.*;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import model.Game;
import model.Square;
import controller.MyActionListener;

public class GomokuFrame extends JFrame {
 private JPanel panelBoard = new JPanel();
 private JPanel panelGame = new JPanel();
 private JPanel panelDetails = new JPanel();
 private JTextField fieldMovements = new JTextField("Movements: 0");
 private JTextField fieldPlayerTurn = new JTextField("Black player turn");
 private Game game;
 private int numberRows;
 private int numberCols;
 public List<Square> listSquares;
 
 public GomokuFrame(int numberRows, int numberCols) {
  this.numberRows = numberRows;
  this.numberCols = numberCols;
  
  game = new Game(numberRows, numberCols); //here it creates the list of squares
  listSquares = game.getBoard().getListSquares();
  initializeFrame();
  setContent();
 }

 private void initializeFrame() {
  setTitle("Gomoku");
  setSize(60*numberRows, 60*numberCols);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(EXIT_ON_CLOSE);
 }
 
 private void setContent() {
  panelGame.setLayout(new BorderLayout());
  add(panelGame);
  
  panelBoard.setLayout(new GridLayout(this.numberRows, this.numberCols));
  panelDetails.setLayout(new GridLayout(1, 0));
  
  panelGame.add(panelBoard, BorderLayout.CENTER);
  panelGame.add(panelDetails,BorderLayout.SOUTH);
  
  panelDetails.add(fieldMovements);
  panelDetails.add(fieldPlayerTurn);
  panelBoard.setBackground(Color.cyan);
  drawBoard();
 }
 
 //Draw Board
 private void drawBoard() {
  MyActionListener mal = new MyActionListener(game, this,fieldMovements,fieldPlayerTurn);
  for (Square s : listSquares) {
   panelBoard.add(s);
   s.addActionListener(mal);
  } 
 }
}


MyActionListener.java

Hacemos que esta clase implemente la interfaz ActionListener, La interfaz ActionListener sirve para recibir acciones de eventos. Cuando la acción de un evento ocurre (dar click sobre el bloque), el método actionPerformed de ese objeto es invocado.

Atributos:

  • counter.- Contador de movimientos.
  • game.- Contiene acceso a todos los métodos publicos de la clase Game.
  • playerColorTurn.- Quién es el jugador actual (White, Black).
  • frame.- Referencia al front-end para poder mostrar mensajes informativos y de diálogo.
  • fieldMovementes.- textField para mostrar la cantidad de movimientos actuales.
  • fieldPlayerTurn.- textField para mostrar de quién es el turno actual.

Contructor:
Inicializa atributos, nada fuera de lo común.

Métodos:

  • actionPerformed.- Esta es una sobre-escritrura (Override), estamos obligados a escribirla si o si. Aquí se escriben ciertas validaciones dependiendo del avance del juego.
  • askForRestartGame.- Muestra un mensaje de diálogo preguntando si desea jugar nuevamente o cerrar la aplicación.


package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JOptionPane;
import javax.swing.JTextField;

import model.Game;
import model.Square;
import model.StoneColor;
import view.GomokuFrame;

public class MyActionListener implements ActionListener {
 private int counter=1;
 private Game game;
 private StoneColor playerColorTurn;
 private GomokuFrame frame;
 private JTextField fieldMovements;
 private JTextField fieldPlayerTurn;
 
 public MyActionListener(Game game, GomokuFrame frame, JTextField fieldMovements, JTextField fieldPlayerTurn) {
  this.game = game;
  this.frame = frame;
  this.fieldMovements = fieldMovements;
  this.fieldPlayerTurn = fieldPlayerTurn;
 }
 
 @Override
 public void actionPerformed(ActionEvent e) {
  Square button = (Square) e.getSource();
  boolean isSucMovement = false;
  
  isSucMovement = game.isCorrectStep(button.getPositionOnBoardX(), button.getPositionOnBoardY());
  
  if(isSucMovement)
  {
   this.playerColorTurn = (counter%2==1)?StoneColor.Black:StoneColor.White;
   this.game.place(button.getPositionOnBoardX(), button.getPositionOnBoardY(), this.playerColorTurn);
   this.fieldPlayerTurn.setText(String.format("%s player turn", (counter%2==1)?StoneColor.White:StoneColor.Black));
  }
  else
   JOptionPane.showMessageDialog(frame, "Wrong movement, Try again please.", "Warning", JOptionPane.WARNING_MESSAGE);
  
  if (isSucMovement)
   ++counter;
  
  this.fieldMovements.setText("Movements: " + counter/2);
   
  //Get the Winner, if exists
  if (game.getWinner(playerColorTurn))
  {
   JOptionPane.showMessageDialog(frame, String.format("The Winner is: %s \nMovements: %d", 
           playerColorTurn, counter/2), "Information", 
           JOptionPane.INFORMATION_MESSAGE);
   askForRestartGame();
  }
  
  //The Game has finished if there are not more movements availables
  if (game.isFinished()){
   JOptionPane.showMessageDialog(frame, String.format("Game Finished! \nThere are not more movements availables"), "Information", 
     JOptionPane.INFORMATION_MESSAGE);
   
   askForRestartGame();
  }
 }
 
 private void askForRestartGame()
 {
  int reply = JOptionPane.showConfirmDialog(frame, String.format("Do you want to start a new Game?"), 
    "Information", JOptionPane.YES_NO_OPTION);
  
  if (reply == JOptionPane.YES_OPTION)
  {
   this.game.startANewGame();
   this.counter = 1;
   this.fieldMovements.setText("Movements: " + 0);
  }
  else
   this.frame.dispose();
 }
}


Main.java

Clase principal, solamente tenemos que instanciar un nuevo objeto de la clase GomokuFrame, asignarle número de filas y columnas y setear su visibilidad en True.


package view;

public class Main {
 public static void main(String[] args) {
  new GomokuFrame(10,10).setVisible(true);
 }
}

Compilar y Correr el proyecto

Verifica si tienes algún error en el código que no te permita correr el proyecto, corre el proyecto seleccionandolo, Run As/Java Application:

Run java application


Código fuente (Descaga)

Puedes descargar el código fuente dando click al siguiente enlace:


Gracias por tu atención, si tienes alguna pregunta o sugerencia escribe en la caja de comentarios de abajo. Saludos!.

Comentarios