import java.util.LinkedList;
/** * Repräsention eines Solitaire-Bretts mit einigen hilfreichen Methoden, * die das Ausführen von Spielzügen (Aktionen) auf dem Spielbrett * ermöglichen. */ public class Board {
/** * Interne Repräsentation des Solitaire-Brettes * als boolsche 2D-Matrix. * true bedeutet Feld belegt, false bedeutet Feld frei. */ private boolean[][] board;
/** * Instantiiert ein Solitaire-Brett mit der Start-Aufstellung. */ public Board() { this.board = new boolean[7][7]; for (int x = 0; x < 7; x++) { for (int y = 0; y < 7; y++) { this.board[x][y] = true; } } this.board[3][3] = false; }
/** * Prüft, ob es sich um die Endstellung handelt. * @return true, falls es sich um die Endstellung handelt. */ public boolean isFinished() {
// Falls das mittlere Feld besetzt ist, // genau prüfen, ob es sich um die Endstellung handelt // (Optimierung). if (this.board[3][3]) { return (!this.board[2][0]) && (!this.board[3][0]) && (!this.board[4][0]) && (!this.board[2][1]) && (!this.board[3][1]) && (!this.board[4][1]) && (!this.board[0][2]) && (!this.board[1][2]) && (!this.board[2][2]) && (!this.board[3][2]) && (!this.board[4][2]) && (!this.board[5][2]) && (!this.board[6][2]) && (!this.board[0][3]) && (!this.board[1][3]) && (!this.board[2][3]) && (!this.board[4][3]) && (!this.board[5][3]) && (!this.board[6][3]) && (!this.board[0][4]) && (!this.board[1][4]) && (!this.board[2][4]) && (!this.board[3][4]) && (!this.board[4][4]) && (!this.board[5][4]) && (!this.board[6][4]) && (!this.board[2][5]) && (!this.board[3][5]) && (!this.board[4][5]) && (!this.board[2][6]) && (!this.board[3][6]) && (!this.board[4][6]); } else { return false; } }
/** * Prüft, ob es sich um eine Feld-Koordinate handelt. Die * Implementierung ist hier sehr ineffizient, * effizienter mit Lookup-Matrix. * @param x die horizontale Komponente. * @param y die vertikale Komponente. * @return true, falls es sich um eine Feld-Koordinate handelt. */ public boolean isField(int x, int y) { return ((0 <= x) && (x < 7) && (0 <= y) && (y < 7)) && (!((0 <= x) && (x < 2) && (0 <= y) && (y < 2))) && (!((0 <= x) && (x < 2) && (5 <= y) && (y < 7))) && (!((5 <= x) && (x < 7) && (0 <= y) && (y < 2))) && (!((5 <= x) && (x < 7) && (5 <= y) && (y < 7))); }
/** * Prüft, ob ein Zug auf dem Brett ausgeführt werden kann. * @param xFrom die x-Komponente vom Startpunkt des Zuges. * @param yFrom die y-Komponente vom Startpunkt des Zuges. * @param xTo die x-Komponente vom Endpunkt des Zuges. * @param yTo die y-Komponente vom Endpunkt des Zuges. * @return true, falls der Zug ausgeführt werden kann. */ public boolean canDoMove(int xFrom, int yFrom, int xTo, int yTo) { return // Ist From-Feld belegt? (this.isField(xFrom, yFrom)) && (this.board[xFrom][yFrom]) && // Ist To-Feld frei? (this.isField(xTo, yTo)) && (!this.board[xTo][yTo]) && // Ist Mittelfeld belegt? (this.board[(xFrom + xTo) / 2][(yFrom + yTo) / 2]); }
/** * Führt einen Zug (Aktion) auf dem Brett aus. * @param action der Zug. */ public void doMove(Move action) { if (this.canDoMove(action.xFrom, action.yFrom, action.xTo, action.yTo)) { // From-Feld leeren this.board[action.xFrom][action.yFrom] = false; // To-Feld besetzen this.board[action.xTo][action.yTo] = true; // Mittelfeld leeren this.board[(action.xFrom + action.xTo) / 2] [(action.yFrom + action.yTo) / 2] = false; } }
/** * Prüft, ob ein Zug auf dem Brett zurückgenommen werden kann. * @param xFrom die x-Komponente vom Startpunkt des Zuges. * @param yFrom die y-Komponente vom Startpunkt des Zuges. * @param xTo die x-Komponente vom Endpunkt des Zuges. * @param yTo die y-Komponente vom Endpunkt des Zuges. * @return true, falls der Zug zurückgenommen werden kann. */ public boolean canRedoMove(int xFrom, int yFrom, int xTo, int yTo) { return // Ist From-Feld frei? (this.isField(xFrom, yFrom)) && (!this.board[xFrom][yFrom]) && // Ist To-Feld belegt? (this.isField(xTo, yTo)) && (this.board[xTo][yTo]) && // Ist Mittelfeld frei? (!this.board[(xFrom + xTo) / 2][(yFrom + yTo) / 2]); }
/** * Nimmt einen Zug (Redo-Aktion) auf dem Brett zurück. * @param action die Zugrücknahme. */ public void redoMove(Move action) { if (this.canRedoMove(action.xFrom, action.yFrom, action.xTo, action.yTo)) { // From-Feld besetzen this.board[action.xFrom][action.yFrom] = true; // To-Feld leeren this.board[action.xTo][action.yTo] = false; // Mittelfeld besetzen this.board[(action.xFrom + action.xTo) / 2] [(action.yFrom + action.yTo) / 2] = true; } }
/** * Liefert alle möglichen Züge, die auf dem angegebenen Feld * ausgeführt werden können. * @param x die x-Komponente des Feldes. * @param y die y-Komponente des Feldes. * @return Die Liste aller möglichen Züge bzgl. Feld(x,y). */ private LinkedList<Move> getMovesOfField(int x, int y) { LinkedList<Move> result = new LinkedList<Move>(); if (this.isField(x, y)) { if (this.canDoMove(x, y, x - 2, y)) { result.add(new Move(x, y, x - 2, y)); } if (this.canDoMove(x, y, x + 2, y)) { result.add(new Move(x, y, x + 2, y)); } if (this.canDoMove(x, y, x, y - 2)) { result.add(new Move(x, y, x, y - 2)); } if (this.canDoMove(x, y, x, y + 2)) { result.add(new Move(x, y, x, y + 2)); } } return result; }
/** * Liefert alle möglichen Züge zur aktuellen Brettsituation. * @return Die Liste aller möglichen Züge. */ public LinkedList<Move> getMoves() { LinkedList<Move> result = new LinkedList<Move>(); for (int x = 0; x < 7; x++) { for (int y = 0; y < 7; y++) { result.addAll(this.getMovesOfField(x, y)); } } return result; }
/** * Gibt die textuelle Repräsentation eines Feldes zurück. * @param x die x-Komponente des Feldes. * @param y die y-Komponente des Feldes. * @return die textuelle Feld-Repräsentation. */ private String pieceToString(int x, int y) { return ((this.isField(x, y)) && (this.board[x][y])) ? "*" : " "; }
/** * Gibt die textuelle Repräsentation des Brettes zurück. * @return die textuelle Brett-Repräsentation. */ public String toString() { String result = ""; result += " a b c d e f g " + "\r\n"; result += " +---+---+---+ " + "\r\n"; result += "7 | " + this.pieceToString(2, 0); result += " | " + this.pieceToString(3, 0); result += " | " + this.pieceToString(4, 0); result += " | 7" + "\r\n"; result += " +---+---+---+ " + "\r\n"; result += "6 | " + this.pieceToString(2, 1); result += " | " + this.pieceToString(3, 1); result += " | " + this.pieceToString(4, 1); result += " | 6" + "\r\n"; result += " +---+---+---+---+---+---+---+ " + "\r\n"; result += "5 | " + this.pieceToString(0, 2); result += " | " + this.pieceToString(1, 2); result += " | " + this.pieceToString(2, 2); result += " | " + this.pieceToString(3, 2); result += " | " + this.pieceToString(4, 2); result += " | " + this.pieceToString(5, 2); result += " | " + this.pieceToString(6, 2); result += " | 5" + "\r\n"; result += " +---+---+---+---+---+---+---+ " + "\r\n"; result += "4 | " + this.pieceToString(0, 3); result += " | " + this.pieceToString(1, 3); result += " | " + this.pieceToString(2, 3); result += " | " + this.pieceToString(3, 3); result += " | " + this.pieceToString(4, 3); result += " | " + this.pieceToString(5, 3); result += " | " + this.pieceToString(6, 3); result += " | 4" + "\r\n"; result += " +---+---+---+---+---+---+---+ " + "\r\n"; result += "3 | " + this.pieceToString(0, 4); result += " | " + this.pieceToString(1, 4); result += " | " + this.pieceToString(2, 4); result += " | " + this.pieceToString(3, 4); result += " | " + this.pieceToString(4, 4); result += " | " + this.pieceToString(5, 4); result += " | " + this.pieceToString(6, 4); result += " | 3" + "\r\n"; result += " +---+---+---+---+---+---+---+ " + "\r\n"; result += "2 | " + this.pieceToString(2, 5); result += " | " + this.pieceToString(3, 5); result += " | " + this.pieceToString(4, 5); result += " | 2" + "\r\n"; result += " +---+---+---+ " + "\r\n"; result += "1 | " + this.pieceToString(2, 6); result += " | " + this.pieceToString(3, 6); result += " | " + this.pieceToString(4, 6); result += " | 1" + "\r\n"; result += " +---+---+---+ " + "\r\n"; result += " a b c d e f g "; return result; } } | |