Skip to content
1 change: 1 addition & 0 deletions Change file
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Can we changed some codes on this project.
57 changes: 57 additions & 0 deletions Computer Player
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/// This class represents a "comuter" player.
/// It determines moves using minmax decision rules
/// </summary>
public class ComputerPlayer : Player
{
public const int DEFAULT_SEARCH_DEPTH = 3;

/// <summary>
/// Constructs a new computer player. The DEFAULT_SEARCH_DEPTH is used
/// </summary>
/// <param name="name">The name of the player</param>
/// <param name="p">The piece this player is using in the came</param>
public ComputerPlayer(string name, Board.Pieces p) : this(name,
p, DEFAULT_SEARCH_DEPTH)
{
}

/// <summary>
/// Constructs a new computer player
/// </summary>
/// <param name="name">The name of the player</param>
/// <param name="p">The piece the player is using</param>
/// <param name="searchDepth">The depth to search for moves in the game tree.</param>
public ComputerPlayer(string name, Board.Pieces p, int searchDepth) :base(name, p)
{
this.SearchDepth = searchDepth;
}

/// <summary>
/// gets or sets the search depth which is the number of moves
/// the computer player will look ahead to determine it's move
/// Greater values yield better computer play
/// </summary>
public int SearchDepth { get; set; }

/// <summary>
/// Start the computer searching for a move
/// Clients should listen to the OnPlayerMoved event to be notified
/// when the computer has found a move
/// </summary>
/// <param name="gameBoard">The current game board</param>
public override void Move(object gameBoard)
{
Board b = (Board)gameBoard;

Node root = new MaxNode(b, null, null);
root.MyPiece = this.PlayerPiece;
root.Evaluator = new EvaluationFunction();
root.FindBestMove(DEFAULT_SEARCH_DEPTH);

currentMove = root.BestMove;

OnPlayerMoved();
}

...
}
43 changes: 43 additions & 0 deletions Creating Players and Running the Game
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

TicTacToeForm f = new TicTacToeForm();

// Create the game players
// Players can be either human or computer players
// It does not matter which piece 'X' or 'O' player 1 or two have
// but they must be different

// Create a human player
Player p1 = new HumanPlayer("Joe", Board.Pieces.X, f);

// Create a computer player
// You can create varying degrees of difficulty by creating computer
// players that build bigger game trees
// uncomment desired player and comment all other player 2s

// create a computer player with the default game tree search depth
Player p2 = new ComputerPlayer("HAL", Board.Pieces.O);

// Create a computer player that only looks ahead 1 move
// i.e only considers their immediate move and not any subsequent moves
// by their opponent.
// this is a very poor player
// Player p2 = new ComputerPlayer(Board.Pieces.X, f, 1);

// Creates an advanced computer player that looks ahead 5 moves
// Player p2 = new ComputerPlayer("Advanced HAL", Board.Pieces.X, 5);

f.AddPlayer(p1);
f.AddPlayer(p2);

