mirror of
https://github.com/TwoFX/Morris.git
synced 2026-02-04 04:52:52 +00:00
Add RandomBot, fix a bug in the game logic
This commit is contained in:
@@ -19,5 +19,15 @@ namespace Morris
|
|||||||
// der .Opponent verwendet, ist einfacher zu erkennen (Kapselung).
|
// der .Opponent verwendet, ist einfacher zu erkennen (Kapselung).
|
||||||
return ~p;
|
return ~p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Random rng = new Random();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gibt ein zufälliges Element der IList zurück
|
||||||
|
/// </summary>
|
||||||
|
public static T ChooseRandom<T>(this IList<T> it)
|
||||||
|
{
|
||||||
|
return it[rng.Next(it.Count)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,7 +244,11 @@ namespace Morris
|
|||||||
return MoveValidity.Invalid; // Darf keinen Stein mehr platzieren
|
return MoveValidity.Invalid; // Darf keinen Stein mehr platzieren
|
||||||
|
|
||||||
// 3.: Wurde eine Mühle geschlossen?
|
// 3.: Wurde eine Mühle geschlossen?
|
||||||
bool millClosed = Mills.Any(mill => mill.Contains(move.To) && mill.All(point => (int)Board[point] == (int)NextToMove || point == move.To));
|
bool millClosed = Mills.Any(mill => // Es muss eine potentielle Mühle geben, die
|
||||||
|
mill.Contains(move.To) && // den neu gesetzten Stein enthält und
|
||||||
|
mill.All(point => // bei der alle Punkte
|
||||||
|
(!move.From.HasValue || point != move.From) && // nicht der Ursprungspunkt der aktuellen Steinbewegung sind und
|
||||||
|
(int)Board[point] == (int)NextToMove || point == move.To)); // entweder schon vom Spieler bestzt sind oder Ziel der aktuellen Steinbewegung sind.
|
||||||
|
|
||||||
// 4.: Verifikation des Mühlenparameters
|
// 4.: Verifikation des Mühlenparameters
|
||||||
if (millClosed)
|
if (millClosed)
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
<Compile Include="Game.cs" />
|
<Compile Include="Game.cs" />
|
||||||
<Compile Include="GameResult.cs" />
|
<Compile Include="GameResult.cs" />
|
||||||
<Compile Include="GameState.cs" />
|
<Compile Include="GameState.cs" />
|
||||||
|
<Compile Include="RandomBot.cs" />
|
||||||
<None Include="LICENSE" />
|
<None Include="LICENSE" />
|
||||||
<Compile Include="IGameStateObserver.cs" />
|
<Compile Include="IGameStateObserver.cs" />
|
||||||
<Compile Include="IMoveProvider.cs" />
|
<Compile Include="IMoveProvider.cs" />
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ namespace Morris
|
|||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var a = new ConsoleInteraction();
|
var a = new ConsoleInteraction();
|
||||||
var g = new Game(a, a);
|
var b = new RandomBot();
|
||||||
|
var g = new Game(b, b);
|
||||||
g.AddObserver(a);
|
g.AddObserver(a);
|
||||||
g.Run();
|
g.Run();
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
|
|||||||
39
Morris/RandomBot.cs
Normal file
39
Morris/RandomBot.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* RandomBot.cs
|
||||||
|
* Copyright (c) 2016 Markus Himmel
|
||||||
|
* This fileis distributed under the terms of the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Morris
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ein extrem einfacher KI-Spieler, der einen zufälligen gültigen Spielzug auswählt
|
||||||
|
/// </summary>
|
||||||
|
class RandomBot : IMoveProvider
|
||||||
|
{
|
||||||
|
// Anhand dieser Klasse können wir sehen, wie einfach es ist, einen Computerspieler zu implementieren.
|
||||||
|
// Es muss lediglich eine einzige, einfache Methode implementiert werden. Der Spielzustandparameter stellt
|
||||||
|
// Methoden wie BasicMoves und IsValidMove bereit, mit denen viele verschiedene Strategien sehr einfach
|
||||||
|
// implementiert werden können.
|
||||||
|
|
||||||
|
private Random rng = new Random();
|
||||||
|
|
||||||
|
public GameMove GetNextMove(IReadOnlyGameState state)
|
||||||
|
{
|
||||||
|
// Ein zufälliger Spielzug
|
||||||
|
GameMove chosen = state.BasicMoves().ToList().ChooseRandom();
|
||||||
|
|
||||||
|
// Wenn wir einen Stein entfernen dürfen, wählen wir einen zufälligen Punkt aus, auf dem sich ein gegnerischer Stein befindet
|
||||||
|
if (state.IsValidMove(chosen) == MoveValidity.ClosesMill)
|
||||||
|
return chosen.WithRemove(Enumerable
|
||||||
|
.Range(0, GameState.FIELD_SIZE)
|
||||||
|
.Where(d => (int)state.Board[d] == (int)state.NextToMove.Opponent())
|
||||||
|
.ToList().ChooseRandom());
|
||||||
|
|
||||||
|
return chosen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user