autoplayer not working bu the rest is
This commit is contained in:
parent
fd9f2cce62
commit
4f71803aa7
|
|
@ -32,4 +32,4 @@ public class AutoPlayer {
|
||||||
return possibleMoves.get(random.nextInt(possibleMoves.size()));
|
return possibleMoves.get(random.nextInt(possibleMoves.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,179 +1,257 @@
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Stack;
|
import java.lang.Math;
|
||||||
|
|
||||||
public class Board {
|
public class Board {
|
||||||
|
|
||||||
private int cNum;
|
private int cNum;
|
||||||
private int lNum;
|
private int lNum;
|
||||||
private ArrayList<Piece> Pieces;
|
private Piece[][] cells;
|
||||||
private Stack<Move> moveHistory = new Stack<>();
|
Piece selectedCell;
|
||||||
|
private ArrayList<Move> moveHistory = new ArrayList<>();
|
||||||
|
public Piece enPassantTargetPawn = null;
|
||||||
|
|
||||||
|
int turnNumber = 0;
|
||||||
|
|
||||||
|
|
||||||
public Board(int colNum, int lineNum) {
|
public Board(int colNum, int lineNum) {
|
||||||
cNum = colNum;
|
cNum=colNum;
|
||||||
lNum = lineNum;
|
lNum=lineNum;
|
||||||
Pieces = new ArrayList<>();
|
cells = new Piece[cNum][lNum]; // creation du tableau de pieces
|
||||||
|
selectedCell=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
return cNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return lNum;
|
return lNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTurnNumber() {
|
public int getHeight() {
|
||||||
return turnNumber;
|
return cNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getTurnNumber() {
|
||||||
|
return turnNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isTurnWhite() {
|
public boolean isTurnWhite() {
|
||||||
return turnWhite;
|
return getTurnNumber() % 2 == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
|
||||||
Piece existing = null;
|
public void setPiece(PieceType type, boolean isWhite, int x, int y) {
|
||||||
|
Piece newPiece = new Piece(type, isWhite, x, y);
|
||||||
for (Piece piece : Pieces) {
|
cells[x][y] = newPiece;
|
||||||
if (piece.getX() == x && piece.getY() == y) {
|
|
||||||
existing = piece;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existing != null) {
|
|
||||||
Pieces.remove(existing);
|
|
||||||
}
|
|
||||||
|
|
||||||
Piece newPiece = new Piece(x, y, isWhite, type);
|
|
||||||
Pieces.add(newPiece);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void populateBoard() {
|
public void populateBoard() {
|
||||||
Pieces.add(new Piece(0, 0, false, PieceType.Rook));
|
|
||||||
Pieces.add(new Piece(1, 0, false, PieceType.Knight));
|
final int startWhite = 0;
|
||||||
Pieces.add(new Piece(2, 0, false, PieceType.Bishop));
|
final int startBlack = lNum-1;
|
||||||
Pieces.add(new Piece(3, 0, false, PieceType.Queen));
|
|
||||||
Pieces.add(new Piece(4, 0, false, PieceType.King));
|
//Black pieces populating
|
||||||
Pieces.add(new Piece(5, 0, false, PieceType.Bishop));
|
setPiece(PieceType.Rook,false,0,startWhite);
|
||||||
Pieces.add(new Piece(6, 0, false, PieceType.Knight));
|
setPiece(PieceType.Knight,false, 1,startWhite);
|
||||||
Pieces.add(new Piece(7, 0, false, PieceType.Rook));
|
setPiece(PieceType.Bishop,false,2,startWhite);
|
||||||
|
setPiece(PieceType.Queen,false,3,startWhite);
|
||||||
for (int i = 0; i < 8; i++) {
|
setPiece(PieceType.King,false,4,startWhite);
|
||||||
Pieces.add(new Piece(i, 1, false, PieceType.Pawn));
|
setPiece(PieceType.Bishop,false,5,startWhite);
|
||||||
|
setPiece(PieceType.Knight,false,6,startWhite);
|
||||||
|
setPiece(PieceType.Rook,false,7,startWhite);
|
||||||
|
|
||||||
|
for (int x = 0; x < cNum; x++) {
|
||||||
|
setPiece(PieceType.Pawn,false,x,startWhite+1);
|
||||||
}
|
}
|
||||||
|
//White pieces populating
|
||||||
|
setPiece(PieceType.Rook,true,0,startBlack);
|
||||||
|
setPiece(PieceType.Knight,true,1,startBlack);
|
||||||
|
setPiece(PieceType.Bishop,true,2,startBlack);
|
||||||
|
setPiece(PieceType.Queen,true,3,startBlack);
|
||||||
|
setPiece(PieceType.King,true,4,startBlack);
|
||||||
|
setPiece(PieceType.Bishop,true,5,startBlack);
|
||||||
|
setPiece(PieceType.Knight,true,6,startBlack);
|
||||||
|
setPiece(PieceType.Rook,true,7,startBlack);
|
||||||
|
|
||||||
Pieces.add(new Piece(0, 7, true, PieceType.Rook));
|
for (int x = 0; x < cNum; x++) {
|
||||||
Pieces.add(new Piece(1, 7, true, PieceType.Knight));
|
|
||||||
Pieces.add(new Piece(2, 7, true, PieceType.Bishop));
|
|
||||||
Pieces.add(new Piece(3, 7, true, PieceType.Queen));
|
|
||||||
Pieces.add(new Piece(4, 7, true, PieceType.King));
|
|
||||||
Pieces.add(new Piece(5, 7, true, PieceType.Bishop));
|
|
||||||
Pieces.add(new Piece(6, 7, true, PieceType.Knight));
|
|
||||||
Pieces.add(new Piece(7, 7, true, PieceType.Rook));
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
setPiece(PieceType.Pawn,true,x,startBlack-1);
|
||||||
Pieces.add(new Piece(i, 6, true, PieceType.Pawn));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
for (int x = 0; x < cNum; x++) {
|
||||||
|
for(int y=0;y<lNum;y++) {
|
||||||
|
if (cells[x][y]==null) {
|
||||||
|
System.out.print("blank - ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.print(cells[x][y].getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ArrayList<Piece> getPieces() {
|
System.out.print("\r\n");
|
||||||
return Pieces;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanBoard() {
|
public void cleanBoard() {
|
||||||
Pieces.clear();
|
for (int y = 0; y < 8; y++) {
|
||||||
|
for (int x = 0; x < 8; x++) {
|
||||||
|
cells[x][y] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedCell = null;
|
||||||
|
moveHistory.clear(); // clear undo history
|
||||||
|
turnNumber = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder boardView = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int y = 0; y < lNum; y++) {
|
||||||
for (int row = 0; row < lNum; row++) {
|
for (int x = 0; x < cNum; x++) {
|
||||||
for (int col = 0; col < cNum; col++) {
|
Piece p = cells[x][y];
|
||||||
Piece pieceAtPosition = getPieceAt(col, row);
|
if (p != null) {
|
||||||
|
sb.append(p.isWhite() ? "W" : "B").append(p.getType().toString().charAt(0)).append(" ");
|
||||||
if (pieceAtPosition != null) {
|
|
||||||
String colorPrefix = pieceAtPosition.isWhite() ? "W" : "B";
|
|
||||||
boardView.append(colorPrefix)
|
|
||||||
.append(pieceAtPosition.getType().getSummary())
|
|
||||||
.append(" ");
|
|
||||||
} else {
|
} else {
|
||||||
boardView.append(".. ");
|
sb.append("-- ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boardView.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
|
return sb.toString();
|
||||||
return boardView.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasSelection = false;
|
|
||||||
private int selectedX, selectedY;
|
|
||||||
private int turnNumber = 0;
|
|
||||||
private boolean turnWhite = true;
|
|
||||||
|
|
||||||
private Piece findPieceAt(int x, int y) {
|
public ArrayList<Piece> getPieces() {
|
||||||
for (Piece piece : Pieces) {
|
ArrayList<Piece> pieces = new ArrayList<>();
|
||||||
if (piece.getX() == x && piece.getY() == y) {
|
|
||||||
return piece;
|
for (int y = 0; y < 8; y++) {
|
||||||
|
for (int x = 0; x < 8; x++) {
|
||||||
|
if (cells[x][y]!= null) {
|
||||||
|
pieces.add(cells[x][y]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
return pieces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void userTouch(int x, int y) {
|
||||||
|
if (this.selectedCell != null) {
|
||||||
|
System.out.println("cellule deja selectionne : " + this.selectedCell.getName());
|
||||||
|
|
||||||
public void userTouch(int col, int row) {
|
int selectedX = selectedCell.getX();
|
||||||
if (GameLost()) return;
|
int selectedY = selectedCell.getY();
|
||||||
|
|
||||||
Piece target = findPieceAt(col, row);
|
// CASE 1: Same cell clicked (deselect)
|
||||||
|
if (cells[x][y] != null && x == selectedX && y == selectedY) {
|
||||||
if (!hasSelection) {
|
System.out.println("il a clique sur la meme cellule, je deselectionne");
|
||||||
if (target != null && target.isWhite() == turnWhite) {
|
this.selectedCell = null;
|
||||||
hasSelection = true;
|
return;
|
||||||
selectedX = col;
|
}
|
||||||
selectedY = row;
|
|
||||||
|
// CASE 2: Illegal move
|
||||||
|
if (!isHighlighted(x, y)) {
|
||||||
|
System.out.println("Illegal move for this piece.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Piece movingPiece = selectedCell;
|
||||||
|
Piece targetPiece = cells[x][y];
|
||||||
|
|
||||||
|
// Handle special move: En Passant
|
||||||
|
if (movingPiece.getType() == PieceType.Pawn && x != selectedX && targetPiece == null) {
|
||||||
|
if (enPassantTargetPawn != null && enPassantTargetPawn.getX() == x && enPassantTargetPawn.getY() == selectedY) {
|
||||||
|
targetPiece = enPassantTargetPawn;
|
||||||
|
cells[x][selectedY] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to move history
|
||||||
|
Move move = new Move(movingPiece, selectedX, selectedY, x, y, targetPiece);
|
||||||
|
moveHistory.add(move);
|
||||||
|
|
||||||
|
// Move piece
|
||||||
|
cells[x][y] = new Piece(movingPiece.getType(), movingPiece.isWhite(), x, y);
|
||||||
|
cells[selectedX][selectedY] = null;
|
||||||
|
|
||||||
|
// En Passant tracking
|
||||||
|
enPassantTargetPawn = null;
|
||||||
|
if (movingPiece.getType() == PieceType.Pawn && Math.abs(y - selectedY) == 2) {
|
||||||
|
enPassantTargetPawn = cells[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedCell.getType() == PieceType.Pawn) {
|
||||||
|
int promotionRow = selectedCell.isWhite() ? 0 : 7;
|
||||||
|
if (y == promotionRow) {
|
||||||
|
cells[x][y] = new Piece(PieceType.Queen, selectedCell.isWhite(), x, y);
|
||||||
|
System.out.println("Pawn promoted to Queen at (" + x + "," + y + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cells[x][y].setHasMoved(true); // Mark king as moved
|
||||||
|
cells[selectedCell.getX()][selectedCell.getY()] = null;
|
||||||
|
|
||||||
|
// Castling: detect and move rook
|
||||||
|
if (selectedCell.getType() == PieceType.King && Math.abs(x - selectedCell.getX()) == 2) {
|
||||||
|
int yRow = selectedCell.getY();
|
||||||
|
boolean isWhite = selectedCell.isWhite();
|
||||||
|
boolean kingside = (x - selectedCell.getX()) == 2;
|
||||||
|
|
||||||
|
int rookFromX = kingside ? 7 : 0;
|
||||||
|
int rookToX = kingside ? x - 1 : x + 1;
|
||||||
|
|
||||||
|
Piece rook = cells[rookFromX][yRow];
|
||||||
|
if (rook != null && rook.getType() == PieceType.Rook && rook.isWhite() == isWhite) {
|
||||||
|
cells[rookToX][yRow] = new Piece(PieceType.Rook, isWhite, rookToX, yRow);
|
||||||
|
cells[rookToX][yRow].setHasMoved(true);
|
||||||
|
cells[rookFromX][yRow] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset selection and switch turn
|
||||||
|
selectedCell = null;
|
||||||
|
turnNumber++;
|
||||||
|
System.out.println(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// No piece selected
|
||||||
|
System.out.println("----- aucune cellule selectionnee");
|
||||||
|
|
||||||
|
Piece clickedPiece = cells[x][y];
|
||||||
|
if (clickedPiece != null) {
|
||||||
|
boolean pieceIsWhite = clickedPiece.isWhite();
|
||||||
|
boolean correctTurn = (pieceIsWhite == isTurnWhite());
|
||||||
|
|
||||||
|
if (correctTurn) {
|
||||||
|
this.selectedCell = clickedPiece;
|
||||||
|
System.out.println("nouvelle cellule selectionne " + clickedPiece.getName());
|
||||||
|
} else {
|
||||||
|
System.out.println("Mauvais tour ! Ce n'est pas le tour de cette couleur.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("il a clique sur cellule vide");
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (col == selectedX && row == selectedY) {
|
|
||||||
hasSelection = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isHighlighted(col, row)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Piece pieceToCapture = findPieceAt(col, row);
|
|
||||||
if (pieceToCapture != null) {
|
|
||||||
Pieces.remove(pieceToCapture);
|
|
||||||
}
|
|
||||||
|
|
||||||
Piece selected = findPieceAt(selectedX, selectedY);
|
|
||||||
if (selected != null) {
|
|
||||||
Pieces.remove(selected);
|
|
||||||
Piece moved = new Piece(col, row, selected.isWhite(), selected.getType());
|
|
||||||
Pieces.add(moved);
|
|
||||||
|
|
||||||
Move move = new Move(selected, col, row, pieceToCapture);
|
|
||||||
moveHistory.push(move);
|
|
||||||
}
|
|
||||||
|
|
||||||
turnNumber++;
|
|
||||||
turnWhite = !turnWhite;
|
|
||||||
hasSelection = false;
|
|
||||||
|
|
||||||
System.out.println(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isSelected(int x, int y) {
|
public boolean isSelected(int x, int y) {
|
||||||
return hasSelection && selectedX == x && selectedY == y;
|
|
||||||
|
return selectedCell != null && selectedCell.getX() == x && selectedCell.getY() == y;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//saving feature: "type + iswhite + x + y"
|
||||||
public String[] toFileRep() {
|
public String[] toFileRep() {
|
||||||
ArrayList<String> lines = new ArrayList<>();
|
ArrayList<String> lines = new ArrayList<>();
|
||||||
for (int y = 0; y < 8; y++) {
|
for (int y = 0; y < 8; y++) {
|
||||||
for (int x = 0; x < 8; x++) {
|
for (int x = 0; x < 8; x++) {
|
||||||
Piece piece = cells[x][y];
|
Piece piece = cells[x][y];
|
||||||
|
|
@ -186,10 +264,10 @@ public class Board {
|
||||||
|
|
||||||
return lines.toArray(new String[0]);
|
return lines.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//loading feature
|
//loading feature
|
||||||
public Board(String[] array) {
|
public Board(String[] array) {
|
||||||
this.cNum = 8;
|
this.cNum = 8;
|
||||||
this.lNum = 8;
|
this.lNum = 8;
|
||||||
this.cells = new Piece[cNum][lNum];
|
this.cells = new Piece[cNum][lNum];
|
||||||
this.selectedCell = null;
|
this.selectedCell = null;
|
||||||
|
|
@ -212,260 +290,220 @@ public class Board {
|
||||||
int x = Integer.parseInt(tokens[2]);
|
int x = Integer.parseInt(tokens[2]);
|
||||||
int y = Integer.parseInt(tokens[3]);
|
int y = Integer.parseInt(tokens[3]);
|
||||||
|
|
||||||
setPiece(isWhite, type, x, y);
|
setPiece(type, isWhite, x, y);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Error parsing line: " + line);
|
System.err.println("Error parsing line: " + line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHighlighted(int destX, int destY) {
|
|
||||||
if (!hasSelection) return false;
|
|
||||||
|
|
||||||
Piece selected = null;
|
|
||||||
for (Piece p : Pieces) {
|
/* The following methods require more work ! */
|
||||||
if (p.getX() == selectedX && p.getY() == selectedY) {
|
|
||||||
selected = p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selected == null) return false;
|
|
||||||
|
|
||||||
int fromX = selected.getX(), fromY = selected.getY();
|
|
||||||
boolean isWhite = selected.isWhite();
|
|
||||||
PieceType type = selected.getType();
|
public boolean isHighlighted(int x, int y) {
|
||||||
|
if (selectedCell == null) return false;
|
||||||
|
|
||||||
|
int currX = selectedCell.getX();
|
||||||
|
int currY = selectedCell.getY();
|
||||||
|
int dx = x - currX;
|
||||||
|
int dy = y - currY;
|
||||||
|
|
||||||
|
PieceType type = selectedCell.getType();
|
||||||
|
boolean isWhite = selectedCell.isWhite();
|
||||||
|
|
||||||
|
if (x < 0 || x >= cNum || y < 0 || y >= lNum) return false;
|
||||||
|
|
||||||
|
Piece target = cells[x][y];
|
||||||
|
if (target != null && target.isWhite() == isWhite) return false;
|
||||||
|
|
||||||
if (type == PieceType.Pawn) {
|
if (type == PieceType.Pawn) {
|
||||||
int dir = isWhite ? -1 : 1;
|
int direction = isWhite ? -1 : 1;
|
||||||
if (destX == fromX && destY == fromY + dir && getPieceAt(destX, destY) == null) return true;
|
|
||||||
if ((isWhite && fromY == 6 || !isWhite && fromY == 1) &&
|
// Forward move
|
||||||
destX == fromX && destY == fromY + 2 * dir &&
|
if (dx == 0 && dy == direction && cells[x][y] == null) return true;
|
||||||
getPieceAt(fromX, fromY + dir) == null && getPieceAt(destX, destY) == null) return true;
|
|
||||||
if ((destX == fromX + 1 || destX == fromX - 1) && destY == fromY + dir) {
|
// Double move
|
||||||
Piece target = getPieceAt(destX, destY);
|
boolean onStartRow = (isWhite && currY == 6) || (!isWhite && currY == 1);
|
||||||
if (target != null && target.isWhite() != isWhite) return true;
|
if (dx == 0 && dy == 2 * direction && onStartRow &&
|
||||||
}
|
cells[x][y] == null && cells[currX][currY + direction] == null) return true;
|
||||||
|
|
||||||
|
// Capture
|
||||||
|
if (Math.abs(dx) == 1 && dy == direction && target != null && target.isWhite() != isWhite) return true;
|
||||||
|
|
||||||
|
// En passant
|
||||||
|
if (Math.abs(dx) == 1 && dy == direction &&
|
||||||
|
enPassantTargetPawn != null &&
|
||||||
|
enPassantTargetPawn.getX() == x &&
|
||||||
|
enPassantTargetPawn.getY() == currY) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == PieceType.Knight) {
|
if (type == PieceType.Rook) {
|
||||||
int[][] moves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
|
if (dx == 0 || dy == 0) {
|
||||||
for (int[] m : moves) {
|
int stepX = Integer.compare(dx, 0);
|
||||||
int x = fromX + m[0], y = fromY + m[1];
|
int stepY = Integer.compare(dy, 0);
|
||||||
if (x == destX && y == destY && x >= 0 && x < cNum && y >= 0 && y < lNum) {
|
int cx = currX + stepX;
|
||||||
Piece target = getPieceAt(x, y);
|
int cy = currY + stepY;
|
||||||
if (target == null || target.isWhite() != isWhite) return true;
|
|
||||||
|
while (cx != x || cy != y) {
|
||||||
|
if (cells[cx][cy] != null) return false;
|
||||||
|
cx += stepX;
|
||||||
|
cy += stepY;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == PieceType.King) {
|
|
||||||
int[][] moves = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,1},{1,-1},{-1,-1}};
|
|
||||||
for (int[] m : moves) {
|
|
||||||
int x = fromX + m[0], y = fromY + m[1];
|
|
||||||
if (x == destX && y == destY && x >= 0 && x < cNum && y >= 0 && y < lNum) {
|
|
||||||
Piece target = getPieceAt(x, y);
|
|
||||||
if (target == null || target.isWhite() != isWhite) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == PieceType.Rook || type == PieceType.Queen) {
|
|
||||||
int[][] directions = {{1,0},{-1,0},{0,1},{0,-1}};
|
|
||||||
for (int[] d : directions) {
|
|
||||||
int x = fromX + d[0], y = fromY + d[1];
|
|
||||||
while (x >= 0 && x < cNum && y >= 0 && y < lNum) {
|
|
||||||
Piece target = getPieceAt(x, y);
|
|
||||||
if (target == null) {
|
|
||||||
if (x == destX && y == destY) return true;
|
|
||||||
} else {
|
|
||||||
if (x == destX && y == destY && target.isWhite() != isWhite) return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x += d[0]; y += d[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == PieceType.Bishop || type == PieceType.Queen) {
|
|
||||||
int[][] directions = {{1,1},{-1,1},{1,-1},{-1,-1}};
|
|
||||||
for (int[] d : directions) {
|
|
||||||
int x = fromX + d[0], y = fromY + d[1];
|
|
||||||
while (x >= 0 && x < cNum && y >= 0 && y < lNum) {
|
|
||||||
Piece target = getPieceAt(x, y);
|
|
||||||
if (target == null) {
|
|
||||||
if (x == destX && y == destY) return true;
|
|
||||||
} else {
|
|
||||||
if (x == destX && y == destY && target.isWhite() != isWhite) return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x += d[0]; y += d[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void undoLastMove() {
|
|
||||||
if (moveHistory.isEmpty()) return;
|
|
||||||
|
|
||||||
Move previousMove = moveHistory.pop();
|
|
||||||
|
|
||||||
int toX = previousMove.getToX();
|
|
||||||
int toY = previousMove.getToY();
|
|
||||||
int fromX = previousMove.getFromX();
|
|
||||||
int fromY = previousMove.getFromY();
|
|
||||||
|
|
||||||
Piece movedPiece = previousMove.getMovedPiece();
|
|
||||||
Piece capturedPiece = previousMove.getCapturedPiece();
|
|
||||||
|
|
||||||
// Remove the piece from its current destination
|
|
||||||
Pieces.removeIf(piece -> piece.getX() == toX && piece.getY() == toY);
|
|
||||||
|
|
||||||
// Restore the moved piece to its original position
|
|
||||||
Pieces.add(new Piece(fromX, fromY, movedPiece.isWhite(), movedPiece.getType()));
|
|
||||||
|
|
||||||
// Restore the captured piece if one was taken
|
|
||||||
if (capturedPiece != null) {
|
|
||||||
Pieces.add(new Piece(capturedPiece.getX(), capturedPiece.getY(), capturedPiece.isWhite(), capturedPiece.getType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
turnNumber--;
|
|
||||||
turnWhite = !turnWhite;
|
|
||||||
hasSelection = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Board(Board source) {
|
|
||||||
this.cNum = source.cNum;
|
|
||||||
this.lNum = source.lNum;
|
|
||||||
this.turnNumber = source.turnNumber;
|
|
||||||
this.turnWhite = source.turnWhite;
|
|
||||||
this.hasSelection = source.hasSelection;
|
|
||||||
this.selectedX = source.selectedX;
|
|
||||||
this.selectedY = source.selectedY;
|
|
||||||
|
|
||||||
this.Pieces = new ArrayList<>();
|
|
||||||
for (Piece piece : source.Pieces) {
|
|
||||||
int x = piece.getX();
|
|
||||||
int y = piece.getY();
|
|
||||||
boolean isWhite = piece.isWhite();
|
|
||||||
PieceType type = piece.getType();
|
|
||||||
this.Pieces.add(new Piece(x, y, isWhite, type));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.moveHistory = new Stack<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void playMove(Move move) {
|
|
||||||
if (GameLost()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Pieces.removeIf(p -> p.getX() == move.getToX() && p.getY() == move.getToY());
|
|
||||||
Pieces.removeIf(p -> p.getX() == move.getFromX() && p.getY() == move.getFromY());
|
|
||||||
Piece moved = move.getMovedPiece();
|
|
||||||
Pieces.add(new Piece(move.getToX(), move.getToY(), moved.isWhite(), moved.getType()));
|
|
||||||
moveHistory.push(move);
|
|
||||||
turnNumber++;
|
|
||||||
turnWhite = !turnWhite;
|
|
||||||
hasSelection = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Piece getPieceAt(int x, int y) {
|
|
||||||
for (Piece p : Pieces) {
|
|
||||||
if (p.getX() == x && p.getY() == y) return p;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void selectPiece(int col, int row) {
|
|
||||||
selectedX = col;
|
|
||||||
selectedY = row;
|
|
||||||
hasSelection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean GameLost() {
|
|
||||||
boolean hasWhiteKing = false;
|
|
||||||
boolean hasBlackKing = false;
|
|
||||||
|
|
||||||
for (Piece piece : Pieces) {
|
|
||||||
if (piece.getType() == PieceType.King) {
|
|
||||||
if (piece.isWhite()) {
|
|
||||||
hasWhiteKing = true;
|
|
||||||
} else {
|
|
||||||
hasBlackKing = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasWhiteKing && hasBlackKing) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !(hasWhiteKing && hasBlackKing);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void activateSelection(int col, int row) {
|
|
||||||
selectedX = col;
|
|
||||||
selectedY = row;
|
|
||||||
hasSelection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isValidDestination(int x, int y) {
|
|
||||||
return isHighlighted(x, y);
|
|
||||||
}
|
|
||||||
public boolean isCheckmate() {
|
|
||||||
if (!isKingInCheck(turnWhite)) return false;
|
|
||||||
|
|
||||||
for (Piece piece : Pieces) {
|
|
||||||
if (piece.isWhite() != turnWhite) continue;
|
|
||||||
|
|
||||||
int fromX = piece.getX();
|
|
||||||
int fromY = piece.getY();
|
|
||||||
|
|
||||||
for (int toX = 0; toX < getWidth(); toX++) {
|
|
||||||
for (int toY = 0; toY < getHeight(); toY++) {
|
|
||||||
Board simulation = new Board(this);
|
|
||||||
simulation.activateSelection(fromX, fromY);
|
|
||||||
if (simulation.isHighlighted(toX, toY)) {
|
|
||||||
Move move = new Move(piece, toX, toY, getPieceAt(toX, toY));
|
|
||||||
simulation.playMove(move);
|
|
||||||
if (!simulation.isKingInCheck(turnWhite)) {
|
|
||||||
return false; // At least one escape exists
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public boolean isKingInCheck(boolean white) {
|
|
||||||
Piece king = null;
|
|
||||||
for (Piece piece : Pieces) {
|
|
||||||
if (piece.getType() == PieceType.King && piece.isWhite() == white) {
|
|
||||||
king = piece;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (king == null) return false;
|
|
||||||
|
|
||||||
int kingX = king.getX(), kingY = king.getY();
|
|
||||||
|
|
||||||
for (Piece attacker : Pieces) {
|
|
||||||
if (attacker.isWhite() == white) continue;
|
|
||||||
|
|
||||||
activateSelection(attacker.getX(), attacker.getY());
|
|
||||||
if (isHighlighted(kingX, kingY)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == PieceType.Bishop) {
|
||||||
|
if (Math.abs(dx) == Math.abs(dy)) {
|
||||||
|
int stepX = Integer.compare(dx, 0);
|
||||||
|
int stepY = Integer.compare(dy, 0);
|
||||||
|
int cx = currX + stepX;
|
||||||
|
int cy = currY + stepY;
|
||||||
|
|
||||||
|
while (cx != x || cy != y) {
|
||||||
|
if (cells[cx][cy] != null) return false;
|
||||||
|
cx += stepX;
|
||||||
|
cy += stepY;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == PieceType.Queen) {
|
||||||
|
if (dx == 0 || dy == 0 || Math.abs(dx) == Math.abs(dy)) {
|
||||||
|
int stepX = Integer.compare(dx, 0);
|
||||||
|
int stepY = Integer.compare(dy, 0);
|
||||||
|
int cx = currX + stepX;
|
||||||
|
int cy = currY + stepY;
|
||||||
|
|
||||||
|
while (cx != x || cy != y) {
|
||||||
|
if (cells[cx][cy] != null) return false;
|
||||||
|
cx += stepX;
|
||||||
|
cy += stepY;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == PieceType.King) {
|
||||||
|
if (Math.abs(dx) <= 1 && Math.abs(dy) <= 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!selectedCell.hasMoved() && dy == 0 && Math.abs(dx) == 2) {
|
||||||
|
boolean kingside = dx == 2;
|
||||||
|
int row = selectedCell.getY();
|
||||||
|
int rookX = kingside ? 7 : 0;
|
||||||
|
|
||||||
|
|
||||||
|
Piece rook = cells[rookX][row];
|
||||||
|
if (rook == null || rook.getType() != PieceType.Rook || rook.isWhite() != isWhite || rook.hasMoved()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check path is clear
|
||||||
|
int step = dx > 0 ? 1 : -1;
|
||||||
|
for (int i = 1; i < Math.abs(dx); i++) {
|
||||||
|
if (cells[currX + step * i][currY] != null) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == PieceType.Knight) {
|
||||||
|
if ((Math.abs(dx) == 2 && Math.abs(dy) == 1) || (Math.abs(dx) == 1 && Math.abs(dy) == 2)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Board(Board other) {
|
||||||
|
this.cNum = other.cNum;
|
||||||
|
this.lNum = other.lNum;
|
||||||
|
this.cells = new Piece[cNum][lNum];
|
||||||
|
this.selectedCell = null; // don't copy selection
|
||||||
|
|
||||||
}
|
for (int x = 0; x < cNum; x++) {
|
||||||
|
for (int y = 0; y < lNum; y++) {
|
||||||
|
Piece p = other.cells[x][y];
|
||||||
|
if (p != null) {
|
||||||
|
this.cells[x][y] = new Piece(p.getType(), p.isWhite(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void playMove(Move move) {
|
||||||
|
|
||||||
|
int fromX = move.getFromX();
|
||||||
|
int fromY = move.getFromY();
|
||||||
|
int toX = move.getToX();
|
||||||
|
int toY = move.getToY();
|
||||||
|
|
||||||
|
Piece movingPiece = cells[fromX][fromY];
|
||||||
|
if (movingPiece == null) {
|
||||||
|
System.err.println("No piece at source position.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cells[toX][toY] = new Piece(movingPiece.getType(), movingPiece.isWhite(), toX, toY);
|
||||||
|
cells[fromX][fromY] = null;
|
||||||
|
|
||||||
|
System.out.println("Moved " + movingPiece.getType() + " from (" + fromX + "," + fromY + ") to (" + toX + "," + toY + ")");
|
||||||
|
System.out.println(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void undoLastMove() {
|
||||||
|
if (moveHistory.isEmpty()) {
|
||||||
|
System.out.println("No move to undo.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Move lastMove = moveHistory.remove(moveHistory.size() - 1);
|
||||||
|
|
||||||
|
int fromX = lastMove.getFromX();
|
||||||
|
int fromY = lastMove.getFromY();
|
||||||
|
int toX = lastMove.getToX();
|
||||||
|
int toY = lastMove.getToY();
|
||||||
|
|
||||||
|
// Restore moved piece
|
||||||
|
cells[fromX][fromY] = lastMove.getPiece();
|
||||||
|
|
||||||
|
// Restore captured piece (or null)
|
||||||
|
if (lastMove.getCapturedPiece() != null) {
|
||||||
|
cells[toX][toY] = lastMove.getCapturedPiece();
|
||||||
|
} else {
|
||||||
|
cells[toX][toY] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear selection
|
||||||
|
selectedCell = null;
|
||||||
|
|
||||||
|
// Roll back turn
|
||||||
|
if (turnNumber > 0) {
|
||||||
|
turnNumber--;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Undo completed.");
|
||||||
|
System.out.println(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
public boolean hasPiece(int x, int y) {
|
||||||
|
return cells[x][y] != null;
|
||||||
|
}
|
||||||
|
public Piece getPiece(int x, int y) {
|
||||||
|
return cells[x][y];
|
||||||
|
}
|
||||||
|
public void resetGame() {
|
||||||
|
cleanBoard();
|
||||||
|
populateBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
import windowInterface.MyInterface;
|
import windowInterface.MyInterface;
|
||||||
|
|
@ -7,6 +6,7 @@ public class Game extends Thread {
|
||||||
|
|
||||||
private AutoPlayer aiPlayer;
|
private AutoPlayer aiPlayer;
|
||||||
private Board board;
|
private Board board;
|
||||||
|
private Piece newPiece;
|
||||||
|
|
||||||
private MyInterface mjf;
|
private MyInterface mjf;
|
||||||
private int COL_NUM = 8;
|
private int COL_NUM = 8;
|
||||||
|
|
@ -31,6 +31,10 @@ public class Game extends Thread {
|
||||||
public int getHeight() {
|
public int getHeight() {
|
||||||
return board.getHeight();
|
return board.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPiece(PieceType type, boolean isWhite, int x, int y) {
|
||||||
|
this.newPiece= new Piece(type,isWhite, x,y);
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
@ -65,10 +69,7 @@ public class Game extends Thread {
|
||||||
board.userTouch(x, y);
|
board.userTouch(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
|
||||||
board.setPiece(isWhite, type, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getFileRepresentation() {
|
public String[] getFileRepresentation() {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,24 @@
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
public class Move {
|
public class Move {
|
||||||
private final int fromX;
|
private Piece piece;
|
||||||
private final int fromY;
|
private int fromX, fromY;
|
||||||
private final int toX;
|
private int toX, toY;
|
||||||
private final int toY;
|
private Piece capturedPiece;
|
||||||
private final Piece movedPiece;
|
private Piece movedPiece;
|
||||||
private final Piece capturedPiece;
|
|
||||||
|
public Move ( Piece piece, int fromX, int fromY, int toX, int toY, Piece capturedPiece){
|
||||||
|
this.piece = piece;
|
||||||
|
this.fromX = fromX;
|
||||||
|
this.fromY = fromY;
|
||||||
|
this.toX = toX;
|
||||||
|
this.toY = toY;
|
||||||
|
this.capturedPiece = capturedPiece;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public Move(Piece movedPiece, int toX, int toY, Piece capturedPiece) {
|
public Move(Piece movedPiece, int toX, int toY, Piece capturedPiece) {
|
||||||
this.fromX = movedPiece.getX();
|
this.fromX = movedPiece.getX();
|
||||||
this.fromY = movedPiece.getY();
|
this.fromY = movedPiece.getY();
|
||||||
|
|
@ -20,28 +31,35 @@ public class Move {
|
||||||
public Move(Piece movedPiece, int toX, int toY) {
|
public Move(Piece movedPiece, int toX, int toY) {
|
||||||
this(movedPiece, toX, toY, null);
|
this(movedPiece, toX, toY, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Piece getPiece() {
|
||||||
|
return piece;
|
||||||
|
}
|
||||||
public int getFromX() {
|
public int getFromX() {
|
||||||
return fromX;
|
return fromX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFromY() {
|
public int getFromY() {
|
||||||
return fromY;
|
return fromY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getToX() {
|
public int getToX() {
|
||||||
return toX;
|
return toX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getToY() {
|
public int getToY() {
|
||||||
return toY;
|
return toY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Piece getMovedPiece() {
|
public Piece getMovedPiece() {
|
||||||
return movedPiece;
|
return movedPiece;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Piece getCapturedPiece() {
|
public Piece getCapturedPiece() {
|
||||||
return capturedPiece;
|
return capturedPiece;
|
||||||
}
|
}
|
||||||
}
|
public boolean isCapture() {
|
||||||
|
return capturedPiece != null;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return piece + ":("+ fromX + "," + fromY + ")-("+ toX + "," + toY + ")" +
|
||||||
|
( capturedPiece != null? "capturing "+ capturedPiece: "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
|
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
public class Piece {
|
public class Piece {
|
||||||
|
|
||||||
private int x;
|
private int x;
|
||||||
private int y;
|
private int y;
|
||||||
private boolean isWhite;
|
|
||||||
private PieceType type;
|
private PieceType type;
|
||||||
|
private boolean color;
|
||||||
|
private boolean hasMoved;
|
||||||
|
|
||||||
public Piece(int x, int y, boolean isWhite, PieceType type) {
|
public Piece(PieceType type_P, boolean color_P, int xP, int yP) {
|
||||||
this.x = x;
|
x = xP;
|
||||||
this.y = y;
|
y = yP;
|
||||||
this.isWhite = isWhite;
|
type = type_P;
|
||||||
this.type = type;
|
color = color_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -23,12 +23,36 @@ public class Piece {
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
public PieceType getType() {
|
public PieceType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWhite() {
|
public boolean isWhite() {
|
||||||
return isWhite;
|
return color;
|
||||||
|
}
|
||||||
|
public boolean hasMoved() {
|
||||||
|
return hasMoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasMoved(boolean moved) {
|
||||||
|
this.hasMoved = moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
if(color) {
|
||||||
|
return type.getSummary().concat("W - ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return type.getSummary().concat("B - ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ public class JPanelChessBoard extends JPanel {
|
||||||
int y = (me.getY()*myGame.getHeight())/getHeight();
|
int y = (me.getY()*myGame.getHeight())/getHeight();
|
||||||
if(pieceAdderMode) {
|
if(pieceAdderMode) {
|
||||||
//TODO
|
//TODO
|
||||||
myGame.setPiece(selectedPieceIsWhite,selectedPieceType, x, y);
|
myGame.setPiece(selectedPieceType,selectedPieceIsWhite, x, y);
|
||||||
pieceAdderMode = false;
|
pieceAdderMode = false;
|
||||||
} else {
|
} else {
|
||||||
myGame.clickCoords(x,y);
|
myGame.clickCoords(x,y);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue