Jogo de Damas em Java sem interface

Comecei o projeto tem uns 4 dias e travei na parte da criação da Dama/King e também estou com dúvidas se a construção desse código está legal, aceito qualquer dica relacionada as classes ou como otimizar este código também.

Segue o link para o repositório do Github caso queira pegar todos os arquivos:

Jogo de Damas

O código por enquanto é esse:

package program;

import java.util.Scanner;

import entities.Tabuleiro;

public class Dama {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		Tabuleiro tab = new Tabuleiro();
		
		boolean move = false;

		tab.createTable();

		tab.positioPieces();
		
		System.out.println("White plays first!");
		
		do {
			
			tab.showTable();
			
			
			if (move == false) {

				System.out.println("Impossible move! Insert Again:");

			}else {
				
				System.out.println("Please insert the column and then the line from 1 to 8:");
				
			}
			

			int piecex = sc.nextInt();
			int piecey = sc.nextInt();
			int movex = sc.nextInt();
			int movey = sc.nextInt();

			if (tab.checkMovement(piecex, piecey, movex, movey)) {

				if (tab.checkToEat(movex, movey, piecex, piecey)) {

					if (tab.doEatMovement(piecex, piecey, movex, movey)) {

						move = true;

					} else {

						move = false;

					}

				} else {

					if (tab.simpleMove(piecex, piecey, movex, movey) == true) {

						tab.doMovement(piecex, piecey, movex, movey);

						move = true;

					} else {

						move = false;

					}

				}
			}

			tab.checkWhoseRound();

			if (tab.getP() == 'w') {

				System.out.println("White's turn!");

			} else {

				System.out.println("Black's turn!");

			}

			tab.showTable();

		} while (tab.checkVictory() == false || move == false);

		sc.close();
	}

}

