Changed nearly everything, minor fixes and renames

Signed-off-by: Pablu23 <43807157+Pablu23@users.noreply.github.com>
This commit is contained in:
Pablu23
2021-11-27 11:57:23 +01:00
parent e5db65d5ca
commit 4c4278edd1
7 changed files with 243 additions and 46 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -86,7 +86,7 @@
</ShowAsCollectionAssociation> </ShowAsCollectionAssociation>
</Class> </Class>
<Class Name="TicTacToe.Program" Collapsed="true"> <Class Name="TicTacToe.Program" Collapsed="true">
<Position X="19.75" Y="7.5" Width="1.5" /> <Position X="19.25" Y="6.25" Width="1.5" />
<TypeIdentifier> <TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode> <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
<FileName>Program.cs</FileName> <FileName>Program.cs</FileName>
@@ -105,12 +105,9 @@
<Class Name="TicTacToe.TicTacToeBoard"> <Class Name="TicTacToe.TicTacToeBoard">
<Position X="10.25" Y="4" Width="1.5" /> <Position X="10.25" Y="4" Width="1.5" />
<TypeIdentifier> <TypeIdentifier>
<HashCode>AAAAAEAAAABIAAAAAECAEEIAAAAAAAAQAQAAAAARAAA=</HashCode> <HashCode>AAAAAEAAAABAAAAAAEAAAEIAAAAAAAAQAQAAAAARgAA=</HashCode>
<FileName>TicTacToeBoard.cs</FileName> <FileName>TicTacToeBoard.cs</FileName>
</TypeIdentifier> </TypeIdentifier>
<ShowAsAssociation>
<Field Name="_fields" />
</ShowAsAssociation>
</Class> </Class>
<Enum Name="TicTacToe.FieldState"> <Enum Name="TicTacToe.FieldState">
<Position X="15" Y="4.75" Width="1.5" /> <Position X="15" Y="4.75" Width="1.5" />

File diff suppressed because one or more lines are too long

View File

