203 lines
10 KiB
C#
203 lines
10 KiB
C#
|
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<Vector, PieceTeam> validTargetSpots = new Dictionary<Vector, PieceTeam>();
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// Setzt die Markierungen sowie die Liste der möglichen Zielfelder zurück
|
|||
|
/// </summary>
|
|||
|
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);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// Löscht die Auswahl des aktuell ausgewählten Feldes
|
|||
|
/// </summary>
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|