`package entities;

public class Tabuleiro {

	private Integer rodada = 0;
	private Integer rodadabkp = 0;
	private String table = "";
	private char[][] matriz = new char[8][8];
	private char P = ' ';
	private char OP = ' ';

	// Get the
	public char getP() {
		return P;
	}

	// Table constructor
	public Tabuleiro() {
	}

	// Creating the board matrix
	public void createTable() {

		for (int i = 0; i < this.matriz.length; ++i) {
			for (int j = 0; j < this.matriz.length; ++j) {
				this.matriz[i][j] = '-';
			}
		}

	}

	// Function to position the pieces over the board
	public void positioPieces() {

		for (int i = 0; i < this.matriz.length; ++i) {
			int w;
			if (i != 0 && i != this.matriz.length - 2) {
				if (i != this.matriz.length - 1 && i != 1) {
					for (w = 0; w < this.matriz.length; ++w) {
						this.matriz[i][w] = '-';
					}
				} else {
					for (w = 1; w < this.matriz.length; w += 2) {
						if (i == this.matriz.length - 1) {
							this.matriz[i][w] = 'w';
						} else {
							this.matriz[i][w] = 'b';
						}
					}
				}
			} else {
				for (w = 0; w < this.matriz.length; w += 2) {
					if (i == this.matriz.length - 2) {
						this.matriz[i][w] = 'w';
					} else {
						this.matriz[i][w] = 'b';
					}
				}
			}
		}

		this.showTable();
	}

	// Function to format the board
	public void showTable() {

		String msg = "";
		String columns = "   ";

		int i;
		for (i = 0; i < this.matriz.length; ++i) {
			columns = columns + i + " ";
		}

		columns = columns + "<- Y";

		for (i = 0; i < this.matriz.length; ++i) {
			msg = msg + " " + i + " ";

			for (int j = 0; j < this.matriz.length; ++j) {
				msg = msg + this.matriz[i][j] + " ";
			}

			msg = msg + "\n";
		}

		msg = msg + " ^\n |\n X";
		this.table = columns + "\n" + msg;
		System.out.println(this.table);
	}

	// Function to check if it's black or white's turn with pair or odd system
	public void checkWhoseRound() {

		if (this.rodada % 2 == 0) {
			this.P = 'w';
			this.OP = 'b';
		} else {
			this.P = 'b';
			this.OP = 'w';
		}
	}

	// Function to change the pieces in matrix
	public void doMovement(int piecex, int piecey, int movex, int movey) {

		checkWhoseRound();

		// Replacing the piece house to empty and then replacing the destiny to the
		// piece
		this.matriz[piecex][piecey] = '-';
		this.matriz[movex][movey] = this.P;

		// Assigning +1 to the round to change the player
		this.rodada = this.rodada + 1;
		rodadabkp = rodada;

	}

	// Function to check if the movement is possible or not
	public boolean checkMovement(int piecex, int piecey, int movex, int movey) {

		checkWhoseRound();

		if (piecex >= 0 && piecex <= 7 && piecey >= 0 && piecey <= 7) {

			// Checking if the movement is within the limits of the matrix
			if (movex >= 0 && movex <= 7 && movey >= 0 && movey <= 7) {
				if (this.matriz[piecex][piecey] != this.P) {
					System.out.println("1");
					System.out.println("Impossible move!Insert Again:");
					return false;

					// Checking if the move house is empty
				} else if (this.matriz[movex][movey] != '-') {

					System.out.println("2");
					System.out.println("Impossible move!Insert Again:");
					return false;

				}

				return true;

			} else {

				return false;
			}
		} else {

			return false;
		}

	}

	// Function to check if the simple move is possible
	public boolean simpleMove(int piecex, int piecey, int movex, int movey) {

		if (itsKing(piecex, piecey) == true) {
			
			

		} else {

			if (this.P != 'w') {
				System.out.println("3");

				// Checking if it is a diagonal movement
				if (Math.abs(movex - piecex) == 1 && Math.abs(movey - piecey) == 1) {

					// Checking if the piece is moving forward
					if (piecex - movex < 0) {

						// Calling the function to do the movement
						return true;

					} else {

						return false;

					}

				} else {

					System.out.println("Impossible move! Insert Again:");
					return false;
				}

				// Checking if it is a diagonal movement
			} else if (Math.abs(movex - piecex) == 1 && Math.abs(movey - piecey) == 1) {

				// Checking if the piece is moving forward
				if (piecex - movex > 0) {

					return true;

				} else {

					System.out.println("10");
					System.out.println("Impossible move! Insert Again:");
					return false;

				}

			} else {
				return false;
			}
		}
		
		return false;
	}

	// Function to check if it's a eating movement
	public boolean checkToEat(int movex, int movey, int piecex, int piecey) {

		checkWhoseRound();

		if (itsKing(piecex, piecey) == true) {

		} else {

			for (int i = -1; i <= 1; ++i) {
				for (int j = -1; j <= 1; ++j) {
					if (i != 0 || j != 0) {
						try {

							// Here I used try because I can't find a way to check if the movement
							if (this.matriz[piecex + i][piecey + j] == this.OP && piecex + i + i == movex
									&& piecey + j + j == movey) {

								return true;
							}

						} catch (Exception e) {

						}

					}

				}
			}
		}

		System.out.println("8");
		return false;
	}

	// Function to do the eating movement
	public boolean doEatMovement(int piecex, int piecey, int movex, int movey) {

		int i = 0, j = 0;

		if (piecex - movex > 0) {

			i = -1;

		} else {

			i = 1;

		}

		if (piecey - movey > 0) {

			j = -1;

		} else {

			j = 1;

		}

		this.matriz[piecex][piecey] = '-';
		this.matriz[piecex + i][piecey + j] = '-';
		this.matriz[movex][movey] = this.P;

		// Checking if the piece have more options of pieces to eat after a eating
		// movement
		if (this.eatAgain(movex, movey) == true) {

			return true;
		} else {

			// Assigning +1 to the round to change the player
			this.rodada = this.rodada + 1;
			rodadabkp = rodada;
			return true;
		}

	}

	// Function to check Victory
	public boolean checkVictory() {

		checkWhoseRound();

		int contw = 0;
		int contb = 0;
		int contbm = 0;
		int contwm = 0;

		int i;
		int j;

		// Counting the pieces to check if it don't have any more
		for (i = 0; i < this.matriz.length; ++i) {
			for (j = 0; j < this.matriz.length; ++j) {
				if (this.matriz[i][j] == 'w') {
					contw++;
				} else if (this.matriz[i][j] == 'b') {
					contb++;
				}
			}
		}

		if (contw == 0) {

			System.out.println("White wins!");
			return true;

		} else if (contb == 0) {
			System.out.println("Black wins!");
			return true;

		}

		// Checking if the black or white pieces don't have more possible movements
		for (i = 0; i < this.matriz.length; ++i) {
			for (j = 0; j < this.matriz.length; ++j) {

				if (this.matriz[i][j] != '-') {

					for (int wi = -1; wi < 2; ++wi) {
						for (int wj = -1; wj < 2; ++wj) {

							if (this.matriz[i][j] == 'w') {

								if (this.rodada % 2 != 0) {

									rodada++;

								}

								if (checkMovement(i, j, i + wi, j + wj) == true) {

									if (checkToEat(i + wi, j + wj, i, j) == true) {

										contwm++;

									} else {

										if (simpleMove(i, j, i + wi, j + wj) == true) {

											contwm++;

										}

									}
								}

							} else if (this.matriz[i][j] == 'b') {

								if (this.rodada % 2 == 0) {

									rodada++;

								}

								if (checkMovement(i, j, i + wi, j + wj) == true) {

									if (checkToEat(i + wi, j + wj, i, j) == true) {

										System.out.println("Aqui chegou 3");
										contbm++;

									} else {

										if (simpleMove(i, j, i + wi, j + wj) == true) {

											System.out.println("Aqui chegou 4");
											contbm++;

										}

									}
								}
							}

						}
					}
				}

			}
		}

		resetRound();

		// Checking if the pieces has no movements
		if (contwm == 0) {

			System.out.println("Black Wins");
			return true;
		} else if (contbm == 0) {
			System.out.println("White Wins");
			return true;
		}

		return false;

	}

	// Function to check if the piece have more options of pieces to eat after a
	// eating movement
	public boolean eatAgain(int movex, int movey) {

		for (int i = -1; i <= 1; ++i) {
			for (int j = -1; j <= 1; ++j) {
				if (i != 0 || j != 0) {
					if (movex + i >= 1 || movey + i >= 1 || movex + i <= 6 || movey + i <= 6) {
						try {
							if (this.matriz[movex + i][movey + j] == this.OP
									&& this.matriz[movex + i + i][movey + j + j] == '-') {
								return true;
							}
						} catch (Exception e) {

						}
					}

				}

			}
		}

		return false;
	}

	// Function to reset the round with the bkp
	public void resetRound() {

		rodada = rodadabkp;

	}

	// Function to check if the piece is a king
	public boolean itsKing(int piecex, int piecey) {

		checkWhoseRound();

		if (this.P == 'w') {
			if (matriz[piecex][piecey] == 'W') {

				return true;
			}
		} else {
			if (matriz[piecex][piecey] == 'B') {

				return true;
			}

		}

		return false;
	}

}`

