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