package gui;
import game.Move;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import util.ChessfigureConstants;
import components.Field;
import components.Figure;
import components.FigureBishop;
import components.FigureKing;
import components.FigureKnight;
import components.FigureQueen;
import components.FigureRook;
/**
* Klasse, die das Schachbrett darstellt.
*
* @author Tabea
*
*/
public class Checkerboard extends JPanel
{
private static Checkerboard instance = null;
private MoveGUI moveGui = new MoveGUI();
private JTable grid = null;
private Move move;
private int fieldFrom,
fieldTo;
private Figure figure;
private int fieldFromColumn = 0,
fieldFromRow = 0,
fieldToColumn = 0,
fieldToRow = 0;
private boolean blackWon = false,
manualMove = false,
mmIsReady = false,
ppIsReady = false,
queen = false,
bishop = false,
knight = false,
rook = false;
private MyMouseListener mml;
private ArrayList<Integer> a = new ArrayList<Integer>();
private ImageIcon icon_king_black = new FigureKing(ChessfigureConstants.BLACK).getIcon(),
icon_king_white = new FigureKing(ChessfigureConstants.WHITE).getIcon(),
icon_rook_black = new FigureRook(ChessfigureConstants.BLACK).getIcon(),
icon_rook_white = new FigureRook(ChessfigureConstants.WHITE).getIcon();
private char newFigure = 'A';
/**
* Privater Konstruktor, der nur ein neues Objekt der Klasse erstellt. Ruft
* die Methode zur Tabellenerstellung auf.
*/
private Checkerboard() {
this.makeTable();
}
/**
* Gibt die Checkerboard-Instanz zurück.
* @return Checkerboard-Instanz
*/
public static Checkerboard getInstance() {
if (instance == null) {
instance = new Checkerboard();
}
return instance;
}
/**
* Methode, die eine Tabelle erzeugt, die das Schachbrett darstellt.
*/
public void makeTable() {
// Tabelle erstellen
this.grid = new JTable(8, 8);
this.grid.setShowHorizontalLines(true);
this.grid.setOpaque(false);
// MouseListener hinzufügen
this.mml = new MyMouseListener(this.grid);
this.grid.addMouseListener(this.mml);
// Zeilenhöhe und Spaltenbreite anpassen, so dass die Felder quadratisch
// sind
this.grid.setRowHeight(75);
int columnIndex = 8;
TableColumn col = null;
for (int i = 0; i < columnIndex; i++) {
col = this.grid.getColumnModel().getColumn(i);
col.setPreferredWidth(75);
// jede Spalte enthält einen CellRenderer
this.grid.getColumnModel().getColumn(i)
.setCellRenderer(new DefaultTableCellRenderer()
{
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
return (JPanel) value;
}
});
}
// neues CheckerboardPanel-Objekt
CheckerboardPanel cb = new CheckerboardPanel();
// in jeder Tabellenzelle wird ein JPanel eingefügt
// Schachbrettmuster wird angelegt
// erst Zeilen
for (int i = 0; i < 8; i++) {
// dann Spalten
for (int j = 0; j < 8; j++) {
// aktuelle Tabellenzelle
this.grid.setValueAt(new CheckerboardPanel(), i, j);
if (i % 2 == 0) {
if (j % 2 == 0) {
cb = (CheckerboardPanel) this.grid.getValueAt(i, j);
cb.setBackground(new Color(251, 225, 172, 100)); // hell
} else {
cb = (CheckerboardPanel) this.grid.getValueAt(i, j);
cb.setBackground(new Color(41, 15, 5, 100)); // dunkel
}
} else {
if (j % 2 == 0) {
cb = (CheckerboardPanel) this.grid.getValueAt(i, j);
cb.setBackground(new Color(41, 15, 5, 100)); // dunkel
} else {
cb = (CheckerboardPanel) this.grid.getValueAt(i, j);
cb.setBackground(new Color(251, 225, 172, 100)); // hell
}
}
}
}
// Felder dürfen weder editiert noch ausgewählt werden
this.grid.setEnabled(false);
// Tabellenaussehen
this.grid.setBorder(BorderFactory.createLineBorder(Color.black));
this.grid.setGridColor(Color.black);
// Tabelle hinzufügen und Wände fett machen
this.add(grid);
this.grid.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5,
new Color(43, 23, 2, 255)));
}
/**
* Methode, die die verwendete Nummerieung in Tabellenform umrechnet. Hier
* nur den Spaltenwert. Sonst 0-63 von links unten nach rechts oben, meine
* Tabelle hat aber standardmäßig, 0/0 links oben.
* @param fieldNumber Feldnummer
* @return konvertierte Spaltennummer
*/
public static int fieldNumberConverterColumn(int fieldNumber) {
// Spalte = fieldNumber mod 8
int column = (fieldNumber - 1) % 8;
return column;
}
/**
* Methode, die die verwendete Nummerieung in Tabellenform umrechnet. Hier
* nur den Zeilenwert. Sonst 0-63 von links unten nach rechts oben, meine
* Tabelle hat aber standardmäßig, 0/0 links oben.
* @param fieldNumber Feldnummer
* @return konvertierte Zeilennummer
*/
public static int fieldNumberConverterRow(int fieldNumber) {
// Zeile = 63-fieldNumber / 8 --> abrunden
int row = (int) Math.floor((64 - fieldNumber) / 8);
return row;
}
/**
* Methode, die Tabellenzeile und -spalte in die von anderen gewünschte
* Feldnummerierung von 1 bis 64 umrechnet. *
* @param row Tabellenzeile
* @param column Tabellenspalte
* @return Feldnummer
*/
public static int convertIntoFieldNumber(int row, int column) {
int fieldNumber = (((8 - row) - 1) * 8) + (column + 1);
return fieldNumber;
}
/**
* Methode, die die Informationen Über das aktuelle Schachfeld und
* eventuelle Sonderfälle einholt.
* @param move aktuelles Move-Objekt
*/
public void setCheckerboardInformation(Move move) {
this.move = move;
// Umrechnung der FieldFrom-Nummer
this.fieldFrom = this.move.getFieldFrom();
this.fieldFromColumn = fieldNumberConverterColumn(this.fieldFrom);
this.fieldFromRow = fieldNumberConverterRow(this.fieldFrom);
// Umrechnung der FieldTo-Nummer
this.fieldTo = this.move.getFieldTo();
this.fieldToColumn = fieldNumberConverterColumn(this.fieldTo);
this.fieldToRow = fieldNumberConverterRow(this.fieldTo);
// aktuelle Figur zwischenspeichern
this.figure = Field.getInstance().getFigureAt(this.fieldFrom);
if (!this.move.isKingSideCastling() && !this.move.isQueenSideCastling()) {
// ganz normaler Zug
// erst Zeile
for (int i = 0; i < 8; i++) {
if (i == this.fieldFromRow) {
// dann Spalte
for (int j = 0; j < 8; j++) {
if (j == this.fieldFromColumn) {
// entfernt die entsprechende Figur auf dem zugehörigen Feld
CheckerboardPanel cbp = (CheckerboardPanel) this.grid
.getValueAt(i, j);
cbp.label.setVisible(false);
Gui.getInstance().repaint();
Gui.getInstance().validate();
}
}
}
}
// erst Zeile
for (int i = 0; i < 8; i++) {
if (i == this.fieldToRow) {
// dann Spalte
for (int j = 0; j < 8; j++) {
if (j == this.fieldToColumn) {
CheckerboardPanel cbp = (CheckerboardPanel) this.grid
.getValueAt(i, j);
// falls dort eine Schachfigur geschlagen wurde
if (this.move.isCaptured()) {
cbp.label.setVisible(false);
}
// zeigt die entsprechende Figur auf dem zugehörigen Feld an
cbp.showIcon(this.figure);
Gui.getInstance().repaint();
Gui.getInstance().validate();
}
}
}
}
} else if (this.move.isKingSideCastling() && !this.move.isQueenSideCastling()) {
// kurze Rochade
this.setKingSideCastling(this.move.getPlayerColor() == ChessfigureConstants.BLACK);
} else {
// lange Rochade
this.setQueenSideCastling(this.move.getPlayerColor() == ChessfigureConstants.BLACK);
}
// wenn der Bauer umgewandelt werden soll
if (this.move.isPawnPromotion()) {
if (this.move.getPlayerColor() == ChessfigureConstants.WHITE) {
System.out.println("lksfnalsfnaslfnlsafdnlafsnlsfanlnasfln");
this.ppIsReady = false;
this.pawnPromotionGUI();
while (!this.ppIsReady) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else if (this.move.getPlayerColor() == ChessfigureConstants.BLACK) {
// Umrechnung der FieldTo-Nummer
int fieldTo = this.move.getFieldTo();
int fieldToColumn = fieldNumberConverterColumn(fieldTo);
int fieldToRow = fieldNumberConverterRow(fieldTo);
CheckerboardPanel cbp = (CheckerboardPanel) this.grid
.getValueAt(fieldToRow, fieldToColumn);
// Bauern weg
cbp.label.setVisible(false);
// welche Figur?
if (this.move.getPawnPromotedTo() == 'Q') {
this.newFigure = ChessfigureConstants.QUEEN_LETTER;
cbp.showIcon(new FigureQueen(ChessfigureConstants.BLACK));
} else if (this.move.getPawnPromotedTo() == 'B') {
this.newFigure = ChessfigureConstants.BISHOP_LETTER;
cbp.showIcon(new FigureBishop(ChessfigureConstants.BLACK));
} else if (this.move.getPawnPromotedTo() == 'K') {
this.newFigure = ChessfigureConstants.KNIGHT_LETTER;
cbp.showIcon(new FigureKnight(ChessfigureConstants.BLACK));
} else if (this.move.getPawnPromotedTo() == 'R') {
this.newFigure = ChessfigureConstants.ROOK_LETTER;
cbp.showIcon(new FigureRook(ChessfigureConstants.BLACK));
}
Gui.getInstance().repaint();
Gui.getInstance().validate();
} else {
System.out.println("Falsch!!!");
}
}
Gui.getInstance().repaint();
Gui.getInstance().validate();
if (this.move.isCheck() && this.move.isCheckMate()) {
// wer gewonnen hat
/*String winner;
if (this.figure.getColor() == ChessfigureConstants.BLACK) {
this.blackWon = true;
winner = "Schwarz";
} else {
this.blackWon = false;
winner = "Weiß";
}*/
javax.swing.JOptionPane.showMessageDialog(this,
"Spiel vorbei!", "Spielende",
JOptionPane.INFORMATION_MESSAGE);
FinishedGameGUI.getInstance();
}
// Abfrage ob Remi --> Dialog
if (this.move.isCheck() && !this.move.isCheckMate()) {
javax.swing.JOptionPane.showMessageDialog(this, "Schach!",
"Schach", JOptionPane.INFORMATION_MESSAGE);
}
}
/**
* Methode, die eine Instanz der Klasse PawnPromotionGUI aufruft.
*/
public void pawnPromotionGUI() {
PawnPromotionGUI.getInstance();
}
/**
* Methode, die die Informationen über die getroffene Spielfigurenwahl des
* Spielers enthält, wenn der Bauer ausgewechselt werden durfte. WEIß
* @param queen
* @param bishop
* @param knight
* @param rook
*/
public void pawnPromotionInformation(boolean queen, boolean bishop,
boolean knight, boolean rook) {
this.queen = queen;
this.bishop = bishop;
this.knight = knight;
this.rook = rook;
// Umrechnung der FieldTo-Nummer
int fieldTo = this.move.getFieldTo();
int fieldToColumn = fieldNumberConverterColumn(fieldTo);
int fieldToRow = fieldNumberConverterRow(fieldTo);
CheckerboardPanel cbp = (CheckerboardPanel) this.grid
.getValueAt(fieldToRow, fieldToColumn);
// Bauern weg
cbp.label.setVisible(false);
if (this.queen) {
this.newFigure = ChessfigureConstants.QUEEN_LETTER;
cbp.showIcon(new FigureQueen(ChessfigureConstants.WHITE));
} else if (this.bishop) {
this.newFigure = ChessfigureConstants.BISHOP_LETTER;
cbp.showIcon(new FigureBishop(ChessfigureConstants.WHITE));
} else if (this.knight) {
this.newFigure = ChessfigureConstants.KNIGHT_LETTER;
cbp.showIcon(new FigureKnight(ChessfigureConstants.WHITE));
} else if (this.rook) {
this.newFigure = ChessfigureConstants.ROOK_LETTER;
cbp.showIcon(new FigureRook(ChessfigureConstants.WHITE));
}
Gui.getInstance().repaint();
Gui.getInstance().validate();
}
public char getPawnPromotionInformation() {
System.out.println("1.: " + this.newFigure);
return this.newFigure;
}
public void setKingSideCastling(boolean black)
{
if (black) {
// Ke8-g8 und Th8-f8 (kurze schwarze Rochade)
// König: 0/4 - 0/6, Turm: 0/7 - 0/5
// König weg
CheckerboardPanel cbp = (CheckerboardPanel) this.grid.getValueAt(0, 4);
cbp.label.setVisible(false);
// König hin
cbp = (CheckerboardPanel) this.grid.getValueAt(0, 6);
cbp.label.setIcon(this.icon_king_black);
cbp.label.setVisible(true);
// Turm weg
cbp = (CheckerboardPanel) this.grid.getValueAt(0, 7);
cbp.label.setVisible(false);
// Turm hin
cbp = (CheckerboardPanel) this.grid.getValueAt(0, 5);
cbp.label.setIcon(this.icon_rook_black);
cbp.label.setVisible(true);
} else {
// Ke1-g1 und Th1-f1 (kurze weiße Rochade)
// König: 7/4 - 7/6, Turm: 7/7 - 7/5
// König weg
CheckerboardPanel cbp = (CheckerboardPanel) this.grid.getValueAt(7, 4);
cbp.label.setVisible(false);
// König hin
cbp = (CheckerboardPanel) this.grid.getValueAt(7, 6);
cbp.label.setIcon(this.icon_king_white);
cbp.label.setVisible(true);
// Turm weg
cbp = (CheckerboardPanel) this.grid.getValueAt(7, 7);
cbp.label.setVisible(false);
// Turm hin
cbp = (CheckerboardPanel) this.grid.getValueAt(7, 5);
cbp.label.setIcon(this.icon_rook_white);
cbp.label.setVisible(true);
}
}
public void setQueenSideCastling(boolean black)
{
if (black) {
// Ke8-c8 und Ta8-d8 (lange schwarze Rochade)
// König: 0/4 - 0/2, Turm: 0/0 - 0/3
// König weg
CheckerboardPanel cbp = (CheckerboardPanel) this.grid.getValueAt(0, 4);
cbp.label.setVisible(false);
// König hin
cbp = (CheckerboardPanel) this.grid.getValueAt(0, 2);
cbp.label.setIcon(this.icon_king_black);
cbp.label.setVisible(true);
// Turm weg
cbp = (CheckerboardPanel) this.grid.getValueAt(0, 0);
cbp.label.setVisible(false);
// Turm hin
cbp = (CheckerboardPanel) this.grid.getValueAt(0, 3);
cbp.label.setIcon(this.icon_rook_black);
cbp.label.setVisible(true);
} else {
// Ke1-c1 und Ta1-d1 (lange weiße Rochade)
// König: 7/4 - 7/2, Turm: 7/0 - 7/3
// König weg
CheckerboardPanel cbp = (CheckerboardPanel) this.grid.getValueAt(7, 4);
cbp.label.setVisible(false);
// König hin
cbp = (CheckerboardPanel) this.grid.getValueAt(7, 2);
cbp.label.setIcon(this.icon_king_white);
cbp.label.setVisible(true);
// Turm weg
cbp = (CheckerboardPanel) this.grid.getValueAt(7, 0);
cbp.label.setVisible(false);
// Turm hin
cbp = (CheckerboardPanel) this.grid.getValueAt(7, 3);
cbp.label.setIcon(this.icon_rook_white);
cbp.label.setVisible(true);
}
}
/**
* Methode wird ausgeführt, wenn die Kamera den Zug nicht richtig
* erkennen konnte. Ruft die Methode originalManualMove() auf.
*
* @return ArrayList al, entweder mit zwei oder vier Werten
*/
public ArrayList<Integer> manualMove() {
ArrayList<Integer> al = new ArrayList<Integer>();
while(al.size() == 0) {
al = this.originalManualMove();
}
return al;
}
/**
* Der Benutzer kann entweder Über klicken am Schachfeld einen normalen Zug
* oder einfach die entsprechende Rochade auswählen.
*
* @return ArrayList mit den Feldnummern, entweder zwei für einen normalen Zug
* oder vier für die entsprechende Rochade
*/
public ArrayList<Integer> originalManualMove() {
this.manualMove = true;
this.mmIsReady = false;
// damit Startansicht
this.moveGui = new MoveGUI();
this.moveGui.startWindow();
while (!this.mmIsReady) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (this.moveGui.isNormalButtonPressed()) {
// Feldnummern von den angeklickten Feldern
return this.a;
} else {
// darf weiß überhaupt eine Rochade ausführen?
if (/*this.figure.getColor() == ChessfigureConstants.WHITE &&*/
Field.getInstance().isCastlingWhitePossible()) {
// welche Rochadenart
if (this.moveGui.isKingsideCastling()) {
// kurze Rochade
// a = 5 7 8 6
this.a.clear();
this.a.add(5);
this.a.add(7);
this.a.add(8);
this.a.add(6);
return this.a;
} else {
// lange Rochade
// a = 5 3 1 4
this.a.clear();
this.a.add(5);
this.a.add(3);
this.a.add(1);
this.a.add(4);
return this.a;
}
// wenn keine Rochade erlaubt
} else {
javax.swing.JOptionPane.showMessageDialog(this, "Keine Rochade möglich, bitte erneute Zugeingabe!",
"Rochade", JOptionPane.INFORMATION_MESSAGE);
this.a.clear();
return this.a;
}
}
}
/**
* Setter für die booleansche Variable, ob die manuelle Zugeingabe
* erfolgreich beendet wurde.
* @param mmIsReady
*/
public void setMmIsReady(boolean mmIsReady) {
this.mmIsReady = mmIsReady;
}
public void setPPIsReady(boolean ppIsReady) {
this.ppIsReady = ppIsReady;
}
/**
* Methode, die die ArrayList setzt.
* @param a ArrayList
*/
public void setArrayList(ArrayList<Integer> a) {
this.a = a;
}
/**
* Getter für die ArrayList.
* @return entsprechende ArrayList
*/
public ArrayList<Integer> getArrayList() {
return this.a;
}
/**
* Getter für die booleansche Variable, ob Schwarz oder Weiß gewonnen hat.
* @return blackWon true oder false
*/
public boolean hasBlackWon() {
return this.blackWon;
}
/**
* Getter für die booleansche Variable, ob der Zug manuell eingegeben werden
* muss oder nicht.
* @return manualMove true oder false
*/
public boolean isManualMove() {
return this.manualMove;
}
/**
* @param manualMove true oder false
*/
public void setManualMove(boolean manualMove) {
this.manualMove = manualMove;
}
/**
* Methode, die die Schachfiguren auf ihre Startpositionen setzt.
* @param figures HashMap mit der Startfeldfigurenanordnung
*/
public void getStartMap(HashMap<Integer, Figure> figures) {
// Iterator erstellen, der ueber alle Figuren iteriert
Iterator<Entry<Integer, Figure>> it = figures.entrySet().iterator();
// iteriere ueber alle Figuren
while (it.hasNext()) {
// Key/Value-Paar speichern
Map.Entry<Integer, Figure> pair = it.next();
// Position der Figur steht im Key
Integer i = pair.getKey();
// value-Objekt
Figure f = pair.getValue();
// entsprechende Figuren werden an zugehöriger Position angezeigt
// Umrechnung der Feldnummern notwendig
CheckerboardPanel cbp = (CheckerboardPanel) this.grid
.getValueAt(fieldNumberConverterRow(i), (fieldNumberConverterColumn(i)));
cbp.showIcon(f);
}
}
/**
* Methode, die die Tabelle neu zeichnen lässt, um ein neues Spiel zu
* ermöglichen.
*/
public void resetMap() {
this.removeAll();
this.makeTable();
}
public MoveGUI getMoveGui() {
return this.moveGui;
}
}