Application.Run(f);

}
}
42 changes: 42 additions & 0 deletions Creating a board
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/// <summary>
/// This class represents a tic-tac-toe board
/// It is Cloneable so that we can copy board configurations when searching for a next move
/// </summary>
public class Board : ICloneable
{
public enum Pieces { X, O, Empty };

int width = 3;
int height = 3;

protected int[,] board; // a two-dimensional array representing the game board

/// <summary>
/// Constructs an empty board
/// </summary>
public Board()
{
board = new int[ROWS, COLUMNS];
}

/// <summary>
/// Make a move on the board
/// </summary>
/// <param name="position">the board position to take</param>
/// <param name="piece"></param>
public void MakeMove(int position, Pieces piece)
{

if (!IsValidSquare(position))
throw new InvalidMoveException();

int pieceNumber = GetPieceNumber(piece);

Point point = GetPoint(position);

board[point.X, point.Y] = pieceNumber;
}
...
// more code in actual source file

}
43 changes: 43 additions & 0 deletions Creating the Players
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// This class abstracts the idea of a Player and includes some commone functionality.
/// It includes an event for clients to be notified when a move is made
/// </summary>
public abstract class Player
{

// Listen for a move made by a player
public event PlayerMovedHandler PlayerMoved;

protected TicTacToeMove currentMove;
public Player(string name, Board.Pieces p)
{
this.Name = name;
this.PlayerPiece = p;
}

public abstract void Move(object gameBoard);

public TicTacToeMove CurrentMove
{
get { return currentMove; }
}

/// <summary>
/// This is invoked by subclasses to indicate that the player decided on a move
/// </summary>
public virtual void OnPlayerMoved()
{
if (PlayerMoved != null)
PlayerMoved(this, new PlayerMovedArgs(currentMove, this));
}

/// <summary>
/// Get or Set the player's piece
/// </summary>
public Board.Pieces PlayerPiece { get; set; }

/// <summary>
/// Get or set the player's name
/// </summary>
public string Name { get; set; }

}
43 changes: 43 additions & 0 deletions Creating the Players1
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// This class abstracts the idea of a Player and includes some commone functionality.
/// It includes an event for clients to be notified when a move is made
/// </summary>
public abstract class Player
{

// Listen for a move made by a player
public event PlayerMovedHandler PlayerMoved;

protected TicTacToeMove currentMove;
public Player(string name, Board.Pieces p)
{
this.Name = name;
this.PlayerPiece = p;
}

public abstract void Move(object gameBoard);

public TicTacToeMove CurrentMove
{
get { return currentMove; }
}

/// <summary>
/// This is invoked by subclasses to indicate that the player decided on a move
/// </summary>
public virtual void OnPlayerMoved()
{
if (PlayerMoved != null)
PlayerMoved(this, new PlayerMovedArgs(currentMove, this));
}

/// <summary>
/// Get or Set the player's piece
/// </summary>
public Board.Pieces PlayerPiece { get; set; }

/// <summary>
/// Get or set the player's name
/// </summary>
public string Name { get; set; }

}
55 changes: 55 additions & 0 deletions Creating the Players2
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/// <summary>
/// This class represents a Human Player
/// </summary>
public class HumanPlayer : Player
{

protected TicTacToeForm ticTacToeForm;

protected bool alreadyMoved = false;

public HumanPlayer(string name, Board.Pieces p, TicTacToeForm tttf)
: base(name, p)
{

this.ticTacToeForm = tttf;

}

/// <summary>
/// Make a move. Waits for the player to double click a square
/// and then triggers the PlayerMoved Event
/// </summary>
/// <param name="gameBoard"></param>
public override void Move(object gameBoard)
{

// start listening to clicks
ticTacToeForm.SquareDoubleClicked += new SquareDoubleClickHandler(SquareDoubleClicked);

// now wait until the user clicks
while (!alreadyMoved)
;

// reset the flag
alreadyMoved = false;
// raise the PlayerMovedEvent
OnPlayerMoved();

}

// when a user double clicks a square on the TicTacToeForm this method receives the
// event message
// the current move is set and the alreadyMoved flag is set to true so that the
// which breaks the while loop in the Move method
void SquareDoubleClicked(object sender, TicTacToeBoardClickedEventArgs args)
{
// unregister the double clicked event
ticTacToeForm.SquareDoubleClicked -= SquareDoubleClicked;

currentMove = new TicTacToeMove(args.BoardPosition, this.PlayerPiece);
alreadyMoved = true;

}

}
94 changes: 94 additions & 0 deletions Creating the Tic-Tac-Toe Game
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/// This class represents a Tic-Tac-Toe game board. It includes logic
/// to keep track of player turns and assign board squares to a player
/// </summary>
public class TicTacToeGame
{

public enum Players { Player1, Player2 };
protected Board board;

protected Stack<TicTacToeMove> moves;
protected Players currentTurn = Players.Player1; // Player 1 goes first

protected bool gameOver = false;

/// <summary>
/// Constructs a new TicTacToeGame using the default board pieces for player one and two
/// </summary>
public TicTacToeGame() : this(Board.Pieces.X, Board.Pieces.O)
{

}

/// <summary>
/// Constructs a new TicTacToe game using the specified player's pieces.
///
/// </summary>
/// <param name="player1Piece">Player one's piece</param>
/// <param name="player2Piece">Player two's piece</param>
public TicTacToeGame(Board.Pieces player1Piece, Board.Pieces player2Piece)
{
this.player1Piece = player1Piece;
this.player2Piece = player2Piece;
board = new Board();
moves = new Stack<TicTacToeMove>();
}

/// <summary>
/// Returns true if the game is over (if there is a winner or there is a draw)
/// </summary>
/// <returns>true if the game is over or false otherwise</returns>
public bool IsGameOver()
{
return board.IsGameOver();
}

/// <summary>
/// Undoes the last move
/// </summary>
public void UndoLastMove()
{
TicTacToeMove lastMove = moves.Pop();

board.UndoMove(lastMove);

SwapTurns();

}

/// <summary>
/// Returns the player for whose turn it is
/// </summary>
public Players CurrentPlayerTurn
{
get { return this.currentTurn; }
}

/// <summary>
/// Makes the move for the specified player
/// </summary>
/// <param name="m">The move to make</param>
/// <param name="p">The player making the move</param>
public void MakeMove(TicTacToeMove m, Players p)
{

if (currentTurn != p)
{
throw new InvalidMoveException("You went out of turn!");
}

if (!board.IsValidSquare(m.Position))
throw new InvalidMoveException("Pick a square on the board!");

board.MakeMove(m.Position, m.Piece);

moves.Push(m);

SwapTurns();

}

...
// more code here

}
Loading