Dica, não compare usando == true ou == false, você já está comparando um valor ou expressão booleana, utilize simplesmente codição ou !condição.

Por exemplo:

  • ao invés de testar if (tab.simpleMove(piecex, piecey, movex, movey) == true)
    faça somente if (tab.simpleMove(piecex, piecey, movex, movey))

  • ao invés de testar if (move == false)
    faça somente if (!move)

Beleza, estava usando dessa forma, mas estava dando erro no código e pensei que fosse por conta disso. E a questão das classes? Você acha que é o suficiente está organizado?

Olá!

Uma coisa que você pode fazer pra começar é retirar a coisa toda que esta no método main() e passar para dentro da classe Dama.
Exemplo:

public class Dama {
    public void iniciar() {
       // Código que está no método main()
   }
}

A sua classe principal (main class) ficaria assim:

// O nome da classe poderia ser simplesmente Main.
public class Aplicacao {
     public static void main(String[] args) {
            Dama dama = new Dama();
            dama.iniciar();
     }
}

A partir daí já daria para começar a refatorar o método iniciar(), poderia utilizar alguns métodos menores privados dentro da classe Dama, colocar criação da estrutura de dados no início da classe e etc…

P.S Minha indicação é apenas uma sugestão para iniciar o exercício de refatoração.

  • Sempre que for iniciar uma sessão de refatoração, salve uma versão. As vezes ao tentar refatorar a pessoa pode acabar danificando o sistema e não conseguindo voltar ao status anterior.

[]’

Já estava pensando em fazer isso, mas não dessa forma, obrigado pela dica! Agora só tenho mais uma pergunta, estou quebrando a cabeça já fiz alguns testes de mesa para tentar descobrir, mas não consigo criar uma lógica para testar o movimento da dama, teria alguma sugestão? Algum outro modo de eu pensar, considerando que estou usando matrizes?

Acho que seria interessante ver um projeto pronto para ter ideias e “inspiração”. Por exemplo:

Um detalhe interessante é que o tabuleiro foi otimizado. Por exemplo, embora o tabuleiro tenha 64 casas, as peças só ficam sobre as casas pretas. Portanto dá para ignorar as casas brancas, então vc só precisa representar as 32 casas pretas.

Além disso ele leva a otimização ao extremo, usando 3 bits (não é bytes, é bits) para cada casa (pois em 3 bits é possível representar os 5 estados possíveis: vazio, peça branca ou preta, e dama branca ou preta).

Enfim, dê uma olhada também nas classes que verificam os movimentos e vc pode tirar ideias e adaptar para o seu código.