using Chess; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Forms; using static Chess.Piece; namespace ChessPanel { public partial class ChessBoard : Panel { private BackgroundWorker BGWorker = new BackgroundWorker(); public Grid fields; public List pieces; public PieceColor activePlayer; private int GRID_SIZE = 8; public bool isSaved = true; Dictionary SelectedPieceTargetSpots = new Dictionary(); //private Vector? selectedField; //private Vector? SelectedField //{ // get { return selectedField; } // set { selectedField = value; HighlightValidTargetSpots(); } //} private Field selectedField; private Field SelectedField { get { return selectedField; } set { selectedField = value; HighlightValidTargetSpots(); } } private bool FieldIsSelected { get { return selectedField != null; } } private void HighlightValidTargetSpots() { if (FieldIsSelected && selectedField.CurrentPiece != null) // Wenn das neu ausgewählte Feld eine Figur enthält, wird diese ausgewählt { selectedField.Select(); } ResetValidTargetSpots(); if (FieldIsSelected) { if (selectedField.CurrentPiece != null) { //SelectedPieceTargetSpots = selectedField.CurrentPiece.GetValidTargetFields(fields); SelectedPieceTargetSpots = selectedField.CurrentPiece.validTargetSpots; if (SelectedPieceTargetSpots == null) SelectedPieceTargetSpots = selectedField.CurrentPiece.GetValidTargetFields(fields); } if (SelectedPieceTargetSpots != null) foreach (var TargetSpot in SelectedPieceTargetSpots) { TargetSpot.Key.Highlight(TargetSpot.Value); } } } /// /// Setzt die Markierungen sowie die Liste der möglichen Zielfelder zurück /// private void ResetValidTargetSpots() { foreach (var validTarget in SelectedPieceTargetSpots) { validTarget.Key.Deselect(); } SelectedPieceTargetSpots.Clear(); // Markierung der Zielfelder zurücksetzen } public int GridSize { get { return GRID_SIZE; } set { GRID_SIZE = value; } } public ChessBoard() { this.DoubleBuffered = true; this.SuspendLayout(); this.Resize += new System.EventHandler(this.ChessBoard_Resize); // this.validTargetSpotCalculator.WorkerReportsProgress = true;// Progress BGWorker.WorkerSupportsCancellation = true; this.BGWorker.RunWorkerCompleted += ValidTargetSpotCalculator_RunWorkerCompleted; this.BGWorker.DoWork += ValidTargetSpotCalculator_DoWork; BeginTargetFieldCalculation(); InitializeGrid(); InitializePieces(); activePlayer = PieceColor.White; this.ResumeLayout(false); } private void ValidTargetSpotCalculator_DoWork(object sender, DoWorkEventArgs e) { BGWorkerData data = e.Argument as BGWorkerData; List ActivePlayerPieces = data.pieces.Where(i => i.color == data.color).ToList(); int total = ActivePlayerPieces.Count; int count = 0; foreach (var piece in ActivePlayerPieces) { if (BGWorker.CancellationPending) { e.Cancel = true; return; } piece.RefreshValidTargetSpots(data.fields); // validTargetSpotCalculator.ReportProgress((int)Math.Floor((float)(++count) / (float)total * 100f)); // Progress } } private void ValidTargetSpotCalculator_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { throw new NotImplementedException(); } private void ToggleActivePlayer() => activePlayer = activePlayer == PieceColor.White ? PieceColor.Black : PieceColor.White; private void DoPieceMove(Field PieceField, Field newPieceField, bool togglePlayer = true, bool skipValidTargetFieldCalculation = false) { isSaved = false; #region Castling if (PieceField.CurrentPiece.type == PieceType.King && Math.Abs(newPieceField.location.X - PieceField.location.X) == 2) DoPieceMove(fields[((newPieceField.location.X - PieceField.location.X == -2) ? 0 : 7), PieceField.location.Y], fields[PieceField.location.X + (newPieceField.location.X - PieceField.location.X) / 2, PieceField.location.Y], false /*Dont Toggle Player*/, true); // Move Rook #endregion #region EnPassant foreach (Piece item in pieces.Where(i => i.type == PieceType.Pawn)) // Reset Enpassant Possible states each move item.EnPassantPossible = false; if (PieceField.CurrentPiece.type == PieceType.Pawn && !PieceField.CurrentPiece.HasMoved) PieceField.CurrentPiece.EnPassantPossible = true; if (PieceField.CurrentPiece.type == PieceType.Pawn && newPieceField.location.X != PieceField.location.X && newPieceField.IsEmpty) fields[newPieceField.location, 0, (PieceField.CurrentPiece.color == PieceColor.White ? 1 : -1)].CurrentPiece = null; #endregion PieceField.CurrentPiece.Move(newPieceField); //PieceField.CurrentPiece.HasMoved = true; // Figur Bereits bewegt Status aktualisieren //newPieceField.CurrentPiece = PieceField.CurrentPiece; // Figur an neue Position kopieren //PieceField.CurrentPiece = null; // Alte Kopie der Figur löschen if (togglePlayer) ToggleActivePlayer(); if (skipValidTargetFieldCalculation) BeginTargetFieldCalculation(); } class BGWorkerData { public BGWorkerData(PieceColor color, List pieces, Grid fields) { this.color = color; this.pieces = pieces; this.fields = fields; } public PieceColor color; public List pieces; public Grid fields; } private void BeginTargetFieldCalculation() { if (BGWorker.WorkerSupportsCancellation) BGWorker.CancelAsync(); else BGWorker.RunWorkerAsync(new BGWorkerData(activePlayer, pieces, fields)); } private void InitializePieces() { pieces = new List { new Rook(PieceColor.Black, new Vector(0, 0), fields), new Rook(PieceColor.Black, new Vector(7, 0), fields), new Rook(PieceColor.White, new Vector(0, 7), fields), new Rook(PieceColor.White, new Vector(7, 7), fields), new Knight(PieceColor.Black, new Vector(1, 0), fields), new Knight(PieceColor.Black, new Vector(6, 0), fields), new Knight(PieceColor.White, new Vector(1, 7), fields), new Knight(PieceColor.White, new Vector(6, 7), fields), new Bishop(PieceColor.Black, new Vector(2, 0), fields), new Bishop(PieceColor.Black, new Vector(5, 0), fields), new Bishop(PieceColor.White, new Vector(2, 7), fields), new Bishop(PieceColor.White, new Vector(5, 7),fields), new King(PieceColor.Black, new Vector(4, 0), fields), new Queen(PieceColor.Black, new Vector(3, 0), fields), new Queen(PieceColor.White, new Vector(3, 7), fields), new King(PieceColor.White, new Vector(4, 7), fields) }; for (int x = 0; x < 8; x++) { pieces.Add(new Pawn(PieceColor.Black, new Vector(x, 1), fields)); pieces.Add(new Pawn(PieceColor.White, new Vector(x, 6), fields)); } foreach (Field field in fields) { field.RefreshPiece(); } } private void InitializeGrid() { this.fields = new Grid(GRID_SIZE); int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / GRID_SIZE; System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength); for (int x = 0; x < this.GRID_SIZE; x++) { for (int y = 0; y < this.GRID_SIZE; y++) { Field field = new Field(x, y) { Size = subPanelSize, 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(Field sender) { this.SuspendLayout(); if (FieldIsSelected && SelectedPieceTargetSpots.ContainsKey(sender)) // Ein erlaubtes Zielfeld wurde angeklickt { DoPieceMove(SelectedField, sender); // Bewege Figur ResetSelectedField(); // Auswahl zurücksetzen } else { if (SelectedField == sender) // Erneutes Anklicken des Auswahlfeldes ResetSelectedField(); // Auswahl zurücksetzen else // Tritt ein, wenn ein Feld angeklickt wurde, dass nicht das Auswahlfeld ist { if (FieldIsSelected) // Wenn ein Feld ausgewählt ist wird die Auswahl gelöscht falls nicht das Auswahlfeld angeklickt wurde ResetSelectedField(); // Auswahl zurücksetzen if (!sender.IsEmpty && sender.CurrentPiece.color == activePlayer) // Feld wird nur ausgewählt, wenn die Farbe der Figur mit der des aktiven Spielers übereinstimmt SelectedField = sender; // 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() { SelectedField.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) / GRID_SIZE; System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength); for (int x = 0; x < this.GRID_SIZE; x++) { for (int y = 0; y < this.GRID_SIZE; y++) { fields[x, y].Size = subPanelSize; fields[x, y].Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height); } } this.ResumeLayout(false); } } }