@@ -8,174 +8,205 @@
using Cecs475 .BoardGames .ComputerOpponent ;
using System .Threading .Tasks ;
namespace Cecs475 .BoardGames .Othello .View {
public class OthelloSquare : INotifyPropertyChanged {
private int mPlayer ;
public int Player {
get { return mPlayer ; }
set {
if (value != mPlayer ) {
mPlayer = value ;
OnPropertyChanged (nameof (Player ));
}
}
}
private bool mIsHovered ;
public bool IsHovered {
get { return mIsHovered ; }
set {
if (value != mIsHovered ) {
mIsHovered = value ;
OnPropertyChanged (nameof (IsHovered ));
}
}
}
public BoardPosition Position {
get ; set ;
}
public event PropertyChangedEventHandler PropertyChanged ;
private void OnPropertyChanged (string name ) {
PropertyChanged ? .Invoke (this , new PropertyChangedEventArgs (name ));
}
}
public class OthelloViewModel : INotifyPropertyChanged , IGameViewModel {
private const int MAX_AI_DEPTH = 7 ;
private OthelloBoard mBoard ;
private ObservableCollection <OthelloSquare > mSquares ;
private IGameAi mGameAi = new MinimaxAi (MAX_AI_DEPTH );
public event PropertyChangedEventHandler PropertyChanged ;
public event EventHandler GameFinished ;
/// <summary >
/// Invoked after applying a move, if the new current player must pass their turn.
/// </summary >
public event EventHandler CurrentPlayerMustPass ;
private void OnPropertyChanged (string name ) {
PropertyChanged ? .Invoke (this , new PropertyChangedEventArgs (name ));
}
public OthelloViewModel () {
mBoard = new OthelloBoard ();
mSquares = new ObservableCollection <OthelloSquare >(
from pos in (
from r in Enumerable .Range (0 , 8 )
from c in Enumerable .Range (0 , 8 )
select new BoardPosition (r , c )
)
select new OthelloSquare () {
Position = pos ,
Player = mBoard .GetPieceAtPosition (pos )
}
);
PossibleMoves = new HashSet <BoardPosition >(
from OthelloMove m in mBoard .GetPossibleMoves ()
select m .Position
);
}
public void UndoMove () {
mBoard .UndoLastMove ();
// In one-player mode, Undo has to remove an additional move to return to the
// human player's turn.
if (Players == NumberOfPlayers .One ) {
mBoard .UndoLastMove ();
}
PossibleMoves = new HashSet <BoardPosition >(
from OthelloMove m in mBoard .GetPossibleMoves ()
select m .Position
);
var newSquares =
from r in Enumerable .Range (0 , 8 )
from c in Enumerable .Range (0 , 8 )
select new BoardPosition (r , c );
int i = 0 ;
foreach (var pos in newSquares ) {
mSquares [i ].Player = mBoard .GetPieceAtPosition (pos );
i ++ ;
}
OnPropertyChanged (nameof (BoardValue ));
OnPropertyChanged (nameof (CurrentPlayer ));
OnPropertyChanged (nameof (CanUndo ));
}
public async Task ApplyMove (BoardPosition position ) {
var possMoves = mBoard .GetPossibleMoves () as IEnumerable <OthelloMove >;
foreach (var move in possMoves ) {
if (move .Position .Equals (position )) {
mBoard .ApplyMove (move );
break ;
}
}
RebindState ();
if (Players == NumberOfPlayers .One && ! mBoard .IsFinished ) {
var bestMove = await Task .Run (() => mGameAi .FindBestMove (mBoard ));
if (bestMove != null ) {
mBoard .ApplyMove (bestMove );
RebindState ();
}
}
if (mBoard .PassCount == 2 ) {
GameFinished ? .Invoke (this , new EventArgs ());
}
if (PossibleMoves .Count == 1 && PossibleMoves .First ().Row == - 1 ) {
CurrentPlayerMustPass ? .Invoke (this , new EventArgs ());
}
if (PossibleMoves .Count == 0 || mBoard .IsFinished ) {
GameFinished ? .Invoke (this , new EventArgs ());
}
}
private void RebindState () {
PossibleMoves = new HashSet <BoardPosition >(
from OthelloMove m in mBoard .GetPossibleMoves ()
select m .Position
);
var newSquares =
from r in Enumerable .Range (0 , 8 )
from c in Enumerable .Range (0 , 8 )
select new BoardPosition (r , c );
int i = 0 ;
foreach (var pos in newSquares ) {
mSquares [i ].Player = mBoard .GetPieceAtPosition (pos );
i ++ ;
}
OnPropertyChanged (nameof (BoardValue ));
OnPropertyChanged (nameof (CurrentPlayer ));
OnPropertyChanged (nameof (CanUndo ));
}
public ObservableCollection <OthelloSquare > Squares {
get { return mSquares ; }
}
public HashSet <BoardPosition > PossibleMoves {
get ; private set ;
}
public int BoardValue { get { return mBoard .Value ; } }
public int CurrentPlayer { get { return mBoard .CurrentPlayer ; } }
public NumberOfPlayers Players { get ; set ; }
public bool CanUndo {
get {
return mBoard .MoveHistory .Count > 0 ;
}
}
}
namespace Cecs475 .BoardGames .Othello .View
{
public class OthelloSquare : INotifyPropertyChanged
{
private int mPlayer ;
public int Player
{
get { return mPlayer ; }
set
{
if (value != mPlayer )
{
mPlayer = value ;
OnPropertyChanged (nameof (Player ));
}
}
}
private bool mIsHovered ;
public bool IsHovered
{
get { return mIsHovered ; }
set
{
if (value != mIsHovered )
{
mIsHovered = value ;
OnPropertyChanged (nameof (IsHovered ));
}
}
}
public BoardPosition Position
{
get ; set ;
}
public event PropertyChangedEventHandler PropertyChanged ;
private void OnPropertyChanged (string name )
{
PropertyChanged ? .Invoke (this , new PropertyChangedEventArgs (name ));
}
}
public class OthelloViewModel : INotifyPropertyChanged , IGameViewModel
{
private const int MAX_AI_DEPTH = 7 ;
private OthelloBoard mBoard ;
private ObservableCollection <OthelloSquare > mSquares ;
private IGameAi mGameAi = new MinimaxAi (MAX_AI_DEPTH );
public event PropertyChangedEventHandler PropertyChanged ;
public event EventHandler GameFinished ;
/// <summary >
/// Invoked after applying a move, if the new current player must pass their turn.
/// </summary >
public event EventHandler CurrentPlayerMustPass ;
private void OnPropertyChanged (string name )
{
PropertyChanged ? .Invoke (this , new PropertyChangedEventArgs (name ));
}
public OthelloViewModel ()
{
mBoard = new OthelloBoard ();
mSquares = new ObservableCollection <OthelloSquare >(
from pos in (
from r in Enumerable .Range (0 , 8 )
from c in Enumerable .Range (0 , 8 )
select new BoardPosition (r , c )
)
select new OthelloSquare ()
{
Position = pos ,
Player = mBoard .GetPieceAtPosition (pos )
}
);
PossibleMoves = new HashSet <BoardPosition >(
from OthelloMove m in mBoard .GetPossibleMoves ()
select m .Position
);
}
public void UndoMove ()
{
mBoard .UndoLastMove ();
// In one-player mode, Undo has to remove an additional move to return to the
// human player's turn.
if (Players == NumberOfPlayers .One )
{
mBoard .UndoLastMove ();
}
PossibleMoves = new HashSet <BoardPosition >(
from OthelloMove m in mBoard .GetPossibleMoves ()
select m .Position
);
var newSquares =
from r in Enumerable .Range (0 , 8 )
from c in Enumerable .Range (0 , 8 )
select new BoardPosition (r , c );
int i = 0 ;
foreach (var pos in newSquares )
{
mSquares [i ].Player = mBoard .GetPieceAtPosition (pos );
i ++ ;
}
OnPropertyChanged (nameof (BoardValue ));
OnPropertyChanged (nameof (CurrentPlayer ));
OnPropertyChanged (nameof (CanUndo ));
}
public async Task ApplyMove (BoardPosition position )
{
var possMoves = mBoard .GetPossibleMoves () as IEnumerable <OthelloMove >;
foreach (var move in possMoves )
{
if (move .Position .Equals (position ))
{
mBoard .ApplyMove (move );
break ;
}
}
RebindState ();
if (Players == NumberOfPlayers .One && ! mBoard .IsFinished )
{
var bestMove = await Task .Run (() => mGameAi .FindBestMove (mBoard ));
if (bestMove != null )
{
mBoard .ApplyMove (bestMove );
RebindState ();
}
}
if (mBoard .PassCount == 2 )
{
GameFinished ? .Invoke (this , new EventArgs ());
}
if (PossibleMoves .Count == 1 && PossibleMoves .First ().Row == - 1 )
{
CurrentPlayerMustPass ? .Invoke (this , new EventArgs ());
}
if (PossibleMoves .Count == 0 || mBoard .IsFinished )
{
GameFinished ? .Invoke (this , new EventArgs ());
}
}
private void RebindState ()
{
PossibleMoves = new HashSet <BoardPosition >(
from OthelloMove m in mBoard .GetPossibleMoves ()
select m .Position
);
var newSquares =
from r in Enumerable .Range (0 , 8 )
from c in Enumerable .Range (0 , 8 )
select new BoardPosition (r , c );
int i = 0 ;
foreach (var pos in newSquares )
{
mSquares [i ].Player = mBoard .GetPieceAtPosition (pos );
i ++ ;
}
OnPropertyChanged (nameof (BoardValue ));
OnPropertyChanged (nameof (CurrentPlayer ));
OnPropertyChanged (nameof (CanUndo ));
}
public ObservableCollection <OthelloSquare > Squares
{
get { return mSquares ; }
}
public HashSet <BoardPosition > PossibleMoves
{
get ; private set ;
}
public int BoardValue { get { return mBoard .Value ; } }
public int CurrentPlayer { get { return mBoard .CurrentPlayer ; } }
public NumberOfPlayers Players { get ; set ; }
public bool CanUndo
{
get
{
return mBoard .MoveHistory .Count > 0 ;
}
}
}
}