chess-board/ChessPanel/ChessBoard.cs

282 lines
12 KiB
C#
Raw Normal View History

2017-02-27 15:15:50 +01:00
using Chess;
using System;
using System.Collections.Generic;
2017-11-16 18:06:29 +01:00
using System.ComponentModel;
using System.Linq;
2017-02-27 15:15:50 +01:00
using System.Windows;
using System.Windows.Forms;
using static Chess.Piece;
namespace ChessPanel
{
public partial class ChessBoard : Panel
{
2017-11-16 18:06:29 +01:00
private BackgroundWorker BGWorker = new BackgroundWorker();
public Grid fields;
public List<Piece> pieces;
2017-02-27 15:15:50 +01:00
public PieceColor activePlayer;
2017-11-16 18:06:29 +01:00
private int GRID_SIZE = 8;
2017-02-27 15:15:50 +01:00
public bool isSaved = true;
2017-11-16 18:06:29 +01:00
Dictionary<Field, PieceTeam> SelectedPieceTargetSpots = new Dictionary<Field, PieceTeam>();
//private Vector? selectedField;
//private Vector? SelectedField
//{
// get { return selectedField; }
// set { selectedField = value; HighlightValidTargetSpots(); }
//}
private Field selectedField;
private Field SelectedField
2017-02-27 15:15:50 +01:00
{
get { return selectedField; }
set { selectedField = value; HighlightValidTargetSpots(); }
}
2017-11-16 18:06:29 +01:00
private bool FieldIsSelected
{
get { return selectedField != null; }
}
2017-02-27 15:15:50 +01:00
private void HighlightValidTargetSpots()
{
2017-11-16 18:06:29 +01:00
if (FieldIsSelected && selectedField.CurrentPiece != null) // Wenn das neu ausgewählte Feld eine Figur enthält, wird diese ausgewählt
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
selectedField.Select();
2017-02-27 15:15:50 +01:00
}
ResetValidTargetSpots();
2017-11-16 18:06:29 +01:00
if (FieldIsSelected)
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
if (selectedField.CurrentPiece != null)
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
//SelectedPieceTargetSpots = selectedField.CurrentPiece.GetValidTargetFields(fields);
SelectedPieceTargetSpots = selectedField.CurrentPiece.validTargetSpots;
if (SelectedPieceTargetSpots == null)
SelectedPieceTargetSpots = selectedField.CurrentPiece.GetValidTargetFields(fields);
2017-02-27 15:15:50 +01:00
}
2017-11-16 18:06:29 +01:00
if (SelectedPieceTargetSpots != null)
foreach (var TargetSpot in SelectedPieceTargetSpots)
{
TargetSpot.Key.Highlight(TargetSpot.Value);
}
2017-02-27 15:15:50 +01:00
}
}
/// <summary>
/// Setzt die Markierungen sowie die Liste der möglichen Zielfelder zurück
/// </summary>
private void ResetValidTargetSpots()
{
2017-11-16 18:06:29 +01:00
foreach (var validTarget in SelectedPieceTargetSpots)
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
validTarget.Key.Deselect();
2017-02-27 15:15:50 +01:00
}
2017-11-16 18:06:29 +01:00
SelectedPieceTargetSpots.Clear(); // Markierung der Zielfelder zurücksetzen
2017-02-27 15:15:50 +01:00
}
public int GridSize
{
2017-11-16 18:06:29 +01:00
get { return GRID_SIZE; }
set { GRID_SIZE = value; }
2017-02-27 15:15:50 +01:00
}
public ChessBoard()
{
this.DoubleBuffered = true;
this.SuspendLayout();
this.Resize += new System.EventHandler(this.ChessBoard_Resize);
2017-11-16 18:06:29 +01:00
// this.validTargetSpotCalculator.WorkerReportsProgress = true;// Progress
BGWorker.WorkerSupportsCancellation = true;
this.BGWorker.RunWorkerCompleted += ValidTargetSpotCalculator_RunWorkerCompleted;
this.BGWorker.DoWork += ValidTargetSpotCalculator_DoWork;
BeginTargetFieldCalculation();
2017-02-27 15:15:50 +01:00
InitializeGrid();
InitializePieces();
activePlayer = PieceColor.White;
this.ResumeLayout(false);
}
2017-11-16 18:06:29 +01:00
private void ValidTargetSpotCalculator_DoWork(object sender, DoWorkEventArgs e)
{
BGWorkerData data = e.Argument as BGWorkerData;
List<Piece> 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();
}
2017-02-27 15:15:50 +01:00
private void ToggleActivePlayer() => activePlayer = activePlayer == PieceColor.White ? PieceColor.Black : PieceColor.White;
2017-11-16 18:06:29 +01:00
private void DoPieceMove(Field PieceField, Field newPieceField, bool togglePlayer = true, bool skipValidTargetFieldCalculation = false)
2017-02-27 15:15:50 +01:00
{
isSaved = false;
#region Castling
2017-11-16 18:06:29 +01:00
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
2017-02-27 15:15:50 +01:00
#endregion
#region EnPassant
2017-11-16 18:06:29 +01:00
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;
2017-02-27 15:15:50 +01:00
#endregion
2017-11-16 18:06:29 +01:00
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
2017-02-27 15:15:50 +01:00
if (togglePlayer)
ToggleActivePlayer();
2017-11-16 18:06:29 +01:00
if (skipValidTargetFieldCalculation) BeginTargetFieldCalculation();
}
class BGWorkerData
{
public BGWorkerData(PieceColor color, List<Piece> pieces, Grid fields)
{
this.color = color;
this.pieces = pieces;
this.fields = fields;
}
public PieceColor color;
public List<Piece> pieces;
public Grid fields;
}
private void BeginTargetFieldCalculation()
{
if (BGWorker.WorkerSupportsCancellation)
BGWorker.CancelAsync();
else
BGWorker.RunWorkerAsync(new BGWorkerData(activePlayer, pieces, fields));
2017-02-27 15:15:50 +01:00
}
2017-11-16 18:06:29 +01:00
2017-02-27 15:15:50 +01:00
private void InitializePieces()
{
2017-11-16 18:06:29 +01:00
pieces = new List<Piece>
{
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),
2017-02-27 15:15:50 +01:00
2017-11-16 18:06:29 +01:00
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),
2017-02-27 15:15:50 +01:00
2017-11-16 18:06:29 +01:00
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),
2017-02-27 15:15:50 +01:00
2017-11-16 18:06:29 +01:00
new Queen(PieceColor.White, new Vector(3, 7), fields),
new King(PieceColor.White, new Vector(4, 7), fields)
};
2017-02-27 15:15:50 +01:00
for (int x = 0; x < 8; x++)
{
2017-11-16 18:06:29 +01:00
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();
2017-02-27 15:15:50 +01:00
}
}
private void InitializeGrid()
{
2017-11-16 18:06:29 +01:00
this.fields = new Grid(GRID_SIZE);
int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / GRID_SIZE;
2017-02-27 15:15:50 +01:00
System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength);
2017-11-16 18:06:29 +01:00
for (int x = 0; x < this.GRID_SIZE; x++)
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
for (int y = 0; y < this.GRID_SIZE; y++)
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
Field field = new Field(x, y)
{
Size = subPanelSize,
Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height)
};
2017-02-27 15:15:50 +01:00
field.FieldClick += FieldClicked;
fields[x, y] = field;
this.Controls.Add(fields[x, y]);
}
}
}
2017-11-16 18:06:29 +01:00
private void FieldClicked(Field sender)
2017-02-27 15:15:50 +01:00
{
this.SuspendLayout();
2017-11-16 18:06:29 +01:00
if (FieldIsSelected && SelectedPieceTargetSpots.ContainsKey(sender)) // Ein erlaubtes Zielfeld wurde angeklickt
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
DoPieceMove(SelectedField, sender); // Bewege Figur
2017-02-27 15:15:50 +01:00
ResetSelectedField(); // Auswahl zurücksetzen
}
else
{
2017-11-16 18:06:29 +01:00
if (SelectedField == sender) // Erneutes Anklicken des Auswahlfeldes
2017-02-27 15:15:50 +01:00
ResetSelectedField(); // Auswahl zurücksetzen
else // Tritt ein, wenn ein Feld angeklickt wurde, dass nicht das Auswahlfeld ist
{
2017-11-16 18:06:29 +01:00
if (FieldIsSelected) // Wenn ein Feld ausgewählt ist wird die Auswahl gelöscht falls nicht das Auswahlfeld angeklickt wurde
2017-02-27 15:15:50 +01:00
ResetSelectedField(); // Auswahl zurücksetzen
2017-11-16 18:06:29 +01:00
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
2017-02-27 15:15:50 +01:00
}
}
this.ResumeLayout(false);
}
/// <summary>
/// Löscht die Auswahl des aktuell ausgewählten Feldes
/// </summary>
private void ResetSelectedField()
{
2017-11-16 18:06:29 +01:00
SelectedField.Deselect(); // Auswahl zurücksetzen
2017-02-27 15:15:50 +01:00
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();
2017-11-16 18:06:29 +01:00
int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / GRID_SIZE;
2017-02-27 15:15:50 +01:00
System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength);
2017-11-16 18:06:29 +01:00
for (int x = 0; x < this.GRID_SIZE; x++)
2017-02-27 15:15:50 +01:00
{
2017-11-16 18:06:29 +01:00
for (int y = 0; y < this.GRID_SIZE; y++)
2017-02-27 15:15:50 +01:00
{
fields[x, y].Size = subPanelSize;
fields[x, y].Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height);
}
}
this.ResumeLayout(false);
}
}
}