chess-board/ChessPanel/ChessBoard.cs
2017-02-27 15:15:50 +01:00

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);
}
}
}