@@ -44,7 +44,7 @@ namespace TicTacToe.Players
//TODO: Save Board history somehow //TODO: Save Board history somehow
public class LearningAiPlayer : Player public class LearningAiPlayer : Player
{ {
private string _pathToLearningDir = @"E:\Programieren\csharp\TicTacToe\TicTacToe\Players\LearningAiDir\ai.json"; private string _pathToLearningDir = @"C:\Users\zam.k\source\repos\TicTacToe\TicTacToe\Players\LearningAiDir\ai.json";
private int _round; private int _round;
private AiBrain _brain; private AiBrain _brain;
private Random _random; private Random _random;
@@ -104,14 +104,14 @@ namespace TicTacToe.Players
return move; return move;
} }
if (_brain is not null) if (_brain != null)
{ {
var allPlayedRounds = _brain.AllOutcomes.FindAll(x => var allPlayedRounds = _brain.AllOutcomes.FindAll(x =>
Equals(x.GetBoardAtTime(_round), copyOfBoard)); Equals(x.GetBoardAtTime(_round), copyOfBoard));
if (_round == 0) if (_round == 0)
{ {
var bestOption = _brain.AllOutcomes.Aggregate((i, j) => i.Weight > j.Weight ? i : j); var bestOption = _brain.AllOutcomes.Aggregate((i, j) => i.Weight > j.Weight ? i : j);
if (bestOption is not null) if (bestOption != null)
{ {
move = bestOption.GetNextMove(_round); move = bestOption.GetNextMove(_round);
} }
@@ -119,7 +119,7 @@ namespace TicTacToe.Players
if (allPlayedRounds.Count != 0) if (allPlayedRounds.Count != 0)
{ {
var bestOption = allPlayedRounds.Aggregate((i, j) => i.Weight > j.Weight ? i : j); var bestOption = allPlayedRounds.Aggregate((i, j) => i.Weight > j.Weight ? i : j);
if (bestOption is not null) if (bestOption != null)
{ {
move = bestOption.GetNextMove(_round); move = bestOption.GetNextMove(_round);
} }

View File

@@ -5,24 +5,183 @@ namespace TicTacToe
{ {
class Program class Program
{ {
static void Main(string[] args) public static void Main(string[] args)
{ {
TicTacToe ticTacToe = new TicTacToe(); MainMenu();
Player player1 = new LearningAiPlayer("Learning", FieldState.PlayerX);
Player player2 = new AdvancedAiPlayer("MinMax", FieldState.PlayerO);
Player player3 = new BasicAiPlayer("Basic", FieldState.PlayerO);
Player player4 = new HumanPlayer("Human", FieldState.PlayerO);
ticTacToe.AddPlayer(player1);
ticTacToe.AddPlayer(player4);
//TODO: Menu
//TODO: Learning Players properties, dont reset, after more than one round = crash
ticTacToe.StartGame();
ticTacToe.DrawScore();
Console.ReadKey(true); Console.ReadKey(true);
} }
private static void MainMenu()
{
TicTacToe ticTacToe = new TicTacToe();
while (true)
{
Console.Clear();
Console.WriteLine("Welcome to TicTacToe");
Console.WriteLine("[C]onfig Players");
//Console.WriteLine("[N]ew Game");
Console.WriteLine("[S]tart Game");
Console.WriteLine("[E]nd");
char input = GetCharInput(new[] { 'c', 's', 'e', 'n' });
switch (input)
{
case 'c':
ConfigPlayers(ticTacToe);
break;
case 's':
if(ticTacToe.GetPlayerCount() < 2)
{
Console.WriteLine("There are not enough Players to start the game");
break;
}
ticTacToe.StartGame();
ticTacToe.DrawScore();
break;
case 'e':
Environment.Exit(0);
break;
case 'n':
ticTacToe = new TicTacToe();
break;
}
Console.WriteLine("To continue press any Key...");
Console.ReadKey(true);
}
}
private static void ConfigPlayers(TicTacToe ticTacToe)
{
//Show Players if any exist
Console.Clear();
if(ticTacToe.GetPlayerCount() == 0)
{
Player p1 = CreatePlayer();
Player p2 = CreatePlayer(p1.Symbol);
ticTacToe.AddPlayer(p1);
ticTacToe.AddPlayer(p2);
}
else
{
Console.WriteLine("Which Player to edit");
ticTacToe.ShowPlayers();
Console.WriteLine("[E]xit");
bool correctInput = false;
int playerToEdit = 0;
while (!correctInput)
{
string input = Console.ReadLine();
if (input?.ToLower() == "e") return;
correctInput = int.TryParse(input, out playerToEdit);
playerToEdit -= 1;
if (correctInput) correctInput = playerToEdit <= ticTacToe.GetPlayerCount();
}
ticTacToe.ReplacePlayer(playerToEdit, CreatePlayer(ticTacToe.GetOpponentSymbol(playerToEdit == 0 ? 1 : 0)));
}
}
private static Player CreatePlayer(FieldState otherPlayer = FieldState.Empty)
{
Console.Clear();
Console.WriteLine("Create new Player\n----------------");
Console.WriteLine("Name of the Player:");
string name = Console.ReadLine();
FieldState sym = FieldState.Empty;
if (otherPlayer == FieldState.Empty)
{
Console.WriteLine("Symbole of the Player");
string symbol = Console.ReadLine();
switch (symbol?.ToUpper())
{
case "X":
sym = FieldState.PlayerX;
break;
case "O":
sym = FieldState.PlayerO;
break;
default:
throw new Exception("Symbol was not recognised");
}
}
else
{
switch (otherPlayer)
{
case FieldState.PlayerO:
sym = FieldState.PlayerX;
break;
case FieldState.PlayerX:
sym = FieldState.PlayerO;
break;
}
}
Console.WriteLine("Type of Player");
Console.WriteLine("[1] Human");
Console.WriteLine("[2] Basic (Random)");
Console.WriteLine("[3] Advanced (Unbeatable)");
Console.WriteLine("[4] Learning (Stupid)");
int ki = int.Parse(Console.ReadLine());
Player player;
switch (ki)
{
case 1:
player = new HumanPlayer(name, sym);
break;
case 2:
player = new BasicAiPlayer(name, sym);
break;
case 3:
player = new AdvancedAiPlayer(name, sym);
break;
case 4:
player = new LearningAiPlayer(name, sym);
break;
default:
throw new Exception("The given Number was wrong");
}
return player;
}
private static char GetCharInput(char[] acceptedChars, string message = null)
{
if (message != null)
Console.WriteLine(message);
char result;
bool loop = true;
do
{
// This is because the highest number is 9 so we always only need one Key to play
var key = Console.ReadKey(true);
result = key.KeyChar;
foreach (var item in acceptedChars)
{
if (result == item)
loop = false;
}
} while (loop);
return result;
}
} }
} }

View File

@@ -10,6 +10,19 @@ namespace TicTacToe
private bool _gameFinished; private bool _gameFinished;
private void RemovePlayer(Player player)
{
if (Players.Count <= 0) throw new Exception("No Players found cant remove Player");
Players.Remove(player);
Scores.Remove(player);
}
public void ReplacePlayer(int oldPlayerIndex, Player newPlayer)
{
RemovePlayer(Players[oldPlayerIndex]);
AddPlayer(newPlayer);
}
public override void AddPlayer(Player player) public override void AddPlayer(Player player)
{ {
if (Players.Count >= 2) throw new Exception("Trying to add too many Players"); if (Players.Count >= 2) throw new Exception("Trying to add too many Players");
@@ -17,6 +30,24 @@ namespace TicTacToe
Scores.Add(player, 0); Scores.Add(player, 0);
} }
public int GetPlayerCount()
{
return Players.Count();
}
public FieldState GetOpponentSymbol(int playerIndex)
{
return Players[playerIndex].Symbol;
}
public void ShowPlayers()
{
for (int i = 0; i < Players.Count; i++)
{
Console.WriteLine($"[{i+1}] Name: {Players[i].Name} | Symbol: {Players[i].Symbol} | Type: {Players[i].GetType().ToString().Substring(18)}");
}
}
public override void AddScore(Player player) public override void AddScore(Player player)
{ {
if (Players.Contains(player)) if (Players.Contains(player))
@@ -49,14 +80,14 @@ namespace TicTacToe
// Get the winner (Player? <- ? because the player could be null) // Get the winner (Player? <- ? because the player could be null)
var winner = Players.FirstOrDefault(x => x.Symbol == winnerState); var winner = Players.FirstOrDefault(x => x.Symbol == winnerState);
if (winner is not null) if (winner != null)
{ {
AddScore(winner); AddScore(winner);
//If one of the Players was a LearningAiPlayer add the Match to the Ai Brain //If one of the Players was a LearningAiPlayer add the Match to the Ai Brain
var player = Players.FirstOrDefault(x => x.GetType() == typeof(LearningAiPlayer)); var player = Players.FirstOrDefault(x => x.GetType() == typeof(LearningAiPlayer));
var learningAiPlayer = player as LearningAiPlayer; var learningAiPlayer = player as LearningAiPlayer;
if (learningAiPlayer is not null) if (learningAiPlayer != null)
learningAiPlayer.SaveToJson(_board); learningAiPlayer.SaveToJson(_board);
} }
CleanUp(); CleanUp();
@@ -72,7 +103,7 @@ namespace TicTacToe
_gameFinished = false; _gameFinished = false;
int round = 0; int round = 0;
while (_gameFinished is not true) while (_gameFinished != true)
{ {
// For both Players // For both Players
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)

View File

@@ -12,23 +12,33 @@ namespace TicTacToe
for (int i = 0; i < Fields.Length; i++) for (int i = 0; i < Fields.Length; i++)
{ {
//Initialise all Fields and give them the Symbol on which Position they are //Initialise all Fields and give them the Symbol on which Position they are
Fields[i] = new Field(Convert.ToChar((i+1).ToString())); Fields[i] = new Field(Convert.ToChar((i + 1).ToString()));
} }
} }
public void DrawBoard() public void DrawBoard()
{ {
Console.Clear(); Console.Clear();
Console.WriteLine(
$"{Fields[0].Symbol} | " + for (int i = 0; i < 9; i++)
$"{Fields[1].Symbol} | " + {
$"{Fields[2].Symbol}\n--------\n" + if (Fields[i].State == FieldState.PlayerO)
$"{Fields[3].Symbol} | " + Console.ForegroundColor = ConsoleColor.Green;
$"{Fields[4].Symbol} | " + if (Fields[i].State == FieldState.PlayerX)
$"{Fields[5].Symbol}\n--------\n" + Console.ForegroundColor = ConsoleColor.Red;
$"{Fields[6].Symbol} | " + if (Fields[i].State == FieldState.Empty)
$"{Fields[7].Symbol} | " + Console.ForegroundColor = ConsoleColor.Gray;
$"{Fields[8].Symbol}");
Console.Write(Fields[i].Symbol);
Console.ForegroundColor = ConsoleColor.Gray;
if ((i + 1) % 3 == 0 && i != 8)
Console.Write("\n--------\n");
else if (i == 8)
Console.WriteLine();
else
Console.Write(" | ");
}
} }
//Tries to mark a position, if the position is not free it returns a false //Tries to mark a position, if the position is not free it returns a false