Added initial code commit

This commit is contained in:
Michael Chen 2017-11-16 18:06:29 +01:00
parent 368cb29eaf
commit dd63e0adf5
Signed by: cnml
GPG Key ID: 5845BF3F82D5F629
19 changed files with 1762 additions and 695 deletions

179
.gitignore vendored
View File

@ -1,7 +1,10 @@
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files # User-specific files
*.rsuser
*.suo *.suo
*.user *.user
*.userosscache *.userosscache
@ -10,6 +13,9 @@
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs
# Mono auto generated files
mono_crash.*
# Build results # Build results
[Dd]ebug/ [Dd]ebug/
[Dd]ebugPublic/ [Dd]ebugPublic/
@ -17,42 +23,62 @@
[Rr]eleases/ [Rr]eleases/
x64/ x64/
x86/ x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
[Ll]ogs/
# Visual Studio 2015 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/
# Uncomment if you have tasks that create the project's static files in wwwroot # Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/ #wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results # MSTest test Results
[Tt]est[Rr]esult*/ [Tt]est[Rr]esult*/
[Bb]uild[Ll]og.* [Bb]uild[Ll]og.*
# NUNIT # NUnit
*.VisualState.xml *.VisualState.xml
TestResult.xml TestResult.xml
nunit-*.xml
# Build Results of an ATL Project # Build Results of an ATL Project
[Dd]ebugPS/ [Dd]ebugPS/
[Rr]eleasePS/ [Rr]eleasePS/
dlldata.c dlldata.c
# DNX # Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json project.lock.json
project.fragment.lock.json project.fragment.lock.json
artifacts/ artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c *_i.c
*_p.c *_p.c
*_i.h *_h.h
*.ilk *.ilk
*.meta *.meta
*.obj *.obj
*.iobj
*.pch *.pch
*.pdb *.pdb
*.ipdb
*.pgc *.pgc
*.pgd *.pgd
*.rsp *.rsp
@ -62,7 +88,9 @@ artifacts/
*.tlh *.tlh
*.tmp *.tmp
*.tmp_proj *.tmp_proj
*_wpftmp.csproj
*.log *.log
*.tlog
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds .builds
@ -90,6 +118,9 @@ ipch/
*.vspx *.vspx
*.sap *.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace # TFS 2012 Local Workspace
$tf/ $tf/
@ -101,15 +132,25 @@ _ReSharper*/
*.[Rr]e[Ss]harper *.[Rr]e[Ss]harper
*.DotSettings.user *.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in # TeamCity is a build add-in
_TeamCity* _TeamCity*
# DotCover is a Code Coverage Tool # DotCover is a Code Coverage Tool
*.dotCover *.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch # NCrunch
_NCrunch_* _NCrunch_*
.*crunch*.local.xml .*crunch*.local.xml
@ -141,9 +182,9 @@ publish/
# Publish Web Output # Publish Web Output
*.[Pp]ublish.xml *.[Pp]ublish.xml
*.azurePubxml *.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings # Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted # but database connection strings (with potential passwords) will be unencrypted
#*.pubxml *.pubxml
*.publishproj *.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to # Microsoft Azure Web App publish settings. Comment the next line if you want to
@ -153,13 +194,15 @@ PublishScripts/
# NuGet Packages # NuGet Packages
*.nupkg *.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore # The packages folder can be ignored because of Package Restore
**/packages/* **/[Pp]ackages/*
# except build/, which is used as an MSBuild target. # except build/, which is used as an MSBuild target.
!**/packages/build/ !**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed # Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config #!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignoreable files # NuGet v3's project.json files produces more ignorable files
*.nuget.props *.nuget.props
*.nuget.targets *.nuget.targets
@ -176,12 +219,15 @@ AppPackages/
BundleArtifacts/ BundleArtifacts/
Package.StoreAssociation.xml Package.StoreAssociation.xml
_pkginfo.txt _pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files # Visual Studio cache files
# files ending in .cache can be ignored # files ending in .cache can be ignored
*.[Cc]ache *.[Cc]ache
# but keep track of directories ending in .cache # but keep track of directories ending in .cache
!*.[Cc]ache/ !?*.[Cc]ache/
# Others # Others
ClientBin/ ClientBin/
@ -192,9 +238,12 @@ ClientBin/
*.jfm *.jfm
*.pfx *.pfx
*.publishsettings *.publishsettings
node_modules/
orleans.codegen.cs orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components # Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/ #bower_components/
@ -209,15 +258,22 @@ _UpgradeReport_Files/
Backup*/ Backup*/
UpgradeLog*.XML UpgradeLog*.XML
UpgradeLog*.htm UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files # SQL Server files
*.mdf *.mdf
*.ldf *.ldf
*.ndf
# Business Intelligence projects # Business Intelligence projects
*.rdl.data *.rdl.data
*.bim.layout *.bim.layout
*.bim_*.settings *.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes # Microsoft Fakes
FakesAssemblies/ FakesAssemblies/
@ -227,6 +283,7 @@ FakesAssemblies/
# Node.js Tools for Visual Studio # Node.js Tools for Visual Studio
.ntvs_analysis.dat .ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log # Visual Studio 6 build log
*.plg *.plg
@ -234,6 +291,20 @@ FakesAssemblies/
# Visual Studio 6 workspace options file # Visual Studio 6 workspace options file
*.opt *.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output # Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts **/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts
@ -249,13 +320,79 @@ paket-files/
# FAKE - F# Make # FAKE - F# Make
.fake/ .fake/
# JetBrains Rider # CodeRush personal settings
.idea/ .cr/personal
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS) # Python Tools for Visual Studio (PTVS)
__pycache__/ __pycache__/
*.pyc *.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@ -47,6 +47,7 @@
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Pieces\Bishop.cs" />
<Compile Include="ChessGame.cs"> <Compile Include="ChessGame.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
@ -57,13 +58,18 @@
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="FieldColorSet.cs" /> <Compile Include="FieldColorSet.cs" />
<Compile Include="Grid.cs" />
<Compile Include="Pieces\King.cs" />
<Compile Include="Pieces\Knight.cs" />
<Compile Include="MainForm.cs"> <Compile Include="MainForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="MainForm.Designer.cs"> <Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon> <DependentUpon>MainForm.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Piece.cs" /> <Compile Include="Pieces\Pawn.cs" />
<Compile Include="Pieces\AbstractPiece.cs" />
<Compile Include="Pieces\Rook.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
@ -71,6 +77,10 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Pieces\Queen.cs" />
<EmbeddedResource Include="ChessGame.resx">
<DependentUpon>ChessGame.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx"> <EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon> <DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@ -78,7 +88,6 @@
<Generator>PublicResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="ClassDiagram.cd" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />

View File

