Added proprietary user interface.
Added most game logic.
This commit is contained in:
parent
71c1a4d20c
commit
27f6efb58a
@ -62,8 +62,6 @@
|
|||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<Compile Include="Properties\Grid.cs" />
|
|
||||||
<Compile Include="Properties\Player.cs" />
|
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
@ -81,5 +79,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TicTacToe\TicTacToe.csproj">
|
||||||
|
<Project>{8EB373A9-D083-4BFE-9396-E9A40E75AAC2}</Project>
|
||||||
|
<Name>TicTacToe</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
26
CleanTicTacToe/MainForm.Designer.cs
generated
26
CleanTicTacToe/MainForm.Designer.cs
generated
@ -23,20 +23,46 @@
|
|||||||
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
|
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
|
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||||
|
this.TslStatus = new System.Windows.Forms.ToolStripStatusLabel();
|
||||||
|
this.statusStrip1.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
|
// statusStrip1
|
||||||
|
//
|
||||||
|
this.statusStrip1.ImageScalingSize = new System.Drawing.Size(32, 32);
|
||||||
|
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
|
this.TslStatus});
|
||||||
|
this.statusStrip1.Location = new System.Drawing.Point(0, 853);
|
||||||
|
this.statusStrip1.Name = "statusStrip1";
|
||||||
|
this.statusStrip1.Size = new System.Drawing.Size(1010, 38);
|
||||||
|
this.statusStrip1.TabIndex = 0;
|
||||||
|
this.statusStrip1.Text = "statusStrip1";
|
||||||
|
//
|
||||||
|
// TslStatus
|
||||||
|
//
|
||||||
|
this.TslStatus.Name = "TslStatus";
|
||||||
|
this.TslStatus.Size = new System.Drawing.Size(0, 28);
|
||||||
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(1010, 891);
|
this.ClientSize = new System.Drawing.Size(1010, 891);
|
||||||
|
this.Controls.Add(this.statusStrip1);
|
||||||
this.Name = "MainForm";
|
this.Name = "MainForm";
|
||||||
this.Text = "Form1";
|
this.Text = "Form1";
|
||||||
|
this.statusStrip1.ResumeLayout(false);
|
||||||
|
this.statusStrip1.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||||
|
private System.Windows.Forms.ToolStripStatusLabel TslStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,59 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TicTacToe;
|
using TicTacToe;
|
||||||
|
|
||||||
namespace CleanTicTacToe {
|
namespace CleanTicTacToe {
|
||||||
public partial class MainForm : Form {
|
public partial class MainForm : Form {
|
||||||
|
private const int BUTTONSIZE = 100;
|
||||||
private readonly Grid _grid;
|
private readonly Grid _grid;
|
||||||
|
private readonly Button[,] _pbxs = new Button[Grid.GRIDSIZE, Grid.GRIDSIZE];
|
||||||
public MainForm() {
|
public MainForm() {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_grid = new Grid();
|
_grid = new Grid();
|
||||||
|
_grid.ExpectNextTurn += Grid_ExpectNextTurn;
|
||||||
|
_grid.GameOver += Grid_GameOver;
|
||||||
|
for (var x = 0; x < Grid.GRIDSIZE; x++)
|
||||||
|
for (var y = 0; y < Grid.GRIDSIZE; y++) {
|
||||||
|
var pictureBox = new Button() {
|
||||||
|
Location = new Point(x * BUTTONSIZE, y * BUTTONSIZE),
|
||||||
|
Width = BUTTONSIZE,
|
||||||
|
Height = BUTTONSIZE,
|
||||||
|
Tag = (x, y)
|
||||||
|
};
|
||||||
|
pictureBox.Click += Grid_Click;
|
||||||
|
Controls.Add(pictureBox);
|
||||||
|
_pbxs[x, y] = pictureBox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Grid_GameOver(object sender, Player e) {
|
||||||
|
TslStatus.Text = $"Player {e} has won!";
|
||||||
|
_grid.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Grid_ExpectNextTurn(object sender, Player e) {
|
||||||
|
TslStatus.Text = $"Player {e} must now pick a spot!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Grid_Click(object sender, EventArgs e) {
|
||||||
|
if (!(sender is Button pictureBox))
|
||||||
|
throw new InvalidProgramException("Expected picturebox as sender!");
|
||||||
|
(var x, var y) = ((int x, int y))pictureBox.Tag;
|
||||||
|
TslStatus.Text = $"Spot {x},{y} clicked!";
|
||||||
|
try {
|
||||||
|
_grid.PickSpot(x, y);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
TslStatus.Text = ex.Message;
|
||||||
|
}
|
||||||
|
RefreshPbxs();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshPbxs() {
|
||||||
|
for (var x = 0; x < Grid.GRIDSIZE; x++)
|
||||||
|
for (var y = 0; y < Grid.GRIDSIZE; y++) {
|
||||||
|
_pbxs[x, y].Text = $"{Grid.GetPlayerChar(_grid[x, y])}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,4 +117,7 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
</root>
|
</root>
|
@ -1,26 +0,0 @@
|
|||||||
namespace TicTacToe {
|
|
||||||
public class Grid {
|
|
||||||
private readonly Player[,] _field;
|
|
||||||
private const int GRIDSIZE = 3;
|
|
||||||
public bool GameOver => IsGameOver();
|
|
||||||
|
|
||||||
private bool IsGameOver() {
|
|
||||||
for (var x = 0; x < GRIDSIZE; x++)
|
|
||||||
for (var y = 0; y < GRIDSIZE; y++)
|
|
||||||
if (IsFieldEmpty(x, y))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsFieldEmpty(int x, int y) {
|
|
||||||
return _field[x, y] == Player.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Grid() {
|
|
||||||
_field = new Player[GRIDSIZE, GRIDSIZE];
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool PickSpot() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace TicTacToe {
|
|
||||||
enum Player {
|
|
||||||
Empty = 0,
|
|
||||||
Cross = 1,
|
|
||||||
Circle = 2
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +1,299 @@
|
|||||||
namespace TicTacToe {
|
using System;
|
||||||
public class Grid {
|
using System.Text;
|
||||||
private readonly Player[,] _field;
|
|
||||||
private const int GRIDSIZE = 3;
|
|
||||||
public bool GameOver => IsGameOver();
|
|
||||||
|
|
||||||
private bool IsGameOver() {
|
namespace TicTacToe {
|
||||||
for (var x = 0; x < GRIDSIZE; x++)
|
public class Grid {
|
||||||
for (var y = 0; y < GRIDSIZE; y++)
|
public const int GRIDSIZE = 3;
|
||||||
if (IsFieldEmpty(x, y))
|
private const Player GameBeginner = Player.Cross;
|
||||||
|
private Player NextGameBeginner = GameBeginner;
|
||||||
|
private readonly Player[,] _field = new Player[GRIDSIZE, GRIDSIZE];
|
||||||
|
private Player? winner;
|
||||||
|
private ((int x, int y) p1, (int x, int y) p2)? winningLine;
|
||||||
|
public event EventHandler<Player> ExpectNextTurn;
|
||||||
|
public event EventHandler<Player> GameOver;
|
||||||
|
public Player this[int x, int y] { get => _field[x, y]; }
|
||||||
|
public bool IsGameOver { get; private set; } = false;
|
||||||
|
public Player ActivePlayer { get; private set; } = GameBeginner;
|
||||||
|
public Player Winner { get => winner.Value; private set => winner = value; }
|
||||||
|
public ((int x, int y) p1, (int x, int y) p2) WinningLine { get => winningLine.Value; private set => winningLine = value; }
|
||||||
|
public Grid() {
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a given field is empty.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">Column index</param>
|
||||||
|
/// <param name="y">Row index</param>
|
||||||
|
/// <returns>True if the field is empty</returns>
|
||||||
|
public bool IsEmpty(int x, int y) => _field[x, y] == Player.Empty;
|
||||||
|
|
||||||
|
public void Reset() {
|
||||||
|
ActivePlayer = NextGameBeginner;
|
||||||
|
NextGameBeginner = EnemyOf(NextGameBeginner);
|
||||||
|
IsGameOver = false;
|
||||||
|
winner = null;
|
||||||
|
winningLine = null;
|
||||||
|
for (var y = 0; y < GRIDSIZE; y++)
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++)
|
||||||
|
_field[x, y] = Player.Empty;
|
||||||
|
ExpectNextTurn?.Invoke(this, ActivePlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a given field is not empty.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">Column index</param>
|
||||||
|
/// <param name="y">Row index</param>
|
||||||
|
/// <returns>True if the field is set</returns>
|
||||||
|
public bool IsSet(int x, int y) => _field[x, y] != Player.Empty;
|
||||||
|
|
||||||
|
public void PickSpot(int x, int y) {
|
||||||
|
if (IsGameOver)
|
||||||
|
throw new InvalidOperationException("Cannot pick spot on finished game!");
|
||||||
|
if (!IsEmpty(x, y))
|
||||||
|
throw new InvalidOperationException("Cannot pick already picked spot!");
|
||||||
|
_field[x, y] = ActivePlayer;
|
||||||
|
TurnOver();
|
||||||
|
if (!IsGameOver)
|
||||||
|
ExpectNextTurn?.Invoke(this, ActivePlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the game is over and updates the properties.
|
||||||
|
/// </summary>
|
||||||
|
/// <see cref="IsGameOver"/>
|
||||||
|
/// <see cref="Winner"/>
|
||||||
|
private void TurnOver() {
|
||||||
|
if (CheckRows() ||
|
||||||
|
CheckColumns() ||
|
||||||
|
CheckDiagonalPrimary() ||
|
||||||
|
CheckDiagonalSecondary() ||
|
||||||
|
CheckDraw()) { // Important to check after all other cases as there might be a full field with a winner
|
||||||
|
IsGameOver = true;
|
||||||
|
GameOver?.Invoke(this, Winner);
|
||||||
|
} else {
|
||||||
|
IsGameOver = false;
|
||||||
|
ActivePlayer = EnemyOf(ActivePlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Player EnemyOf(Player player) {
|
||||||
|
switch (player) {
|
||||||
|
case Player.Cross:
|
||||||
|
return Player.Circle;
|
||||||
|
case Player.Circle:
|
||||||
|
return Player.Cross;
|
||||||
|
default:
|
||||||
|
throw new Exception("Unexpected enumerable state!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region GameOverTests
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a field is full and there is no winner
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool CheckDraw() {
|
||||||
|
for (var y = 0; y < GRIDSIZE; y++) {
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
if (IsEmpty(x, y))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Winner = Player.Empty;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
private bool IsFieldEmpty(int x, int y) {
|
/// Checks primary diagonal on a win.
|
||||||
return _field[x, y] == Player.Empty;
|
/// </summary>
|
||||||
|
/// <returns>True if a win was found</returns>
|
||||||
|
private bool CheckDiagonalPrimary() {
|
||||||
|
var circlecount = 0;
|
||||||
|
var crosscount = 0;
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
switch (_field[x, x]) {
|
||||||
|
case Player.Circle:
|
||||||
|
circlecount++;
|
||||||
|
break;
|
||||||
|
case Player.Cross:
|
||||||
|
crosscount++;
|
||||||
|
break;
|
||||||
|
case Player.Empty:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw new InvalidProgramException("Unexpected enumerable state!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crosscount == GRIDSIZE) {
|
||||||
|
Winner = Player.Cross;
|
||||||
|
WinningLine = ((0, 0), (GRIDSIZE, GRIDSIZE));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (circlecount == GRIDSIZE) {
|
||||||
|
Winner = Player.Circle;
|
||||||
|
WinningLine = ((0, 0), (GRIDSIZE, GRIDSIZE));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks secondary diagonal on a win.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if a win was found</returns>
|
||||||
|
private bool CheckDiagonalSecondary() {
|
||||||
|
var circlecount = 0;
|
||||||
|
var crosscount = 0;
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
switch (_field[x, GRIDSIZE - 1 - x]) {
|
||||||
|
case Player.Circle:
|
||||||
|
circlecount++;
|
||||||
|
break;
|
||||||
|
case Player.Cross:
|
||||||
|
crosscount++;
|
||||||
|
break;
|
||||||
|
case Player.Empty:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw new InvalidProgramException("Unexpected enumerable state!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crosscount == GRIDSIZE) {
|
||||||
|
Winner = Player.Cross;
|
||||||
|
WinningLine = ((0, GRIDSIZE), (GRIDSIZE, 0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (circlecount == GRIDSIZE) {
|
||||||
|
Winner = Player.Circle;
|
||||||
|
WinningLine = ((0, GRIDSIZE), (GRIDSIZE, 0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Grid() {
|
/// <summary>
|
||||||
_field = new Player[GRIDSIZE, GRIDSIZE];
|
/// Checks all columns on a win.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if a win was found</returns>
|
||||||
|
private bool CheckColumns() {
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
if (CheckColumn(in x)) {
|
||||||
|
WinningLine = ((x, 0), (x, GRIDSIZE));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PickSpot() {
|
/// <summary>
|
||||||
|
/// Checks a specific column on a win.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="y">Column index</param>
|
||||||
|
/// <returns>True if a win was found</returns>
|
||||||
|
private bool CheckColumn(in int y) {
|
||||||
|
var circlecount = 0;
|
||||||
|
var crosscount = 0;
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
switch (_field[y, x]) {
|
||||||
|
case Player.Circle:
|
||||||
|
circlecount++;
|
||||||
|
break;
|
||||||
|
case Player.Cross:
|
||||||
|
crosscount++;
|
||||||
|
break;
|
||||||
|
case Player.Empty:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw new InvalidProgramException("Unexpected enumerable state!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crosscount == GRIDSIZE) {
|
||||||
|
Winner = Player.Cross;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (circlecount == GRIDSIZE) {
|
||||||
|
Winner = Player.Circle;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks all rows on a win.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if a win was found</returns>
|
||||||
|
private bool CheckRows() {
|
||||||
|
for (var y = 0; y < GRIDSIZE; y++) {
|
||||||
|
if (CheckRow(in y)) {
|
||||||
|
WinningLine = ((0, y), (GRIDSIZE, y));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks a specific row on a win.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="y">Row index</param>
|
||||||
|
/// <returns>True if a win was found</returns>
|
||||||
|
private bool CheckRow(in int y) {
|
||||||
|
var circlecount = 0;
|
||||||
|
var crosscount = 0;
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
switch (_field[x, y]) {
|
||||||
|
case Player.Circle:
|
||||||
|
circlecount++;
|
||||||
|
break;
|
||||||
|
case Player.Cross:
|
||||||
|
crosscount++;
|
||||||
|
break;
|
||||||
|
case Player.Empty:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw new InvalidProgramException("Unexpected enumerable state!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crosscount == GRIDSIZE) {
|
||||||
|
Winner = Player.Cross;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (circlecount == GRIDSIZE) {
|
||||||
|
Winner = Player.Circle;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the grid data into a string. All rows are printed pipe ('|') separated and all row items are printed comma (',') separated.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string uniquely identifying the grid</returns>
|
||||||
|
public override string ToString() {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var y = 0; y < GRIDSIZE; y++) {
|
||||||
|
if (y > 0)
|
||||||
|
sb.Append("|");
|
||||||
|
for (var x = 0; x < GRIDSIZE; x++) {
|
||||||
|
if (x > 0)
|
||||||
|
sb.Append(",");
|
||||||
|
sb.Append(GetPlayerChar(_field[x, y]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static char GetPlayerChar(Player player) {
|
||||||
|
switch (player) {
|
||||||
|
case Player.Empty:
|
||||||
|
return ' ';
|
||||||
|
case Player.Cross:
|
||||||
|
return 'X';
|
||||||
|
case Player.Circle:
|
||||||
|
return 'O';
|
||||||
|
default:
|
||||||
|
throw new Exception("Unexpected enumerable state!");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
namespace TicTacToe {
|
namespace TicTacToe {
|
||||||
enum Player {
|
public enum Player {
|
||||||
Empty = 0,
|
Empty = 0,
|
||||||
Cross = 1,
|
Cross = 1,
|
||||||
Circle = 2
|
Circle = 2
|
||||||
|
Loading…
Reference in New Issue
Block a user