using Chess; using System; using System.Collections.Generic; using System.Windows; using System.Windows.Forms; using static Chess.Piece; namespace ChessPanel { public partial class ChessBoard : Panel { public Field[,] fields; public PieceColor activePlayer; private int gridSize = 8; public bool isSaved = true; Dictionary validTargetSpots = new Dictionary(); private Vector? selectedField; private Vector? SelectedField { get { return selectedField; } set { selectedField = value; HighlightValidTargetSpots(); } } private void HighlightValidTargetSpots() { if (selectedField.HasValue && fields[(int)selectedField.Value.X, (int)selectedField.Value.Y].CurrentPiece != null) // Wenn das neu ausgewählte Feld eine Figur enthält, wird diese ausgewählt { fields[(int)selectedField.Value.X, (int)selectedField.Value.Y].Select(); } ResetValidTargetSpots(); if (selectedField.HasValue) { if (fields[(int)selectedField.Value.X, (int)selectedField.Value.Y].CurrentPiece != null) { validTargetSpots = fields[(int)selectedField.Value.X, (int)selectedField.Value.Y].CurrentPiece.GetValidTargetFields(fields, new Vector(selectedField.Value.X, selectedField.Value.Y)); } foreach (var item in validTargetSpots) { fields[(int)item.Key.X, (int)item.Key.Y].Highlight(item.Value); } } } /// /// Setzt die Markierungen sowie die Liste der möglichen Zielfelder zurück /// private void ResetValidTargetSpots() { foreach (var item in validTargetSpots) { fields[(int)item.Key.X, (int)item.Key.Y].Deselect(); } validTargetSpots.Clear(); // Markierung der Zielfelder zurücksetzen } public int GridSize { get { return gridSize; } set { gridSize = value; } } public ChessBoard() { this.DoubleBuffered = true; this.SuspendLayout(); this.Resize += new System.EventHandler(this.ChessBoard_Resize); InitializeGrid(); InitializePieces(); activePlayer = PieceColor.White; this.ResumeLayout(false); } private void ToggleActivePlayer() => activePlayer = activePlayer == PieceColor.White ? PieceColor.Black : PieceColor.White; private void DoPieceMove(Vector location, Vector newLocation, bool togglePlayer = true) { isSaved = false; #region Castling if (fields[(int)location.X, (int)location.Y].CurrentPiece.type == PieceType.King && Math.Abs(newLocation.X - location.X) == 2) DoPieceMove(new Vector(((newLocation.X - location.X == -2) ? 0 : 7), location.Y), new Vector(location.X + (newLocation.X - location.X) / 2, location.Y), false /*Dont Toggle Player*/); // Move Rook #endregion #region EnPassant foreach (var item in fields) // Reset Enpassant Possible states each move { if (item.CurrentPiece != null) if (item.CurrentPiece.type == PieceType.Pawn) { item.CurrentPiece.EnPassantPossible = false; } } if (fields[(int)location.X, (int)location.Y].CurrentPiece.type == PieceType.Pawn && !fields[(int)location.X, (int)location.Y].CurrentPiece.HasMoved) fields[(int)location.X, (int)location.Y].CurrentPiece.EnPassantPossible = true; if (fields[(int)location.X, (int)location.Y].CurrentPiece.type == PieceType.Pawn && newLocation.X != location.X && fields[(int)newLocation.X, (int)newLocation.Y].IsEmpty) fields[(int)newLocation.X, (int)newLocation.Y + (fields[(int)location.X, (int)location.Y].CurrentPiece.color == PieceColor.White ? 1 : -1)].CurrentPiece = null; #endregion fields[(int)location.X, (int)location.Y].CurrentPiece.HasMoved = true; // Figur Bereits bewegt Status aktualisieren fields[(int)newLocation.X, (int)newLocation.Y].CurrentPiece = fields[(int)location.X, (int)location.Y].CurrentPiece; // Figur an neue Position kopieren fields[(int)location.X, (int)location.Y].CurrentPiece = null; // Alte Kopie der Figur löschen if (togglePlayer) ToggleActivePlayer(); } private void InitializePieces() { fields[0, 0].CurrentPiece = new Rook(PieceColor.Black); fields[7, 0].CurrentPiece = new Rook(PieceColor.Black); fields[0, 7].CurrentPiece = new Rook(PieceColor.White); fields[7, 7].CurrentPiece = new Rook(PieceColor.White); fields[1, 0].CurrentPiece = new Knight(PieceColor.Black); fields[6, 0].CurrentPiece = new Knight(PieceColor.Black); fields[1, 7].CurrentPiece = new Knight(PieceColor.White); fields[6, 7].CurrentPiece = new Knight(PieceColor.White); fields[2, 0].CurrentPiece = new Bishop(PieceColor.Black); fields[5, 0].CurrentPiece = new Bishop(PieceColor.Black); fields[2, 7].CurrentPiece = new Bishop(PieceColor.White); fields[5, 7].CurrentPiece = new Bishop(PieceColor.White); fields[4, 0].CurrentPiece = new King(PieceColor.Black); fields[3, 0].CurrentPiece = new Queen(PieceColor.Black); fields[3, 7].CurrentPiece = new Queen(PieceColor.White); fields[4, 7].CurrentPiece = new King(PieceColor.White); for (int x = 0; x < 8; x++) { fields[x, 1].CurrentPiece = new Pawn(PieceColor.Black); fields[x, 6].CurrentPiece = new Pawn(PieceColor.White); } } private void InitializeGrid() { this.fields = new Field[gridSize, gridSize]; int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / gridSize; System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength); for (int x = 0; x < this.gridSize; x++) { for (int y = 0; y < this.gridSize; y++) { Field field = new Field(x, y); field.Size = subPanelSize; field.Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height); field.FieldClick += FieldClicked; fields[x, y] = field; this.Controls.Add(fields[x, y]); } } } private void FieldClicked(Vector coordinates) { this.SuspendLayout(); if (SelectedField.HasValue && validTargetSpots.ContainsKey(coordinates)) // Ein erlaubtes Zielfeld wurde angeklickt { DoPieceMove(SelectedField.Value, coordinates); // Bewege Figur ResetSelectedField(); // Auswahl zurücksetzen } else { if (SelectedField == coordinates) // Erneutes Anklicken des Auswahlfeldes ResetSelectedField(); // Auswahl zurücksetzen else // Tritt ein, wenn ein Feld angeklickt wurde, dass nicht das Auswahlfeld ist { if (SelectedField.HasValue) // Wenn ein Feld ausgewählt ist wird die Auswahl gelöscht falls nicht das Auswahlfeld angeklickt wurde ResetSelectedField(); // Auswahl zurücksetzen if (!fields[(int)coordinates.X, (int)coordinates.Y].IsEmpty && fields[(int)coordinates.X, (int)coordinates.Y].CurrentPiece.color == activePlayer) // Feld wird nur ausgewählt, wenn die Farbe der Figur mit der des aktiven Spielers übereinstimmt SelectedField = coordinates; // Kein Feld ist ausgewählt: Angeklicktes Feld auswählen (!) AKTUALISIERT AUTOMATISCH DIE MARKIERUNGEN } } this.ResumeLayout(false); } /// /// Löscht die Auswahl des aktuell ausgewählten Feldes /// private void ResetSelectedField() { fields[(int)SelectedField.Value.X, (int)SelectedField.Value.Y].Deselect(); // Auswahl zurücksetzen SelectedField = null; // Erlaubte Zielfelder zurücksetzen } #region Helper Can be deleted static readonly string[] Columns = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH" }; public static string IndexToColumn(int index) { if (index <= 0) throw new IndexOutOfRangeException("index must be a positive number"); return Columns[index - 1]; } #endregion private void ChessBoard_Resize(object sender, EventArgs e) { RefreshSize(); } private void RefreshSize() { this.SuspendLayout(); int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / gridSize; System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength); for (int x = 0; x < this.gridSize; x++) { for (int y = 0; y < this.gridSize; y++) { fields[x, y].Size = subPanelSize; fields[x, y].Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height); } } this.ResumeLayout(false); } } }