@ -1,6 +1,8 @@
using Chess; using Chess;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using static Chess.Piece; using static Chess.Piece;
@ -9,34 +11,53 @@ namespace ChessPanel
{ {
public partial class ChessBoard : Panel public partial class ChessBoard : Panel
{ {
public Field[,] fields; private BackgroundWorker BGWorker = new BackgroundWorker();
public Grid fields;
public List<Piece> pieces;
public PieceColor activePlayer; public PieceColor activePlayer;
private int gridSize = 8; private int GRID_SIZE = 8;
public bool isSaved = true; public bool isSaved = true;
Dictionary<Vector, PieceTeam> validTargetSpots = new Dictionary<Vector, PieceTeam>(); Dictionary<Field, PieceTeam> SelectedPieceTargetSpots = new Dictionary<Field, PieceTeam>();
private Vector? selectedField; //private Vector? selectedField;
private Vector? SelectedField //private Vector? SelectedField
//{
// get { return selectedField; }
// set { selectedField = value; HighlightValidTargetSpots(); }
//}
private Field selectedField;
private Field SelectedField
{ {
get { return selectedField; } get { return selectedField; }
set { selectedField = value; HighlightValidTargetSpots(); } set { selectedField = value; HighlightValidTargetSpots(); }
} }
private bool FieldIsSelected
{
get { return selectedField != null; }
}
private void 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 if (FieldIsSelected && selectedField.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(); selectedField.Select();
} }
ResetValidTargetSpots(); ResetValidTargetSpots();
if (selectedField.HasValue) if (FieldIsSelected)
{ {
if (fields[(int)selectedField.Value.X, (int)selectedField.Value.Y].CurrentPiece != null) if (selectedField.CurrentPiece != null)
{ {
validTargetSpots = fields[(int)selectedField.Value.X, (int)selectedField.Value.Y].CurrentPiece.GetValidTargetFields(fields, new Vector(selectedField.Value.X, selectedField.Value.Y)); //SelectedPieceTargetSpots = selectedField.CurrentPiece.GetValidTargetFields(fields);
} SelectedPieceTargetSpots = selectedField.CurrentPiece.validTargetSpots;
foreach (var item in validTargetSpots) if (SelectedPieceTargetSpots == null)
{ SelectedPieceTargetSpots = selectedField.CurrentPiece.GetValidTargetFields(fields);
fields[(int)item.Key.X, (int)item.Key.Y].Highlight(item.Value);
} }
if (SelectedPieceTargetSpots != null)
foreach (var TargetSpot in SelectedPieceTargetSpots)
{
TargetSpot.Key.Highlight(TargetSpot.Value);
}
} }
} }
/// <summary> /// <summary>
@ -44,119 +65,177 @@ namespace ChessPanel
/// </summary> /// </summary>
private void ResetValidTargetSpots() private void ResetValidTargetSpots()
{ {
foreach (var item in validTargetSpots) foreach (var validTarget in SelectedPieceTargetSpots)
{ {
fields[(int)item.Key.X, (int)item.Key.Y].Deselect(); validTarget.Key.Deselect();
} }
validTargetSpots.Clear(); // Markierung der Zielfelder zurücksetzen SelectedPieceTargetSpots.Clear(); // Markierung der Zielfelder zurücksetzen
} }
public int GridSize public int GridSize
{ {
get { return gridSize; } get { return GRID_SIZE; }
set { gridSize = value; } set { GRID_SIZE = value; }
} }
public ChessBoard() public ChessBoard()
{ {
this.DoubleBuffered = true; this.DoubleBuffered = true;
this.SuspendLayout(); this.SuspendLayout();
this.Resize += new System.EventHandler(this.ChessBoard_Resize); 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(); InitializeGrid();
InitializePieces(); InitializePieces();
activePlayer = PieceColor.White; activePlayer = PieceColor.White;
this.ResumeLayout(false); this.ResumeLayout(false);
} }
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();
}
private void ToggleActivePlayer() => activePlayer = activePlayer == PieceColor.White ? PieceColor.Black : PieceColor.White; private void ToggleActivePlayer() => activePlayer = activePlayer == PieceColor.White ? PieceColor.Black : PieceColor.White;
private void DoPieceMove(Vector location, Vector newLocation, bool togglePlayer = true) private void DoPieceMove(Field PieceField, Field newPieceField, bool togglePlayer = true, bool skipValidTargetFieldCalculation = false)
{ {
isSaved = false; isSaved = false;
#region Castling #region Castling
if (fields[(int)location.X, (int)location.Y].CurrentPiece.type == PieceType.King && Math.Abs(newLocation.X - location.X) == 2) if (PieceField.CurrentPiece.type == PieceType.King && Math.Abs(newPieceField.location.X - PieceField.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 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 #endregion
#region EnPassant #region EnPassant
foreach (var item in fields) // Reset Enpassant Possible states each move foreach (Piece item in pieces.Where(i => i.type == PieceType.Pawn)) // Reset Enpassant Possible states each move
{ item.EnPassantPossible = false;
if (item.CurrentPiece != null) if (PieceField.CurrentPiece.type == PieceType.Pawn && !PieceField.CurrentPiece.HasMoved)
if (item.CurrentPiece.type == PieceType.Pawn) PieceField.CurrentPiece.EnPassantPossible = true;
{ if (PieceField.CurrentPiece.type == PieceType.Pawn && newPieceField.location.X != PieceField.location.X && newPieceField.IsEmpty)
item.CurrentPiece.EnPassantPossible = false; fields[newPieceField.location, 0, (PieceField.CurrentPiece.color == PieceColor.White ? 1 : -1)].CurrentPiece = null;
}
}
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 #endregion
fields[(int)location.X, (int)location.Y].CurrentPiece.HasMoved = true; // Figur Bereits bewegt Status aktualisieren PieceField.CurrentPiece.Move(newPieceField);
fields[(int)newLocation.X, (int)newLocation.Y].CurrentPiece = fields[(int)location.X, (int)location.Y].CurrentPiece; // Figur an neue Position kopieren //PieceField.CurrentPiece.HasMoved = true; // Figur Bereits bewegt Status aktualisieren
fields[(int)location.X, (int)location.Y].CurrentPiece = null; // Alte Kopie der Figur löschen //newPieceField.CurrentPiece = PieceField.CurrentPiece; // Figur an neue Position kopieren
//PieceField.CurrentPiece = null; // Alte Kopie der Figur löschen
if (togglePlayer) if (togglePlayer)
ToggleActivePlayer(); ToggleActivePlayer();
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));
}
private void InitializePieces() private void InitializePieces()
{ {
fields[0, 0].CurrentPiece = new Rook(PieceColor.Black); pieces = new List<Piece>
fields[7, 0].CurrentPiece = new Rook(PieceColor.Black); {
fields[0, 7].CurrentPiece = new Rook(PieceColor.White); new Rook(PieceColor.Black, new Vector(0, 0), fields),
fields[7, 7].CurrentPiece = new Rook(PieceColor.White); 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),
fields[1, 0].CurrentPiece = new Knight(PieceColor.Black); new Knight(PieceColor.Black, new Vector(1, 0), fields),
fields[6, 0].CurrentPiece = new Knight(PieceColor.Black); new Knight(PieceColor.Black, new Vector(6, 0), fields),
fields[1, 7].CurrentPiece = new Knight(PieceColor.White); new Knight(PieceColor.White, new Vector(1, 7), fields),
fields[6, 7].CurrentPiece = new Knight(PieceColor.White); new Knight(PieceColor.White, new Vector(6, 7), fields),
fields[2, 0].CurrentPiece = new Bishop(PieceColor.Black); new Bishop(PieceColor.Black, new Vector(2, 0), fields),
fields[5, 0].CurrentPiece = new Bishop(PieceColor.Black); new Bishop(PieceColor.Black, new Vector(5, 0), fields),
fields[2, 7].CurrentPiece = new Bishop(PieceColor.White); new Bishop(PieceColor.White, new Vector(2, 7), fields),
fields[5, 7].CurrentPiece = new Bishop(PieceColor.White); 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),
fields[4, 0].CurrentPiece = new King(PieceColor.Black); new Queen(PieceColor.White, new Vector(3, 7), fields),
fields[3, 0].CurrentPiece = new Queen(PieceColor.Black); new King(PieceColor.White, new Vector(4, 7), fields)
};
fields[3, 7].CurrentPiece = new Queen(PieceColor.White);
fields[4, 7].CurrentPiece = new King(PieceColor.White);
for (int x = 0; x < 8; x++) for (int x = 0; x < 8; x++)
{ {
fields[x, 1].CurrentPiece = new Pawn(PieceColor.Black); pieces.Add(new Pawn(PieceColor.Black, new Vector(x, 1), fields));
fields[x, 6].CurrentPiece = new Pawn(PieceColor.White); pieces.Add(new Pawn(PieceColor.White, new Vector(x, 6), fields));
}
foreach (Field field in fields)
{
field.RefreshPiece();
} }
} }
private void InitializeGrid() private void InitializeGrid()
{ {
this.fields = new Field[gridSize, gridSize]; this.fields = new Grid(GRID_SIZE);
int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / gridSize; int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / GRID_SIZE;
System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength); System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength);
for (int x = 0; x < this.gridSize; x++) for (int x = 0; x < this.GRID_SIZE; x++)
{ {
for (int y = 0; y < this.gridSize; y++) for (int y = 0; y < this.GRID_SIZE; y++)
{ {
Field field = new Field(x, y); Field field = new Field(x, y)
field.Size = subPanelSize; {
field.Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height); Size = subPanelSize,
Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height)
};
field.FieldClick += FieldClicked; field.FieldClick += FieldClicked;
fields[x, y] = field; fields[x, y] = field;
this.Controls.Add(fields[x, y]); this.Controls.Add(fields[x, y]);
} }
} }
} }
private void FieldClicked(Vector coordinates) private void FieldClicked(Field sender)
{ {
this.SuspendLayout(); this.SuspendLayout();
if (SelectedField.HasValue && validTargetSpots.ContainsKey(coordinates)) // Ein erlaubtes Zielfeld wurde angeklickt if (FieldIsSelected && SelectedPieceTargetSpots.ContainsKey(sender)) // Ein erlaubtes Zielfeld wurde angeklickt
{ {
DoPieceMove(SelectedField.Value, coordinates); // Bewege Figur DoPieceMove(SelectedField, sender); // Bewege Figur
ResetSelectedField(); // Auswahl zurücksetzen ResetSelectedField(); // Auswahl zurücksetzen
} }
else else
{ {
if (SelectedField == coordinates) // Erneutes Anklicken des Auswahlfeldes if (SelectedField == sender) // Erneutes Anklicken des Auswahlfeldes
ResetSelectedField(); // Auswahl zurücksetzen ResetSelectedField(); // Auswahl zurücksetzen
else // Tritt ein, wenn ein Feld angeklickt wurde, dass nicht das Auswahlfeld ist 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 if (FieldIsSelected) // Wenn ein Feld ausgewählt ist wird die Auswahl gelöscht falls nicht das Auswahlfeld angeklickt wurde
ResetSelectedField(); // Auswahl zurücksetzen 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 if (!sender.IsEmpty && sender.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 SelectedField = sender; // Kein Feld ist ausgewählt: Angeklicktes Feld auswählen (!) AKTUALISIERT AUTOMATISCH DIE MARKIERUNGEN
} }
} }
this.ResumeLayout(false); this.ResumeLayout(false);
@ -166,7 +245,7 @@ namespace ChessPanel
/// </summary> /// </summary>
private void ResetSelectedField() private void ResetSelectedField()
{ {
fields[(int)SelectedField.Value.X, (int)SelectedField.Value.Y].Deselect(); // Auswahl zurücksetzen SelectedField.Deselect(); // Auswahl zurücksetzen
SelectedField = null; // Erlaubte Zielfelder zurücksetzen SelectedField = null; // Erlaubte Zielfelder zurücksetzen
} }
#region Helper Can be deleted #region Helper Can be deleted
@ -186,11 +265,11 @@ namespace ChessPanel
private void RefreshSize() private void RefreshSize()
{ {
this.SuspendLayout(); this.SuspendLayout();
int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / gridSize; int subPanelEdgeLength = Math.Min(this.Size.Width, this.Size.Height) / GRID_SIZE;
System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength); System.Drawing.Size subPanelSize = new System.Drawing.Size(subPanelEdgeLength, subPanelEdgeLength);
for (int x = 0; x < this.gridSize; x++) for (int x = 0; x < this.GRID_SIZE; x++)
{ {
for (int y = 0; y < this.gridSize; y++) for (int y = 0; y < this.GRID_SIZE; y++)
{ {
fields[x, y].Size = subPanelSize; fields[x, y].Size = subPanelSize;
fields[x, y].Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height); fields[x, y].Location = new System.Drawing.Point(x * subPanelSize.Width, y * subPanelSize.Height);

View File

@ -15,24 +15,25 @@ namespace Chess
private void InitializeComponent() private void InitializeComponent()
{ {
this.board = new ChessBoard(); this.board = new ChessPanel.ChessBoard();
this.SuspendLayout(); this.SuspendLayout();
// //
// board // board
// //
this.board.Cursor = System.Windows.Forms.Cursors.Hand;
this.board.GridSize = 8; this.board.GridSize = 8;
this.board.Cursor = Cursors.Hand;
this.board.Location = new System.Drawing.Point(0, 0); this.board.Location = new System.Drawing.Point(0, 0);
this.board.Name = "board"; this.board.Name = "board";
int size = Math.Min(this.Size.Width, this.Size.Height); this.board.Size = new System.Drawing.Size(100, 100);
board.Size = new System.Drawing.Size(size, size);
this.board.TabIndex = 0; this.board.TabIndex = 0;
this.board.Paint += new System.Windows.Forms.PaintEventHandler(this.board_Paint);
// //
// ChessGame // ChessGame
// //
this.Controls.Add(this.board); this.Controls.Add(this.board);
this.Resize += new System.EventHandler(this.ResizeEvent); this.Resize += new System.EventHandler(this.ResizeEvent);
this.ResumeLayout(false); this.ResumeLayout(false);
} }
private void ResizeEvent(object sender, EventArgs e) private void ResizeEvent(object sender, EventArgs e)
@ -77,5 +78,10 @@ namespace Chess
board.Size = new System.Drawing.Size(size, size); board.Size = new System.Drawing.Size(size, size);
board.Location = this.Size.Width > this.Size.Height ? new System.Drawing.Point((this.Size.Width - size) / 2, 0) : new System.Drawing.Point(0, (this.Size.Height - size) / 2); board.Location = this.Size.Width > this.Size.Height ? new System.Drawing.Point((this.Size.Width - size) / 2, 0) : new System.Drawing.Point(0, (this.Size.Height - size) / 2);
} }
private void board_Paint(object sender, PaintEventArgs e)
{
}
} }
} }

