Changed nearly everything, minor fixes and renames
Signed-off-by: Pablu23 <43807157+Pablu23@users.noreply.github.com>
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 89 KiB |
@@ -86,7 +86,7 @@
|
||||
</ShowAsCollectionAssociation>
|
||||
</Class>
|
||||
<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>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
|
||||
<FileName>Program.cs</FileName>
|
||||
@@ -105,12 +105,9 @@
|
||||
<Class Name="TicTacToe.TicTacToeBoard">
|
||||
<Position X="10.25" Y="4" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAEAAAABIAAAAAECAEEIAAAAAAAAQAQAAAAARAAA=</HashCode>
|
||||
<HashCode>AAAAAEAAAABAAAAAAEAAAEIAAAAAAAAQAQAAAAARgAA=</HashCode>
|
||||
<FileName>TicTacToeBoard.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<ShowAsAssociation>
|
||||
<Field Name="_fields" />
|
||||
</ShowAsAssociation>
|
||||
</Class>
|
||||
<Enum Name="TicTacToe.FieldState">
|
||||
<Position X="15" Y="4.75" Width="1.5" />
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -44,7 +44,7 @@ namespace TicTacToe.Players
|
||||
//TODO: Save Board history somehow
|
||||
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 AiBrain _brain;
|
||||
private Random _random;
|
||||
@@ -104,14 +104,14 @@ namespace TicTacToe.Players
|
||||
return move;
|
||||
}
|
||||
|
||||
if (_brain is not null)
|
||||
if (_brain != null)
|
||||
{
|
||||
var allPlayedRounds = _brain.AllOutcomes.FindAll(x =>
|
||||
Equals(x.GetBoardAtTime(_round), copyOfBoard));
|
||||
if (_round == 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -119,7 +119,7 @@ namespace TicTacToe.Players
|
||||
if (allPlayedRounds.Count != 0)
|
||||
{
|
||||
var bestOption = allPlayedRounds.Aggregate((i, j) => i.Weight > j.Weight ? i : j);
|
||||
if (bestOption is not null)
|
||||
if (bestOption != null)
|
||||
{
|
||||
move = bestOption.GetNextMove(_round);
|
||||
}
|
||||
|
||||
@@ -5,24 +5,183 @@ namespace TicTacToe
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
MainMenu();
|
||||
Console.ReadKey(true);
|
||||
}
|
||||
|
||||
private static void MainMenu()
|
||||
{
|
||||
TicTacToe ticTacToe = new TicTacToe();
|
||||
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);
|
||||
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");
|
||||
|
||||
//TODO: Menu
|
||||
//TODO: Learning Players properties, dont reset, after more than one round = crash
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,19 @@ namespace TicTacToe
|
||||
|
||||
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)
|
||||
{
|
||||
if (Players.Count >= 2) throw new Exception("Trying to add too many Players");
|
||||
@@ -17,6 +30,24 @@ namespace TicTacToe
|
||||
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)
|
||||
{
|
||||
if (Players.Contains(player))
|
||||
@@ -49,14 +80,14 @@ namespace TicTacToe
|
||||
|
||||
// Get the winner (Player? <- ? because the player could be null)
|
||||
var winner = Players.FirstOrDefault(x => x.Symbol == winnerState);
|
||||
if (winner is not null)
|
||||
if (winner != null)
|
||||
{
|
||||
AddScore(winner);
|
||||
|
||||
//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 learningAiPlayer = player as LearningAiPlayer;
|
||||
if (learningAiPlayer is not null)
|
||||
if (learningAiPlayer != null)
|
||||
learningAiPlayer.SaveToJson(_board);
|
||||
}
|
||||
CleanUp();
|
||||
@@ -72,7 +103,7 @@ namespace TicTacToe
|
||||
_gameFinished = false;
|
||||
int round = 0;
|
||||
|
||||
while (_gameFinished is not true)
|
||||
while (_gameFinished != true)
|
||||
{
|
||||
// For both Players
|
||||
for (int i = 0; i < 2; i++)
|
||||
|
||||
@@ -19,16 +19,26 @@ namespace TicTacToe
|
||||
public void DrawBoard()
|
||||
{
|
||||
Console.Clear();
|
||||
Console.WriteLine(
|
||||
$"{Fields[0].Symbol} | " +
|
||||
$"{Fields[1].Symbol} | " +
|
||||
$"{Fields[2].Symbol}\n--------\n" +
|
||||
$"{Fields[3].Symbol} | " +
|
||||
$"{Fields[4].Symbol} | " +
|
||||
$"{Fields[5].Symbol}\n--------\n" +
|
||||
$"{Fields[6].Symbol} | " +
|
||||
$"{Fields[7].Symbol} | " +
|
||||
$"{Fields[8].Symbol}");
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
if (Fields[i].State == FieldState.PlayerO)
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
if (Fields[i].State == FieldState.PlayerX)
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
if (Fields[i].State == FieldState.Empty)
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user