120
ChessPanel/ChessGame.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="ChessPanel.ChessBoard" Collapsed="true">
<Position X="19" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AICAAAAAAAAAAAAQAQAACCAEAIAgJAAACgAAAEoABII=</HashCode>
<FileName>ChessBoard.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.ChessGame" Collapsed="true">
<Position X="20.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAIAAAAEAAAAACAAAABAAAIAAAAAAAAAA=</HashCode>
<FileName>ChessGame.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Field" Collapsed="true">
<Position X="22.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AABBgAEIEIYEIBAACAAAIAACADAAAEACAAAgQAAAABA=</HashCode>
<FileName>Field.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Form1" Collapsed="true">
<Position X="19" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAEAAAACAAAAAAAACAAAACAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Form1.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Piece" Collapsed="true">
<Position X="10.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAABAAAAAAAAAAAAAAAAAAAAEAABAACAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Rook" Collapsed="true">
<Position X="9.75" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Pawn" Collapsed="true">
<Position X="14.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Knight" Collapsed="true">
<Position X="5.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Bishop" Collapsed="true">
<Position X="7.5" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Queen" Collapsed="true">
<Position X="12" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.King" Collapsed="true">
<Position X="16.5" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAgAAAA=</HashCode>
<FileName>Piece.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Program" Collapsed="true">
<Position X="20.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
<FileName>Program.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Chess.Properties.Resources" Collapsed="true">
<Position X="22.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAADAgQAQABAAAAIBEAAAIUAAIAAABAACAAAAIIA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Chess.Properties.Settings" Collapsed="true">
<Position X="19" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAIAAAAAABAAAAAAAAAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Struct Name="Chess.FieldColorSet" Collapsed="true">
<Position X="19" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAQAQAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>FieldColorSet.cs</FileName>
</TypeIdentifier>
</Struct>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@ -21,17 +21,35 @@ namespace Chess
private FieldColorSet currentEnemyColorSet; private FieldColorSet currentEnemyColorSet;
private FieldColorSet currentSelectedColorSet; private FieldColorSet currentSelectedColorSet;
private FieldColorSet currentAllyColorSet; private FieldColorSet currentAllyColorSet;
public delegate void ClickEventHandler(Vector coordinates); public delegate void ClickEventHandler(Field sender);
public event ClickEventHandler FieldClick; public event ClickEventHandler FieldClick;
public bool IsEmpty { get { return currentPiece == null; } } public bool IsEmpty { get { return currentPiece == null; } }
public Piece currentPiece; public Piece currentPiece;
public Piece CurrentPiece public Piece CurrentPiece
{ {
get { return currentPiece; } get
set { currentPiece = value; RefreshPiece(); } {
return currentPiece;
}
set
{
currentPiece = value;
RefreshPiece();
}
}
public override string Text
{
get
{
return "";
var pos = location.ToString();
if (IsEmpty)
return pos + Environment.NewLine + "leer";
return pos + Environment.NewLine + currentPiece.ToString();
}
} }
private void RefreshPiece() public void RefreshPiece()
{ {
if (currentPiece == null) if (currentPiece == null)
this.BackgroundImage = ChessPanel.Properties.Resources.Empty; this.BackgroundImage = ChessPanel.Properties.Resources.Empty;
@ -40,17 +58,17 @@ namespace Chess
} }
public void Deselect() public void Deselect()
{ {
setActiveColorSet(currentNormalColorSet); SetActiveColorSet(currentNormalColorSet);
} }
public void Highlight(PieceTeam team) // validTargetField public void Highlight(PieceTeam team) // validTargetField
{ {
switch (team) switch (team)
{ {
case PieceTeam.Enemy: case PieceTeam.Enemy:
setActiveColorSet(currentEnemyColorSet); SetActiveColorSet(currentEnemyColorSet);
break; break;
case PieceTeam.Ally: case PieceTeam.Ally:
setActiveColorSet(currentAllyColorSet); SetActiveColorSet(currentAllyColorSet);
break; break;
default: default:
break; break;
@ -58,9 +76,9 @@ namespace Chess
} }
public new void Select() // selectedField public new void Select() // selectedField
{ {
setActiveColorSet(currentSelectedColorSet); SetActiveColorSet(currentSelectedColorSet);
} }
private void setActiveColorSet(FieldColorSet set) private void SetActiveColorSet(FieldColorSet set)
{ {
this.BackColor = set.NormalColor; this.BackColor = set.NormalColor;
this.FlatAppearance.MouseDownBackColor = set.MouseDownColor; this.FlatAppearance.MouseDownBackColor = set.MouseDownColor;
@ -68,34 +86,36 @@ namespace Chess
} }
public Field(int x, int y) public Field(int x, int y)
{ {
this.currentNormalColorSet = (x + y) % 2 == 0 ? primaryNormalColorSet : secondaryNormalColorSet; this.currentNormalColorSet = (x + y) % 2 == 0 ? FieldColorSet.primaryNormalColorSet : FieldColorSet.secondaryNormalColorSet;
this.currentAllyColorSet = (x + y) % 2 == 0 ? primaryValidFriendlyTargetFieldSet : secondaryValidFriendlyTargetFieldSet; this.currentAllyColorSet = (x + y) % 2 == 0 ? FieldColorSet.primaryValidFriendlyTargetFieldSet : FieldColorSet.secondaryValidFriendlyTargetFieldSet;
this.currentEnemyColorSet = (x + y) % 2 == 0 ? primaryValidEnemyTargetFieldSet : secondaryValidEnemyTargetFieldSet; this.currentEnemyColorSet = (x + y) % 2 == 0 ? FieldColorSet.primaryValidEnemyTargetFieldSet : FieldColorSet.secondaryValidEnemyTargetFieldSet;
this.currentSelectedColorSet = (x + y) % 2 == 0 ? primarySelectedColorSet : secondarySelectedColorSet; this.currentSelectedColorSet = (x + y) % 2 == 0 ? FieldColorSet.primarySelectedColorSet : FieldColorSet.secondarySelectedColorSet;
this.FlatStyle = FlatStyle.Flat; this.FlatStyle = FlatStyle.Flat;
this.FlatAppearance.BorderSize = 0; this.FlatAppearance.BorderSize = 0;
this.setActiveColorSet(this.currentNormalColorSet); this.SetActiveColorSet(this.currentNormalColorSet);
this.Cursor = Cursors.Arrow; this.Cursor = Cursors.Arrow;
this.location = new Vector(x, y); // NICHT L(!)ocation, der gibt die Position des Buttons in Pixel auf dem Control an! this.location = new Vector(x, y); // NICHT L(!)ocation, der gibt die Position des Buttons in Pixel auf dem Control an!
this.Name = string.Format($"field[{x},{y}]"); this.Name = string.Format($"field[{x},{y}]");
this.Text = ""; this.Text = string.Empty;
this.BackgroundImageLayout = ImageLayout.Zoom; this.BackgroundImageLayout = ImageLayout.Zoom;
this.BackgroundImage = ChessPanel.Properties.Resources.Empty; this.BackgroundImage = ChessPanel.Properties.Resources.Empty;
this.Click += clicked; this.Click += Clicked;
} }
private void clicked(object sender, EventArgs e) private void Clicked(object sender, EventArgs e)
{ {
FieldClick(this.location); FieldClick(this);
} }
public override string ToString() public override string ToString()
{ {
return this.currentPiece.type.ToString(); if (IsEmpty)
return "leer";
return this.currentPiece.ToString();
} }
} }
} }

View File

@ -3,6 +3,14 @@ namespace Chess
{ {
struct FieldColorSet struct FieldColorSet
{ {
public static readonly FieldColorSet primaryNormalColorSet = new FieldColorSet(Color.FromArgb(204, 204, 204), Color.FromArgb(153, 153, 153), Color.White);
public static readonly FieldColorSet secondaryNormalColorSet = new FieldColorSet(Color.FromArgb(51, 51, 51), Color.FromArgb(102, 102, 102), Color.Black);
public static readonly FieldColorSet primarySelectedColorSet = new FieldColorSet(Color.FromArgb(204, 204, 102), Color.FromArgb(153, 153, 102), Color.FromArgb(255, 255, 102));
public static readonly FieldColorSet secondarySelectedColorSet = new FieldColorSet(Color.FromArgb(204, 204, 51), Color.FromArgb(153, 153, 51), Color.FromArgb(255, 255, 51));
public static readonly FieldColorSet primaryValidFriendlyTargetFieldSet = new FieldColorSet(Color.FromArgb(102, 204, 102), Color.FromArgb(102, 153, 102), Color.FromArgb(102, 255, 102));
public static readonly FieldColorSet secondaryValidFriendlyTargetFieldSet = new FieldColorSet(Color.FromArgb(51, 204, 51), Color.FromArgb(51, 153, 51), Color.FromArgb(51, 255, 51));
public static readonly FieldColorSet primaryValidEnemyTargetFieldSet = new FieldColorSet(Color.FromArgb(204, 102, 102), Color.FromArgb(153, 102, 102), Color.FromArgb(255, 102, 102));
public static readonly FieldColorSet secondaryValidEnemyTargetFieldSet = new FieldColorSet(Color.FromArgb(204, 51, 51), Color.FromArgb(153, 51, 51), Color.FromArgb(255, 51, 51));
public FieldColorSet(Color MOC, Color MDC, Color NC) public FieldColorSet(Color MOC, Color MDC, Color NC)
{ {
MouseOverColor = MOC; MouseOverColor = MOC;

169
ChessPanel/Grid.cs Normal file
View File

@ -0,0 +1,169 @@
using Chess;
using System;
using System.Windows;
using System.Collections;
namespace ChessPanel
{
public class Grid : IEnumerable
{
public Grid(int GridSize)
{
fields = new Field[GridSize, GridSize];
this.GridSize = GridSize;
}
//public Grid(Field[,] fields)
//{
// this.GridSize = fields.GetLength(0);
// this.fields = CopyMultiArray(fields);
//}
/// <summary>
/// Creates a copy of the given array;
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Array"></param>
/// <returns></returns>
private static T[,] CopyMultiArray<T>(T[,] Array)
{
int[] dim = new int[] { Array.GetLength(0), Array.GetLength(1) };
T[,] Copy = new T[dim[0], dim[1]];
for (int x = 0; x < dim[0]; x++)
for (int y = 0; y < dim[1]; y++)
Copy[x, y] = Array[x, y];
return Copy;
}
//public Grid(Grid fields) : this(fields.fields) { }
public Field[,] fields;
public int GridSize;
public Field this[Vector v] { get { return fields[(int)v.X, (int)v.Y]; } set { fields[(int)v.X, (int)v.Y] = value; } }
internal Piece GetKing(PieceColor color)
{
foreach (Field item in this)
{
if (item.CurrentPiece?.color == color && item.CurrentPiece?.type == PieceType.King)
return item.CurrentPiece;
}
throw new Exception("No King found");
}
public Field this[int x, int y] { get { return fields[x, y]; } set { fields[x, y] = value; } }
public Field this[double x, double y] { get { return fields[(int)x, (int)y]; } set { fields[(int)x, (int)y] = value; } }
/// <summary>
/// Adds x and y values to Vector v and gets the field at the position
/// </summary>
/// <param name="v">Vector</param>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <returns>Field</returns>
public Field this[Vector v, int x, int y] { get { return fields[x + (int)v.X, y + (int)v.Y]; } set { fields[x + (int)v.X, y + (int)v.Y] = value; } }
public Field this[int x, int y, Vector v] { get { return fields[x + (int)v.X, y + (int)v.Y]; } set { fields[x + (int)v.X, y + (int)v.Y] = value; } }
public Field this[Vector v, double x, double y]
{
get
{
return fields[(int)x + (int)v.X, (int)y + (int)v.Y];
}
set
{
fields[(int)x + (int)v.X, (int)y + (int)v.Y] = value;
}
}
public Field this[double x, double y, Vector v] { get { return fields[(int)x + (int)v.X, (int)y + (int)v.Y]; } set { fields[(int)x + (int)v.X, (int)y + (int)v.Y] = value; } }
public Field GetFieldWithOffset(Field f, double x, double y)
{
int _x = (int)(f.location.X + x);
int _y = (int)(f.location.Y + y);
return fields[_x, _y];
}
/// <summary>
/// Checks if a field is endagered by a party
/// </summary>
/// <param name="field">Reference to the Field that should be checked</param>
/// <param name="color">Color of the attacking party</param>
/// <param name="movePiece">Piece that virtually got moved</param>
/// <param name="targetPos">Field that the movePiece virtually moved to</param>
/// <returns></returns>
public bool IsFieldVirtuallyEndagered(Field field, PieceColor color, Piece movePiece, Field targetPos)
{
foreach (Field item in this)
{
if (item.IsEmpty) continue; // Feld ist leer
if (item == movePiece.field) continue; // Quellfeld muss nicht geprüft werden
Piece p = item.CurrentPiece;
if (p.color != color) continue; // Figur ist kein Gegner
// Ask every Piece of the other party if it can attack the specified field
if (p.EndageresFieldWithVirtualMove(this, field, movePiece, targetPos))
//if (item.currentPiece.GetValidTargetFields(movePiece, targetPos).ContainsKey(field))
return true;
}
return false;
}
IEnumerator IEnumerable.GetEnumerator()
{
return new FieldEnum(fields);
}
}
// When you implement IEnumerable, you must also implement IEnumerator.
public class FieldEnum : IEnumerator
{
public Field[,] field;
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
int width;
int height;
public FieldEnum(Field[,] list)
{
field = list;
width = list.GetLength(0);
height = list.GetLength(1);
}
public bool MoveNext()
{
position++;
return (position < field.Length);
}
public void Reset()
{
position = -1;
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public Field Current
{
get
{
try
{
return field[position % 8, position / 8];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
}

View File

@ -5,11 +5,11 @@ namespace Chess
{ {
public partial class MainForm : Form public partial class MainForm : Form
{ {
bool Fullscreen = false; bool _fullscreen = false;
bool fullscreen bool Fullscreen
{ {
get { return Fullscreen; } get { return _fullscreen; }
set { Fullscreen = value; RefreshFullScreen(); } set { _fullscreen = value; RefreshFullScreen(); }
} }
public MainForm() public MainForm()
{ {
@ -19,7 +19,7 @@ namespace Chess
private void RefreshFullScreen() private void RefreshFullScreen()
{ {
this.SuspendLayout(); this.SuspendLayout();
if (fullscreen) if (Fullscreen)
{ {
this.WindowState = FormWindowState.Normal; this.WindowState = FormWindowState.Normal;
this.FormBorderStyle = FormBorderStyle.None; this.FormBorderStyle = FormBorderStyle.None;
@ -36,7 +36,7 @@ namespace Chess
private void MainForm_KeyUp(object sender, KeyEventArgs e) private void MainForm_KeyUp(object sender, KeyEventArgs e)
{ {
if (e.KeyCode == Keys.F11) if (e.KeyCode == Keys.F11)
fullscreen = !fullscreen; Fullscreen = !Fullscreen;
} }
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
@ -46,7 +46,7 @@ namespace Chess
private void MainForm_Load(object sender, EventArgs e) private void MainForm_Load(object sender, EventArgs e)
{ {
fullscreen = true; Fullscreen = true;
} }
} }
} }

View File

@ -1,461 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using ChessPanel;
using System.Linq;
using System.Windows;
namespace Chess
{
public abstract class Piece
{
public enum PieceColor { White, Black };
public enum PieceTeam { Enemy, Ally };
public enum PieceType { King, Queen, Bishop, Rook, Knight, Pawn };
public PieceColor color;
public PieceType type;
public Image image;
public bool HasMoved = false;
public bool EnPassantPossible = false; // Only in Pawn Class. Signs that this Piece has virtually not jumped two pieces, but one
internal static bool IsEndangeredLocationForPiece(Field[,] fields, Vector pieceLocation, Vector testLocation, PieceColor color)
{
bool returnValue = false;
Piece p = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
foreach (var field in fields)
{
if (field.currentPiece != null) if (field.currentPiece.color != color) if (field.currentPiece.GetValidTargetFields(fields, field.location, true).ContainsKey(testLocation))
{
returnValue = true;
break;
}
}
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p;
return returnValue;
}
internal static bool MoveWillEndangerKing(Field[,] fields, Vector pieceLocation, Vector pieceMovedLocation, PieceColor color) // This does not test if it is a valid move spot
{
bool returnValue = false;
Piece p1 = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
Piece p2 = fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece;
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p1;
returnValue = KingIsEndangered(fields, color);
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p1;
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p2;
return returnValue;
}
private static bool KingIsEndangered(Field[,] fields, PieceColor color)
{
Vector kingLocation = GetKingLocation(fields, color);
foreach (var field in fields)
{
if (field.currentPiece == null || field.currentPiece.color != color)
continue;
if (field.currentPiece.GetValidTargetFields(fields, field.location, testKingDanger: true).ContainsKey(kingLocation))
{
return true;
}
}
return false;
}
private static Vector GetKingLocation(Field[,] fields, PieceColor color)
{
foreach (var field in fields)
if (!field.IsEmpty && field.currentPiece.type == PieceType.King && field.currentPiece.color == color)
return field.location;
throw new Exception("King not found!");
}
internal abstract Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector currentLocation, bool onlyAttackFields = false, bool testKingDanger = false);
}
public class Rook : Piece
{
public Rook(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color);
/*if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
internal static Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
for (int x = (int)location.X - 1; x >= 0; x--) // nach Links
{
if (fields[x, (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[x, (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Enemy);
break;
}
}
for (int x = (int)location.X + 1; x <= 7; x++) // nach Rechts
{
if (fields[x, (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[x, (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Enemy);
break;
}
}
for (int y = (int)location.Y - 1; y >= 0; y--) // nach Unten
{
if (fields[(int)(int)location.X, y].IsEmpty)
{
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Ally);
}
else
{
if (fields[(int)(int)location.X, y].currentPiece.color != color)
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Enemy);
break;
}
}
for (int y = (int)location.Y + 1; y <= 7; y++) // nach Oben
{
if (fields[(int)(int)location.X, y].IsEmpty)
{
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Ally);
}
else
{
if (fields[(int)(int)location.X, y].currentPiece.color != color)
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Enemy);
break;
}
}
return targetFields;
}
} // FINALIZED
public class Pawn : Piece
{
public Pawn(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool onlyAttackFields = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color, onlyAttackFields);
/*if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
private Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color, bool onlyAttackFields = false)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
int direction = this.color == PieceColor.White ? -1 : 1;
#region EnPassant
if (location.Y == (this.color == PieceColor.White ? 3 : 4))
for (int x = -1; x < 2; x += 2)
if (location.X + x <= 7 && location.X + x >= 0)
if (fields[(int)location.X + x, (int)location.Y].currentPiece != null)
if (fields[(int)location.X + x, (int)location.Y].currentPiece.type == PieceType.Pawn)
if (fields[(int)location.X + x, (int)location.Y].currentPiece.color != this.color)
if (fields[(int)location.X + x, (int)location.Y].currentPiece.EnPassantPossible)
targetFields.Add(new Vector(location.X + x, location.Y + direction), PieceTeam.Enemy);
#endregion
#region Movement
if (!onlyAttackFields)
for (int y = 1; y < 1 + (HasMoved ? 1 : 2); y++)
{
if (location.Y + (direction * y) > 7 || location.Y + (direction * y) < 0)
break;
if (fields[(int)location.X, (int)location.Y + (direction * y)].IsEmpty)
targetFields.Add(new Vector(location.X, (int)location.Y + (direction * y)), PieceTeam.Ally);
else
break;
}
#endregion
#region Attack
for (int x = -1; x < 2; x += 2)
{
if (location.Y + (direction) > 7 || location.Y + (direction) < 0 || location.X + x > 7 || location.X + x < 0)
continue;
if (onlyAttackFields || (fields[(int)location.X + x, (int)location.Y + (direction)].currentPiece != null && fields[(int)location.X + x, (int)location.Y + (direction)].currentPiece.color != this.color))
{
targetFields.Add(new Vector((int)location.X + x, (int)location.Y + (direction)), PieceTeam.Enemy);
}
}
#endregion
return targetFields;
}
} // EN-PASSANT MISSING
public class Knight : Piece
{
public Knight(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color);
/* if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
private Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
for (int a = -1; a < 2; a += 2)
{
for (int b = -2; b < 3; b += 4)
{
if (!(a + (int)location.X > 7 || b + (int)location.Y < 0 || a + (int)location.X < 0 || b + (int)location.Y > 7))
{
if (fields[a + (int)location.X, b + (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(a + (int)location.X, b + (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[a + (int)location.X, b + (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(a + (int)location.X, b + (int)location.Y), PieceTeam.Enemy);
}
}
if (!(b + (int)location.X > 7 || a + (int)location.Y < 0 || b + (int)location.X < 0 || a + (int)location.Y > 7))
{
if (fields[b + (int)location.X, a + (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(b + (int)location.X, a + (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[b + (int)location.X, a + (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(b + (int)location.X, a + (int)location.Y), PieceTeam.Enemy);
}
}
}
}
return targetFields;
}
} // FINALIZED
public class Bishop : Piece
{
public Bishop(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool onlyAttackFields = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color, onlyAttackFields);
/* if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
internal static Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color, bool onlyAttackFields = true)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
for (int xy = 1; xy <= 7; xy++) // nach RechtsOben
{
if (location.X + xy > 7 || (int)location.Y + xy > 7)
break;
if (fields[xy + (int)location.X, xy + (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(xy + (int)location.X, xy + (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[xy + (int)location.X, xy + (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(xy + (int)location.X, xy + (int)location.Y), PieceTeam.Enemy);
break;
}
}
for (int xy = 1; xy <= 7; xy++) // nach LinksOben
{
if (location.X - xy < 0 || (int)location.Y + xy > 7)
break;
if (fields[(int)location.X - xy, (int)location.Y + xy].IsEmpty)
{
targetFields.Add(new Vector(location.X - xy, (int)location.Y + xy), PieceTeam.Ally);
}
else
{
if (fields[(int)location.X - xy, (int)location.Y + xy].currentPiece.color != color)
targetFields.Add(new Vector(location.X - xy, (int)location.Y + xy), PieceTeam.Enemy);
break;
}
}
for (int xy = 1; xy <= 7; xy++) // nach RechtsUnten
{
if (location.X + xy > 7 || (int)location.Y - xy < 0)
break;
if (fields[xy + (int)location.X, (int)location.Y - xy].IsEmpty)
{
targetFields.Add(new Vector(xy + (int)location.X, (int)location.Y - xy), PieceTeam.Ally);
}
else
{
if (fields[xy + (int)location.X, (int)location.Y - xy].currentPiece.color != color)
targetFields.Add(new Vector(xy + (int)location.X, (int)location.Y - xy), PieceTeam.Enemy);
break;
}
}
for (int xy = 1; xy <= 7; xy++) // nach LinksUnten
{
if (location.X - xy < 0 || (int)location.Y - xy < 0)
break;
if (fields[(int)location.X - xy, (int)location.Y - xy].IsEmpty)
{
targetFields.Add(new Vector(location.X - xy, (int)location.Y - xy), PieceTeam.Ally);
}
else
{
if (fields[(int)location.X - xy, (int)location.Y - xy].currentPiece.color != color)
targetFields.Add(new Vector(location.X - xy, (int)location.Y - xy), PieceTeam.Enemy);
break;
}
}
return targetFields;
}
} // FINALIZED
public class Queen : Piece
{
public Queen(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false)
{
Dictionary<Vector, PieceTeam> targetFields = Rook.GetTargetFields(fields, location, this.color);
targetFields = targetFields.Concat(Bishop.GetTargetFields(fields, location, this.color)
.Where(kvp => !targetFields.ContainsKey(kvp.Key)))
.OrderBy(c => c.Value)
.ToDictionary(c => c.Key, c => c.Value);
/*if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
} // FINALIZED
public class King : Piece
{
public King(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false) // ignoreKingCheck hat keinen Einfluss
{
return GetTargetFields(fields, location, this.color);
}
private Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
#region Castling
if (!this.HasMoved) // Only Castle if King did not move
foreach (var item in fields)
{
var itemLocation = item.location;
// Sucht nach Ally Turm und prüft, ob er sich schon bewegt hat
if (item.currentPiece != null && item.currentPiece.type == PieceType.Rook && !item.currentPiece.HasMoved && item.currentPiece.color == this.color)
{
if (itemLocation.X == 0 || itemLocation.X == 7)
{
bool castling = true;
for (int x = (itemLocation.X == 0 ? 1 : 5); (itemLocation.X == 0 ? x < 4 : x < 7); x++)
{
if (!fields[x, (int)location.Y].IsEmpty)
{
castling = false;
break;
}
}
if (castling) // Only Check endangered Fields if castling is generally possible
{
for (int x = (itemLocation.X == 0 ? 2 : 4); x < (itemLocation.X == 0 ? 5 : 7); x++) // König steht im Schach oder überschreitet bedrohtes Feld
{
if (IsEndangeredLocationForPiece(fields, location, new Vector(x, location.Y), color))
{
castling = false;
break;
}
}
if (castling)
{
targetFields.Add(new Vector((itemLocation.X == 0 ? 2 : 6), itemLocation.Y), PieceTeam.Ally);
}
}
}
}
}
#endregion
#region Movement: 1 in every direction
for (int x = -1; x < 2; x++)
{
for (int y = -1; y < 2; y++)
{
if ((x == 0 && y == 0) || location.X + x > 7 || location.Y + y > 7 || location.X + x < 0 || location.Y + y < 0)
continue;
if (!IsEndangeredLocationForPiece(fields, location, new Vector(location.X + x, location.Y + y), color))
if (fields[(int)location.X + x, (int)location.Y + y].IsEmpty)
{
targetFields.Add(new Vector(location.X + x, (int)location.Y + y), PieceTeam.Ally);
}
else
{
if (fields[(int)location.X + x, (int)location.Y + y].currentPiece.color != color)
targetFields.Add(new Vector(location.X + x, (int)location.Y + y), PieceTeam.Enemy);
continue;
}
}
}
#endregion
return targetFields;
}
} // CHECKMATE/CHECK-TEST MISSING
}

View File

@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using ChessPanel;
using System.Linq;
using System.Windows;
namespace Chess
{
public enum PieceColor { White, Black };
public enum PieceTeam { Enemy, Ally };
public enum PieceType { King, Queen, Bishop, Rook, Knight, Pawn };
public enum MoveMode { Normal, Attack, Movement };
/// <summary>
/// Figur
/// </summary>
public abstract class Piece
{
public PieceColor color;
public PieceType type;
public Dictionary<Field, PieceTeam> validTargetSpots;
public Image image;
public bool HasMoved = false;
public Field field;
public bool EnPassantPossible = false; // Only in Pawn Class. Signs that this Piece has virtually not jumped two pieces, but one, reflective meaning: This.Figure can be attacked using Enpassant if this.type is Pawn
public override string ToString()
{
return type.ToString();
}
public Piece(Vector position, Grid fields)
{
this.field = fields[position];
fields[position].CurrentPiece = this;
}
public Dictionary<Field, PieceTeam> RefreshValidTargetSpots(Grid fields, MoveMode mode = MoveMode.Normal)
{
this.validTargetSpots = this.GetValidTargetFields(fields, mode);
return validTargetSpots;
}
internal void RemoveTargetFieldsWhereKingIsEndangered(Grid fields, Dictionary<Field, PieceTeam> targetFields)
{
Field ownKingLocation = fields.GetKing(this.color).field;
foreach (var virtualTargetField in targetFields)
{
if (fields.IsFieldVirtuallyEndagered(ownKingLocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, virtualTargetField.Key))
targetFields.Remove(virtualTargetField.Key);
}
}
/// <summary>
/// Tests if the Move will leave your King endangered.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="pieceLocation">Location of Piece to move</param>
/// <param name="simulatedLocation">Location to move Piece to</param>
/// <param name="color">Color of Piece to move</param>
/// <returns>Bool</returns>
/* internal static bool MoveWillEndangerOwnKing(Grid fields, Vector pieceLocation, Vector simulatedLocation, PieceColor color)
{
// fields[simulateLocation].currentPiece = fields[pieceLocation].currentPiece;
// fields[pieceLocation].currentPiece = null;
// Check if own king is endangered
return FieldIsEndangered(fields, simulatedLocation, kingLocation, color, dontTestKingDanger: true);
}*/
/// <summary>
/// Checks if a specific field can be reached by the figure while a virtual move is simulated
/// </summary>
/// <param name="movePiece">Piece that virtually got moved</param>
/// <param name="targetPos">Field that the movePiece virtually moved to</param>
/// <param name="possibleEndageredField">Field that should be checked</param>
/// <param name="fields">Current Game Grid</param>
/// <returns></returns>
internal abstract bool EndageresFieldWithVirtualMove(Grid fields, Field possibleEndageredField, Piece movePiece, Field targetPos);
internal void Move(Field newPieceField)
{
this.field.CurrentPiece = null; // Remove piece from previous position
this.field = newPieceField; // Set pieces location to new field
newPieceField.CurrentPiece = this; // Set new fields piece to this
}
/// <summary>
/// Tests if the Move will leave your movedPiece endangered.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="pieceLocation">Location of Piece to move</param>
/// <param name="testLocation">Location to move Piece to</param>
/// <param name="color">Color of Piece to move</param>
/// <returns>Bool</returns>
//internal static bool MoveWillEndangerPiece(Grid fields, Vector pieceLocation, Vector testLocation, PieceColor color)
//{
// return false;
// //Grid simulatedField = fields;
// //simulatedField[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
// //return FieldIsEndangered(fields simulatedField, testLocation, color);
//}
/// <summary>
/// Tests if your King is currently endangered.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="color">Kings color</param>
/// <returns></returns>
//private static bool KingIsEndangered(Grid fields, PieceColor color) => FieldIsEndangered(fields, GetKingLocation(fields, color), color, dontTestKingDanger: true);
/// <summary>
/// Tests if the testLocation is endangered by an enemy.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="color">Ally Color</param>
/// <param name="testLocation">Location to test</param>
/// <returns>Bool</returns>
//private static bool FieldIsEndangered(Grid fields, Vector simulatedLocation, Vector testLocation, PieceColor color, bool dontTestKingDanger = false)
//{
// foreach (Field field in fields)
// {
// if (field.location != simulatedLocation
// && field.currentPiece != null
// && field.currentPiece.color != color
// && field.currentPiece.GetValidTargetFields(fields, dontTestKingDanger: dontTestKingDanger).ContainsKey(testLocation))
// return true;
// }
// return false;
//}
/*internal static bool IsEndangeredLocationForPiece(Grid fields, Vector pieceLocation, Vector testLocation, PieceColor color)
{
bool returnValue = false;
Piece p = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
foreach (var field in fields)
{
if (field.currentPiece != null) if (field.currentPiece.color != color) if (field.currentPiece.GetValidTargetFields(fields, field.location, true).ContainsKey(testLocation))
{
returnValue = true;
break;
}
}
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p;
return returnValue;
}*/
/* internal static bool MoveWillEndangerKing(Grid fields, Vector pieceLocation, Vector pieceMovedLocation, PieceColor color) // This does not test if it is a valid move spot
{
bool returnValue = false;
Piece p1 = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
Piece p2 = fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece;
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p1;
returnValue = KingIsEndangered(fields, color);
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p1;
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p2;
return returnValue;
}*/
/* private static bool KingIsEndangered(Grid fields, PieceColor color)
{
Vector kingLocation = GetKingLocation(fields, color);
foreach (var field in fields)
{
if (field.currentPiece == null || field.currentPiece.color != color)
continue;
if (field.currentPiece.GetValidTargetFields(fields, field.location, dontTestKingDanger: true).ContainsKey(kingLocation))
{
return true;
}
}
return false;
}*/
/// <summary>
/// Searches for the King of the given color.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="color">Kings color</param>
/// <returns>King location as Vector</returns>
private static Vector GetKingLocation(Grid fields, PieceColor color)
{
foreach (Field field in fields)
if (!field.IsEmpty && field.currentPiece.type == PieceType.King && field.currentPiece.color == color)
return field.location;
throw new Exception("King not found!");
}
virtual internal Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Normal, bool dontTestKingDanger = false)
{
var targetFields = GetTargetFields(fields, field, this.color);
if (!dontTestKingDanger)
{
Field kinglocation = fields.GetKing(this.color).field;
List<Field> remove = new List<Field>();
foreach (var item in targetFields.Keys)
{
if (fields.IsFieldVirtuallyEndagered(kinglocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, item))
remove.Add(item);
}
foreach (var item in remove)
{
targetFields.Remove(item);
}
}
return targetFields;
}
internal abstract Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color);
internal static bool FieldIsVirtuallyEmpty(Field targetPos, Field skipField, Field possibleTargetField)
{
return (possibleTargetField.IsEmpty && possibleTargetField != targetPos)
|| possibleTargetField == skipField;
}
internal static bool CheckFieldCanBeReached(Field possibleEndageredField, Field targetPos, Piece movePiece, Field possibleTargetField, PieceColor color, out bool breakIt)
{
breakIt = false;
var skipField = movePiece.field;
if (FieldIsVirtuallyEmpty(targetPos, skipField, possibleTargetField))
{
if (possibleTargetField == possibleEndageredField)
return true;
}
else
{
var checkPiece = possibleTargetField == targetPos ? movePiece : possibleTargetField.CurrentPiece;
if (checkPiece.color != color && possibleTargetField == possibleEndageredField)
return true;
breakIt=true;
}
return false;
}
//internal abstract Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Any, bool dontTestKingDanger = false);
}
}

View File

@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using ChessPanel;
using System.Linq;
using System.Windows;
namespace Chess
{
public enum PieceColor { White, Black };
public enum PieceTeam { Enemy, Ally };
public enum PieceType { King, Queen, Bishop, Rook, Knight, Pawn };
public enum MoveMode { Any, Attack, Movement };
/// <summary>
/// Figur
/// </summary>
public abstract class Piece
{
public PieceColor color;
public PieceType type;
public Image image;
public bool HasMoved = false;
public Field field;
private Vector virtualPosition;//?
public bool EnPassantPossible = false; // Only in Pawn Class. Signs that this Piece has virtually not jumped two pieces, but one, reflective meaning: This.Figure can be attacked using Enpassant if this.type is Pawn
public override string ToString()
{
return type.ToString();
}
public Piece(Vector position, Grid fields)
{
this.field = fields[position];
fields[position].CurrentPiece = this;
}
internal void removeTargetFieldsWhereKingIsEndangered(Grid fields, Dictionary<Field, PieceTeam> targetFields)
{
Field ownKingLocation = fields.GetKing(this.color).field;
foreach (var virtualTargetField in targetFields)
{
if (fields.IsFieldVirtuallyEndagered(ownKingLocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, virtualTargetField.Key))
targetFields.Remove(virtualTargetField.Key);
}
}
/// <summary>
/// Tests if the Move will leave your King endangered.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="pieceLocation">Location of Piece to move</param>
/// <param name="simulatedLocation">Location to move Piece to</param>
/// <param name="color">Color of Piece to move</param>
/// <returns>Bool</returns>
/* internal static bool MoveWillEndangerOwnKing(Grid fields, Vector pieceLocation, Vector simulatedLocation, PieceColor color)
{
// fields[simulateLocation].currentPiece = fields[pieceLocation].currentPiece;
// fields[pieceLocation].currentPiece = null;
// Check if own king is endangered
return FieldIsEndangered(fields, simulatedLocation, kingLocation, color, dontTestKingDanger: true);
}*/
/// <summary>
/// Checks if a specific field can be reached by the figure while a virtual move is simulated
/// </summary>
/// <param name="movePiece">Piece that virtually got moved</param>
/// <param name="targetPos">Field that the movePiece virtually moved to</param>
/// <param name="possibleEndageredField">Field that should be checked</param>
/// <param name="fields">Current Game Grid</param>
/// <returns></returns>
internal abstract bool EndageresFieldWithVirtualMove(Grid fields, Field possibleEndageredField, Piece movePiece, Field targetPos);
internal void Move(Field newPieceField)
{
this.field.CurrentPiece = null; // Remove piece from previous position
this.field = newPieceField; // Set pieces location to new field
newPieceField.CurrentPiece = this; // Set new fields piece to this
}
/// <summary>
/// Tests if the Move will leave your movedPiece endangered.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="pieceLocation">Location of Piece to move</param>
/// <param name="testLocation">Location to move Piece to</param>
/// <param name="color">Color of Piece to move</param>
/// <returns>Bool</returns>
//internal static bool MoveWillEndangerPiece(Grid fields, Vector pieceLocation, Vector testLocation, PieceColor color)
//{
// return false;
// //Grid simulatedField = fields;
// //simulatedField[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
// //return FieldIsEndangered(fields simulatedField, testLocation, color);
//}
/// <summary>
/// Tests if your King is currently endangered.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="color">Kings color</param>
/// <returns></returns>
//private static bool KingIsEndangered(Grid fields, PieceColor color) => FieldIsEndangered(fields, GetKingLocation(fields, color), color, dontTestKingDanger: true);
/// <summary>
/// Tests if the testLocation is endangered by an enemy.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="color">Ally Color</param>
/// <param name="testLocation">Location to test</param>
/// <returns>Bool</returns>
//private static bool FieldIsEndangered(Grid fields, Vector simulatedLocation, Vector testLocation, PieceColor color, bool dontTestKingDanger = false)
//{
// foreach (Field field in fields)
// {
// if (field.location != simulatedLocation
// && field.currentPiece != null
// && field.currentPiece.color != color
// && field.currentPiece.GetValidTargetFields(fields, dontTestKingDanger: dontTestKingDanger).ContainsKey(testLocation))
// return true;
// }
// return false;
//}
/*internal static bool IsEndangeredLocationForPiece(Grid fields, Vector pieceLocation, Vector testLocation, PieceColor color)
{
bool returnValue = false;
Piece p = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
foreach (var field in fields)
{
if (field.currentPiece != null) if (field.currentPiece.color != color) if (field.currentPiece.GetValidTargetFields(fields, field.location, true).ContainsKey(testLocation))
{
returnValue = true;
break;
}
}
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p;
return returnValue;
}*/
/* internal static bool MoveWillEndangerKing(Grid fields, Vector pieceLocation, Vector pieceMovedLocation, PieceColor color) // This does not test if it is a valid move spot
{
bool returnValue = false;
Piece p1 = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
Piece p2 = fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece;
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p1;
returnValue = KingIsEndangered(fields, color);
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p1;
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p2;
return returnValue;
}*/
/* private static bool KingIsEndangered(Grid fields, PieceColor color)
{
Vector kingLocation = GetKingLocation(fields, color);
foreach (var field in fields)
{
if (field.currentPiece == null || field.currentPiece.color != color)
continue;
if (field.currentPiece.GetValidTargetFields(fields, field.location, dontTestKingDanger: true).ContainsKey(kingLocation))
{
return true;
}
}
return false;
}*/
/// <summary>
/// Searches for the King of the given color.
/// </summary>
/// <param name="fields">GameField</param>
/// <param name="color">Kings color</param>
/// <returns>King location as Vector</returns>
private static Vector GetKingLocation(Grid fields, PieceColor color)
{
foreach (Field field in fields)
if (!field.IsEmpty && field.currentPiece.type == PieceType.King && field.currentPiece.color == color)
return field.location;
throw new Exception("King not found!");
}
virtual internal Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Any, bool dontTestKingDanger = false)
{
var targetFields = GetTargetFields(fields, field, this.color);
if (!dontTestKingDanger)
{
Field kinglocation = fields.GetKing(this.color).field;
List<Field> remove = new List<Field>();
foreach (var item in targetFields.Keys)
{
if (fields.IsFieldVirtuallyEndagered(kinglocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, item))
remove.Add(item);
}
foreach (var item in remove)
{
targetFields.Remove(item);
}
}
return targetFields;
}
internal abstract Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color);
internal static bool FieldIsVirtuallyEmpty(Field targetPos, Field skipField, Field possibleTargetField)
{
return (possibleTargetField.IsEmpty && possibleTargetField != targetPos)
|| possibleTargetField == skipField;
}
internal static bool checkFieldCanBeReached(Field possibleEndageredField, Field targetPos, Piece movePiece, Field possibleTargetField, PieceColor color, out bool breakIt)
{
breakIt = false;
var skipField = movePiece.field;
if (FieldIsVirtuallyEmpty(targetPos, skipField, possibleTargetField))
{
if (possibleTargetField == possibleEndageredField)
return true;
}
else
{
var checkPiece = possibleTargetField == targetPos ? movePiece : possibleTargetField.CurrentPiece;
if (checkPiece.color != color && possibleTargetField == possibleEndageredField)
return true;
breakIt=true;
}
return false;
}
//internal abstract Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Any, bool dontTestKingDanger = false);
}
}

143
ChessPanel/Pieces/Bishop.cs Normal file
View File

@ -0,0 +1,143 @@
using Chess;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows;
namespace ChessPanel
{
public class Bishop : Piece
{
public Bishop(PieceColor color, Vector position, Grid fields) : base(position, fields)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
private static bool AddFieldToTargetFields(Grid fields, Field field, int x, int y, Dictionary<Field, PieceTeam> targetFields, PieceColor color)
{
if (fields[field.location, x, y].IsEmpty)
{
targetFields.Add(fields[field.location, x, y], PieceTeam.Ally);
}
else
{
if (fields[field.location, x, y].CurrentPiece?.color != color)
targetFields.Add(fields[field.location, x, y], PieceTeam.Enemy);
return true;
}
return false;
}
internal override Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color)
{
return StaticGetTargetFields(fields, field, color);
}
internal static Dictionary<Field, PieceTeam> StaticGetTargetFields(Grid fields, Field field, PieceColor color)
{
Dictionary<Field, PieceTeam> targetFields = new Dictionary<Field, PieceTeam>();
#region nach RechtsOben
for (int xy = 1; xy <= 7; xy++)
{
if (CheckOutOfBounds(field, xy, xy) || AddFieldToTargetFields(fields, field, xy, xy, targetFields, color))
break;
}
#endregion
// LinksOben
for (int xy = 1; xy <= 7; xy++)
{
if (CheckOutOfBounds(field, -xy, xy) || AddFieldToTargetFields(fields, field, -xy, xy, targetFields, color))
break;
}
// RechtsUnten
for (int xy = 1; xy <= 7; xy++)
{
if (CheckOutOfBounds(field, xy, -xy) || AddFieldToTargetFields(fields, field, xy, -xy, targetFields, color))
break;
}
// LinksUnten
for (int xy = 1; xy <= 7; xy++)
{
if (CheckOutOfBounds(field, -xy, -xy) || AddFieldToTargetFields(fields, field, -xy, -xy, targetFields, color))
break;
}
return targetFields;
}
private static bool CheckOutOfBounds(Field field, int x, int y)
{
return field.location.X + x > 7 || (int)field.location.Y + y > 7
|| field.location.X + x < 0 || (int)field.location.Y + y < 0;
}
/// <summary>
///
/// </summary>
/// <param name="fields">Global Field Grid</param>
/// <param name="field">Field that should be checked for endager</param>
/// <param name="movePiece">Piece that should be moved</param>
/// <param name="targetPos">Target of the moved piece</param>
/// <returns></returns>
internal override bool EndageresFieldWithVirtualMove(Grid fields, Field possibleEndageredField, Piece movePiece, Field targetPos)
{
return StaticEndageresFieldWithVirtualMove(fields, this.field, possibleEndageredField, movePiece, targetPos, color);
}
internal static bool StaticEndageresFieldWithVirtualMove(Grid fields, Field thisField, Field possibleEndageredField, Piece movePiece, Field targetPos, PieceColor color)
{
var skipField = movePiece.field;
for (int xy = 1; xy <= 7; xy++) // nach RechtsOben
{
if (thisField.location.X + xy > 7 || thisField.location.Y + xy > 7)
break;
var possibleTargetField = fields.GetFieldWithOffset(thisField, xy, xy);
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
for (int xy = 1; xy <= 7; xy++)
{
if (thisField.location.X - xy < 0 || thisField.location.Y + xy > 7) // LinksOben
break;
var possibleTargetField = fields.GetFieldWithOffset(thisField, -xy, xy);
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
for (int xy = 1; xy <= 7; xy++)
{
if (thisField.location.X + xy > 7 || thisField.location.Y - xy < 0) // RechtsUnten
break;
var possibleTargetField = fields.GetFieldWithOffset(thisField, xy, -xy);
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
for (int xy = 1; xy <= 7; xy++)
{
if (thisField.location.X - xy < 0 || thisField.location.Y - xy < 0) // LinksUnten
break;
var possibleTargetField = fields.GetFieldWithOffset(thisField, -xy, -xy);
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
return false;
}
} // FINALIZED
}

132
ChessPanel/Pieces/King.cs Normal file
View File

@ -0,0 +1,132 @@
using Chess;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows;
namespace ChessPanel
{
public class King : Piece
{
public King(PieceColor color, Vector position, Grid fields) : base(position, fields)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override bool EndageresFieldWithVirtualMove(Grid fields, Field field, Piece movePiece, Field targetPos)
{
//#region Movement: 1 in every direction
//for (int x = -1; x < 2; x++)
//{
// for (int y = -1; y < 2; y++)
// {
// if ((x == 0 && y == 0) || field.location.X + x > 7 || field.location.Y + y > 7 || field.location.X + x < 0 || field.location.Y + y < 0)
// continue;
// if (!fields.IsFieldVirtuallyEndagered(fields[field.location, x, y], (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, fields[field.location, x, y]))
// if ((fields[field.location, x, y].IsEmpty && fields[field.location, x, y] != targetPos) || fields[field.location, x, y] == movePiece.field)
// {
// if (fields[field.location, x, y] == field)
// return true;
// continue;
// }
// else
// {
// if (fields[field.location, x, y].currentPiece.color != color)
// if (fields[field.location, x, y] == field)
// return true;
// break;
// }
// }
//}
//#endregion
return false;
}
internal override Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Normal, bool dontTestKingDanger = false)
{
var targetFields = GetTargetFields(fields, field, this.color);
if (!dontTestKingDanger)
{
List<Field> remove = new List<Field>();
foreach (var virtualKinglocation in targetFields.Keys)
{
if (fields.IsFieldVirtuallyEndagered(virtualKinglocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, virtualKinglocation))
remove.Add(virtualKinglocation);
}
foreach (var item in remove)
{
targetFields.Remove(item);
}
}
return targetFields;
}
internal override Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color)
{
Dictionary<Field, PieceTeam> targetFields = new Dictionary<Field, PieceTeam>();
#region Castling
if (!this.HasMoved && false) // Only Castle if King did not move
foreach (Field item in fields)
{
var itemLocation = item.location;
// Sucht nach Ally Turm und prüft, ob er sich schon bewegt hat
if (item.currentPiece != null && item.currentPiece.type == PieceType.Rook && !item.currentPiece.HasMoved && item.currentPiece.color == this.color)
{
if (itemLocation.X == 0 || itemLocation.X == 7)
{
bool castling = true;
for (int x = (itemLocation.X == 0 ? 1 : 5); (itemLocation.X == 0 ? x < 4 : x < 7); x++)
{
if (!fields[x, (int)field.location.Y].IsEmpty)
{
castling = false;
break;
}
}
if (castling) // Only Check endangered Fields if castling is generally possible
{
for (int x = (itemLocation.X == 0 ? 2 : 4); x < (itemLocation.X == 0 ? 5 : 7); x++) // König steht im Schach oder überschreitet bedrohtes Feld
{
if (fields.IsFieldVirtuallyEndagered(fields[x, field.location.Y], (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, fields[x, field.location.Y]))
{
castling = false;
break;
}
}
if (castling)
{
targetFields.Add(fields[(itemLocation.X == 0 ? 2 : 6), itemLocation.Y], PieceTeam.Ally);
}
}
}
}
}
#endregion
#region Movement: 1 in every direction
for (int x = -1; x < 2; x++)
{
for (int y = -1; y < 2; y++)
{
if ((x == 0 && y == 0) || field.location.X + x > 7 || field.location.Y + y > 7 || field.location.X + x < 0 || field.location.Y + y < 0)
continue;
if (fields[field.location, x, y].IsEmpty)
{
targetFields.Add(fields[field.location, x, y], PieceTeam.Ally);
}
else
{
if (fields[field.location, x, y].currentPiece.color != color)
targetFields.Add(fields[field.location, x, y], PieceTeam.Enemy);
continue;
}
}
}
#endregion
return targetFields;
}
} // CHECKMATE/CHECK-TEST MISSING
}

View File

@ -0,0 +1,98 @@
using Chess;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows;
namespace ChessPanel
{
public class Knight : Piece
{
public Knight(PieceColor color, Vector position, Grid fields) : base(position, fields)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override bool EndageresFieldWithVirtualMove(Grid fields, Field field, Piece movePiece, Field targetPos)
{
for (int a = -1; a < 2; a += 2)
{
for (int b = -2; b < 3; b += 4)
{
if (!(a + (int)field.location.X > 7 || b + (int)field.location.Y < 0 || a + (int)field.location.X < 0 || b + (int)field.location.Y > 7))
{
if ((fields[field.location,a,b].IsEmpty && fields[field.location, a, b] != targetPos) || fields[field.location, a, b] == movePiece.field)
{
if (fields[field.location, a, b] == field)
return true;
continue;
}
else
{
if (fields[field.location, a, b].CurrentPiece?.color != color)
if (fields[field.location, a, b] == field)
return true;
break;
}
}
if (!(b + (int)field.location.X > 7 || a + (int)field.location.Y < 0 || b + (int)field.location.X < 0 || a + (int)field.location.Y > 7))
{
if ((fields[field.location, b, a].IsEmpty && fields[field.location, b, a] != targetPos) || fields[field.location, b, a] == movePiece.field)
{
if (fields[field.location, b, a] == field)
return true;
continue;
}
else
{
if (fields[field.location, b, a].CurrentPiece?.color != color)
if (fields[field.location, b, a] == field)
return true;
break;
}
}
}
}
return false;
}
internal override Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color)
{
Dictionary<Field, PieceTeam> targetFields = new Dictionary<Field, PieceTeam>();
for (int a = -1; a < 2; a += 2)
{
for (int b = -2; b < 3; b += 4)
{
if (!(a + (int)field.location.X > 7 || b + (int)field.location.Y < 0 || a + (int)field.location.X < 0 || b + (int)field.location.Y > 7))
{
if (fields[field.location,a,b].IsEmpty)
{
targetFields.Add(fields[field.location, a, b], PieceTeam.Ally);
}
else
{
if (fields[field.location, a, b].CurrentPiece?.color != color)
targetFields.Add(fields[field.location, a, b], PieceTeam.Enemy);
}
}
if (!(b + (int)field.location.X > 7 || a + (int)field.location.Y < 0 || b + (int)field.location.X < 0 || a + (int)field.location.Y > 7))
{
if (fields[field.location, b, a].IsEmpty)
{
targetFields.Add(fields[field.location, b, a], PieceTeam.Ally);
}
else
{
if (fields[field.location, b, a].CurrentPiece?.color != color)
targetFields.Add(fields[field.location, b, a], PieceTeam.Enemy);
}
}
}
}
return targetFields;
}
} // FINALIZED
}

80
ChessPanel/Pieces/Pawn.cs Normal file
View File

@ -0,0 +1,80 @@
using Chess;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows;
namespace ChessPanel
{
public class Pawn : Piece
{
public Pawn(PieceColor color, Vector position, Grid fields) : base(position, fields)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override bool EndageresFieldWithVirtualMove(Grid fields, Field field, Piece movePiece, Field targetPos) // Pawn does not care about virtually moved pieces, if field is in range it can attack
{
int direction = this.color == PieceColor.White ? -1 : 1;
#region Attack
for (int x = -1; x < 2; x += 2)
{
if (field.location.Y + (direction) > 7 || field.location.Y + (direction) < 0 || field.location.X + x > 7 || field.location.X + x < 0)
continue;
if (fields[field.location, x, direction] == field)
return true;
}
#endregion
return false;
}
internal override Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color)
{
MoveMode mode = MoveMode.Normal;
Dictionary<Field, PieceTeam> targetFields = new Dictionary<Field, PieceTeam>();
int direction = this.color == PieceColor.White ? -1 : 1;
#region Movement
if (mode == MoveMode.Normal || mode == MoveMode.Movement)
for (int y = 1; y < 1 + (HasMoved ? 1 : 2); y++)
{
if (field.location.Y + (direction * y) > 7 || field.location.Y + (direction * y) < 0)
break;
if (fields[field.location, 0, (direction * y)].IsEmpty)
targetFields.Add(fields[field.location, 0, (direction * y)], PieceTeam.Ally);
else
break;
}
#endregion
#region Attack
if (mode == MoveMode.Normal || mode == MoveMode.Attack)
{
#region EnPassant
if (field.location.Y == (this.color == PieceColor.White ? 3 : 4))
for (int x = -1; x < 2; x += 2)
if (field.location.X + x <= 7 && field.location.X + x >= 0)
if (fields[field.location, x, 0].CurrentPiece != null
&& fields[field.location, x, 0].CurrentPiece.type == PieceType.Pawn
&& fields[field.location, x, 0].CurrentPiece.color != this.color
&& fields[field.location, x, 0].CurrentPiece.EnPassantPossible)
targetFields.Add(fields[field.location, x, direction], PieceTeam.Enemy);
#endregion
for (int x = -1; x < 2; x += 2)
{
if (field.location.Y + (direction) > 7 || field.location.Y + (direction) < 0 || field.location.X + x > 7 || field.location.X + x < 0)
continue;
if (fields[field.location, x, direction].CurrentPiece != null && fields[field.location, x, direction].CurrentPiece.color != this.color)
{
targetFields.Add(fields[field.location, x, direction], PieceTeam.Enemy);
}
}
#endregion
}
return targetFields;
}
}
}

View File

@ -0,0 +1,35 @@
using Chess;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows;
namespace ChessPanel
{
public class Queen : Piece
{
public Queen(PieceColor color, Vector position, Grid fields) : base(position, fields)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override bool EndageresFieldWithVirtualMove(Grid fields, Field possibleEndageredField, Piece movePiece, Field targetPos)
{
return Rook.StaticEndageresFieldWithVirtualMove(fields, this.field, possibleEndageredField, movePiece, targetPos, color)
|| Bishop.StaticEndageresFieldWithVirtualMove(fields, this.field, possibleEndageredField, movePiece, targetPos, color);
}
internal override Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color)
{
Dictionary<Field, PieceTeam> targetFields = Rook.StaticGetTargetFields(fields, field, this.color); // Take Rook fields
targetFields = targetFields.Concat(Bishop.StaticGetTargetFields(fields, field, this.color) // Add Bishop; Rook + Bishop = Queen
.Where(kvp => !targetFields.ContainsKey(kvp.Key)))
.OrderBy(c => c.Value)
.ToDictionary(c => c.Key, c => c.Value);
return targetFields;
}
} // FINALIZED
}

141
ChessPanel/Pieces/Rook.cs Normal file
View File

@ -0,0 +1,141 @@
using Chess;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows;
namespace ChessPanel
{
public class Rook : Piece
{
public Rook(PieceColor color, Vector position, Grid fields) : base(position, fields)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
//internal override Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Any, bool dontTestKingDanger = false)
//{
// var targetFields = GetTargetFields(fields, field, this.color);
// if (!dontTestKingDanger)
// {
// Field kinglocation = fields.GetKing(this.color).field;
// foreach (var item in targetFields)
// if (fields.IsFieldVirtuallyEndagered(kinglocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, item.Key))
// targetFields.Remove(item.Key);
// }
// return targetFields;
//}
internal override Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color)
{
return StaticGetTargetFields(fields, field, color);
}
internal static Dictionary<Field, PieceTeam> StaticGetTargetFields(Grid fields, Field field, PieceColor color)
{
Dictionary<Field, PieceTeam> targetFields = new Dictionary<Field, PieceTeam>();
for (int x = (int)field.location.X - 1; x >= 0; x--) // nach Links
{
if (fields[x, field.location.Y].IsEmpty)
{
targetFields.Add(fields[x, field.location.Y], PieceTeam.Ally);
}
else
{
if (fields[x, (int)field.location.Y].currentPiece.color != color)
targetFields.Add(fields[x, field.location.Y], PieceTeam.Enemy);
break;
}
}
for (int x = (int)field.location.X + 1; x <= 7; x++) // nach Rechts
{
if (fields[x, (int)field.location.Y].IsEmpty)
{
targetFields.Add(fields[x, field.location.Y], PieceTeam.Ally);
}
else
{
if (fields[x, (int)field.location.Y].currentPiece.color != color)
targetFields.Add(fields[x, field.location.Y], PieceTeam.Enemy);
break;
}
}
for (int y = (int)field.location.Y - 1; y >= 0; y--) // nach Unten
{
if (fields[(int)field.location.X, y].IsEmpty)
{
targetFields.Add(fields[field.location.X, y], PieceTeam.Ally);
}
else
{
if (fields[(int)field.location.X, y].currentPiece.color != color)
targetFields.Add(fields[field.location.X, y], PieceTeam.Enemy);
break;
}
}
for (int y = (int)field.location.Y + 1; y <= 7; y++) // nach Oben
{
if (fields[(int)field.location.X, y].IsEmpty)
{
targetFields.Add(fields[field.location.X, y], PieceTeam.Ally);
}
else
{
if (fields[(int)field.location.X, y].currentPiece.color != color)
targetFields.Add(fields[field.location.X, y], PieceTeam.Enemy);
break;
}
}
return targetFields;
}
internal override bool EndageresFieldWithVirtualMove(Grid fields, Field possibleEndageredField, Piece movePiece, Field targetPos)
{
return StaticEndageresFieldWithVirtualMove(fields, this.field, possibleEndageredField, movePiece, targetPos, color);
}
internal static bool StaticEndageresFieldWithVirtualMove(Grid fields, Field thisField, Field possibleEndageredField, Piece movePiece, Field targetPos, PieceColor color)
{
if (possibleEndageredField.location.X != thisField.location.X && possibleEndageredField.location.Y != thisField.location.Y) // Field can not be reached horizontally nor vertically
return false;
for (int x = (int)thisField.location.X - 1; x >= 0; x--) // nach Links
{
var possibleTargetField = fields[x, thisField.location.Y];
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
for (int x = (int)thisField.location.X + 1; x <= 7; x++) // nach Rechts
{
var possibleTargetField = fields[x, thisField.location.Y];
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
for (int y = (int)thisField.location.Y - 1; y >= 0; y--) // nach Oben
{
var possibleTargetField = fields[thisField.location.X, y];
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
for (int y = (int)thisField.location.Y + 1; y <= 7; y++) // nach Unten
{
var possibleTargetField = fields[thisField.location.X, y];
if (CheckFieldCanBeReached(possibleEndageredField, targetPos, movePiece, possibleTargetField, color, out bool breakIt))
return true;
if (breakIt)
break;
}
return false;
}
} // FINALIZED
}