From caff8d79aa3d5273af44989625ddb7dc95b060bf Mon Sep 17 00:00:00 2001 From: Ashish Singh Chauhan Date: Wed, 16 Sep 2015 02:19:14 +0530 Subject: [PATCH 01/13] Finish Readme Chess Library is Project for AI --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ddf7b5e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Chess +Chess library & test program with AI +Chess library is a project for AI From e3df263b60e9c823c108ca64a35bf3556be05dbf Mon Sep 17 00:00:00 2001 From: Ashish Singh Chauhan Date: Thu, 15 Jun 2017 12:13:59 +0530 Subject: [PATCH 02/13] Change Change some file --- Change file | 1 + 1 file changed, 1 insertion(+) create mode 100644 Change file diff --git a/Change file b/Change file new file mode 100644 index 0000000..2c55ddc --- /dev/null +++ b/Change file @@ -0,0 +1 @@ +Can we changed some codes on this project. From 50944afa10a5fd7e4ffb37e25104d2536407700f Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:36:25 +0530 Subject: [PATCH 03/13] Creating a board --- Creating a board | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Creating a board diff --git a/Creating a board b/Creating a board new file mode 100644 index 0000000..f0c3ab0 --- /dev/null +++ b/Creating a board @@ -0,0 +1,42 @@ + /// + /// This class represents a tic-tac-toe board + /// It is Cloneable so that we can copy board configurations when searching for a next move + /// + 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 + + /// + /// Constructs an empty board + /// + public Board() + { + board = new int[ROWS, COLUMNS]; + } + + /// + /// Make a move on the board + /// + /// the board position to take + /// + 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 + + } From 275e4edee73c67b48f5d4a573054b031cc3c0a3c Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:38:43 +0530 Subject: [PATCH 04/13] Creating the Tic-Tac-Toe Game --- Creating the Tic-Tac-Toe Game | 94 +++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Creating the Tic-Tac-Toe Game diff --git a/Creating the Tic-Tac-Toe Game b/Creating the Tic-Tac-Toe Game new file mode 100644 index 0000000..bba1303 --- /dev/null +++ b/Creating the Tic-Tac-Toe Game @@ -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 + /// + public class TicTacToeGame + { + + public enum Players { Player1, Player2 }; + protected Board board; + + protected Stack moves; + protected Players currentTurn = Players.Player1; // Player 1 goes first + + protected bool gameOver = false; + + /// + /// Constructs a new TicTacToeGame using the default board pieces for player one and two + /// + public TicTacToeGame() : this(Board.Pieces.X, Board.Pieces.O) + { + + } + + /// + /// Constructs a new TicTacToe game using the specified player's pieces. + /// + /// + /// Player one's piece + /// Player two's piece + public TicTacToeGame(Board.Pieces player1Piece, Board.Pieces player2Piece) + { + this.player1Piece = player1Piece; + this.player2Piece = player2Piece; + board = new Board(); + moves = new Stack(); + } + + /// + /// Returns true if the game is over (if there is a winner or there is a draw) + /// + /// true if the game is over or false otherwise + public bool IsGameOver() + { + return board.IsGameOver(); + } + + /// + /// Undoes the last move + /// + public void UndoLastMove() + { + TicTacToeMove lastMove = moves.Pop(); + + board.UndoMove(lastMove); + + SwapTurns(); + + } + + /// + /// Returns the player for whose turn it is + /// + public Players CurrentPlayerTurn + { + get { return this.currentTurn; } + } + + /// + /// Makes the move for the specified player + /// + /// The move to make + /// The player making the move + 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 + + } From 4c3fcd00e2b376e2f5fe876780f88e9c3966513d Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:42:24 +0530 Subject: [PATCH 05/13] Creating the Tic-Tac-Toe Game1 --- Creating the Tic-Tac-Toe Game1 | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Creating the Tic-Tac-Toe Game1 diff --git a/Creating the Tic-Tac-Toe Game1 b/Creating the Tic-Tac-Toe Game1 new file mode 100644 index 0000000..505ee3e --- /dev/null +++ b/Creating the Tic-Tac-Toe Game1 @@ -0,0 +1,28 @@ + /// + /// Represents a tic-tac-toe move + /// + public class TicTacToeMove + { + + /// + /// Constructs a TicTacToeMove + /// + /// The position to move to + /// The piece that is moving + public TicTacToeMove(int position, Board.Pieces piece) + { + this.Position = position; + this.Piece = piece; + } + + /// + /// gets or sets the position on the board + /// + public int Position { get; set; } + + /// + /// Gets or sets the piece making this move + /// + public Board.Pieces Piece {get; set;} + + } From 655b38a7752c1ac98f95de803cbd0c8c1ec8cfe6 Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:44:21 +0530 Subject: [PATCH 06/13] Creating the Players --- Creating the Players | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Creating the Players diff --git a/Creating the Players b/Creating the Players new file mode 100644 index 0000000..d26c6d5 --- /dev/null +++ b/Creating the Players @@ -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 + /// + 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; } + } + + /// + /// This is invoked by subclasses to indicate that the player decided on a move + /// + public virtual void OnPlayerMoved() + { + if (PlayerMoved != null) + PlayerMoved(this, new PlayerMovedArgs(currentMove, this)); + } + + /// + /// Get or Set the player's piece + /// + public Board.Pieces PlayerPiece { get; set; } + + /// + /// Get or set the player's name + /// + public string Name { get; set; } + + } From 3dbe280e1965fa689cfea0f8d4056657f300511f Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:50:52 +0530 Subject: [PATCH 07/13] Creating the Players1 --- Creating the Players1 | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Creating the Players1 diff --git a/Creating the Players1 b/Creating the Players1 new file mode 100644 index 0000000..d26c6d5 --- /dev/null +++ b/Creating the Players1 @@ -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 + /// + 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; } + } + + /// + /// This is invoked by subclasses to indicate that the player decided on a move + /// + public virtual void OnPlayerMoved() + { + if (PlayerMoved != null) + PlayerMoved(this, new PlayerMovedArgs(currentMove, this)); + } + + /// + /// Get or Set the player's piece + /// + public Board.Pieces PlayerPiece { get; set; } + + /// + /// Get or set the player's name + /// + public string Name { get; set; } + + } From 73bc8254eea26923f70e3d0f7a16199a5b98175f Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:52:42 +0530 Subject: [PATCH 08/13] Creating the Players2 --- Creating the Players2 | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Creating the Players2 diff --git a/Creating the Players2 b/Creating the Players2 new file mode 100644 index 0000000..243578d --- /dev/null +++ b/Creating the Players2 @@ -0,0 +1,55 @@ +/// + /// This class represents a Human Player + /// + 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; + + } + + /// + /// Make a move. Waits for the player to double click a square + /// and then triggers the PlayerMoved Event + /// + /// + 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; + + } + + } From b5189093b2a54a7f1a2f75a92388bd670128db07 Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:56:53 +0530 Subject: [PATCH 09/13] Implementing MINIMAX --- Implementing MINIMAX | 179 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 Implementing MINIMAX diff --git a/Implementing MINIMAX b/Implementing MINIMAX new file mode 100644 index 0000000..976ca24 --- /dev/null +++ b/Implementing MINIMAX @@ -0,0 +1,179 @@ + /// + /// This class represents a Node in the search Tree. + /// Each Node contains a particular board configuration. Nodes 0 or more children + /// that represent subsequent moves from that Node's board. + /// + /// + public abstract class Node + { + + // this nodes children + protected List children; + + // the value associated with the node -- this is the result of the + // evaluatio function for leaf nodes + protected double value; + + // The child node that represents the best move + // for a node. + protected Node bestMoveNode; + + // the board that this node represents + protected Board board; + + // the evaluation function + protected static EvaluationFunction evaluator; + + protected Board.Pieces myPiece; // the piece representing the node's piece + protected Board.Pieces opponentPiece; // the opponents piece + + // the move that was made from the parent node that created this node + TicTacToeMove move; + Node parent = null; + + /// + /// Constructs a new Node + /// + /// The board that the Node will use to evaluate itself and generate its children + /// The parent of this node + /// The move from the parent's board that generated this node's board + public Node(Board b, Node parent, TicTacToeMove move) + { + this.board = b; + this.parent = parent; + this.move = move; + if (parent != null) + myPiece = Board.GetOponentPiece(parent.MyPiece); + children = new List(); + } + + /// + /// The game piece that this node 'has' + /// + public Board.Pieces MyPiece + { + get { return myPiece; } + set + { + myPiece = value; + opponentPiece = Board.GetOponentPiece(value); + } + } + + /// + /// sets the evaluation function used by this node to calculate + /// its value + /// + public EvaluationFunction Evaluator + { + set { evaluator = value; } + } + + /// + /// The value of this node either computed by the evaluation function + /// or the value selected from among child nodes, + /// + public double Value + { + get { return value; } + set { this.value = value;} + } + + /// + /// + /// + public abstract void Evaluate(); + + /// + /// Selects the best move node for the node + /// + public void SelectBestMove() + { + // if no children there is no best move for the node + if (children.Count == 0) + { + bestMoveNode = null; + return; + } + + // sort the children so that the first element contains the 'best' node + List sortedChildren = SortChildren(this.children); + + this.bestMoveNode = sortedChildren[0]; + Value = bestMoveNode.Value; + } + + /// + /// Finds the best move for the node. + /// + /// The depth to search + public virtual void FindBestMove(int depth) + { + if (depth > 0) + { + // expand this node -- subclasses provide their own implementation of this + GenerateChildren(); + + // evaluate each child + // if there is a winner there is no need to go further down + // the tree + // sends the Evaluate() message to each child node, which is implemented + // by subclasses + EvaluateChildren(); + + // check for a winner + bool haveWinningChild = children.Exists(c => c.IsGameEndingNode()); + + if (haveWinningChild) + { + // the best move depends on the subclass + SelectBestMove(); + return; + } + else + { + foreach (Node child in children) + { + child.FindBestMove(depth - 1); + } + SelectBestMove(); + } + } + } + + /// + /// Checks to see if the node is either a winner or MAX or MIN + /// + /// true if either 'X' or 'O' + public virtual bool IsGameEndingNode() + { + return Value == double.MaxValue || Value == double.MinValue; + } + + /// + /// The best move from this node's board configuration + /// + public TicTacToeMove BestMove + { + get { return this.bestMoveNode.move; } + } + + // create the children + protected void GenerateChildren(); + + // evaluate the child nodes + protected void EvaluateChildren() + { + foreach (Node child in this.children) + { + child.Evaluate(); + } + } + + protected abstract List SortChildren(List unsortedChildren); + + // does the node's configuration represent a winner + // for the node in question + protected abstract bool IsWinningNode(); + + } From d40f1994c7c1278c7b1247bfd2e06027b0883c63 Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 06:59:18 +0530 Subject: [PATCH 10/13] MinNode and MaxNode --- MinNode and MaxNode | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 MinNode and MaxNode diff --git a/MinNode and MaxNode b/MinNode and MaxNode new file mode 100644 index 0000000..d5c7d0a --- /dev/null +++ b/MinNode and MaxNode @@ -0,0 +1,54 @@ + /// This class represents a MAX node in the game tree. + /// + public class MaxNode : Node + { + + /// + /// Constructs a new max node + /// + /// The Board that this node represents + /// The node's parent + /// The move made to create this node's board + public MaxNode(Board b, Node parent, TicTacToeMove m) + : base(b, parent, m) + { + } + + // Generate Children. MAX Nodes have MIN children + protected override void GenerateChildren() + { + // create child nodes for each of the availble positions + int[] openPositions = board.OpenPositions; + + foreach (int i in openPositions) + { + Board b = (Board) board.Clone(); + TicTacToeMove m = new TicTacToeMove(i, myPiece); + + b.MakeMove(i, myPiece); + children.Add(new MinNode(b, this, m)); + + } + } + + // Evaluates how favorable the board configuration is for this node + protected override void Evaluate() + { + this.Value = evaluator.Evaluate(this.board, myPiece); + } + + // does this node have a winning game configuration + protected override bool IsWinningNode() + { + + return this.Value == double.MaxValue; + } + + // returns a List of this nodes children sorted in descending order + protected override List SortChildren(List unsortedChildren) + { + List sortedChildren = unsortedChildren.OrderByDescending(n=> n.Value).ToList(); + return sortedChildren; + } + + } From 1d4b3fd823071f61ab65cc2c01d693fa06e9c072 Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 07:03:34 +0530 Subject: [PATCH 11/13] MinNode --- MinNode | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 MinNode diff --git a/MinNode b/MinNode new file mode 100644 index 0000000..6ee14f8 --- /dev/null +++ b/MinNode @@ -0,0 +1,60 @@ + /// + /// This class represents a MIN node in the game tree + /// + public class MinNode : Node + { + + /// + /// Constructs a MIN node + /// + /// The board that this node represents + /// This node's parent + /// The move that was made from the parent to lead to this node's board + public MinNode(Board b, Node parent, TicTacToeMove m) + :base(b, parent, m) + { + + } + + // Generates the node's children. MIN nodes have MAX children + protected override void GenerateChildren() + { + int[] openPositions = board.OpenPositions; + + foreach (int i in openPositions) + { + Board b = (Board)board.Clone(); + TicTacToeMove m = new TicTacToeMove(i, myPiece); + + b.MakeMove(i, myPiece); + children.Add(new MaxNode(b, this, m)); + + } + + } + + // determines if this node is a winner + // by convention a winning node for a MIN node + // is double.MinValue + protected override bool IsWinningNode() + { + return this.value == double.MinValue; + + } + + // returns a list of the child nodes in ascending order + // the first node in the list will be the best node for the min node + protected override List SortChildren(List unsortedChildren) + { + List sortedChildren = unsortedChildren.OrderBy(n => n.Value).ToList(); + return sortedChildren; + } + + /// + /// evalutes the value of the node using the evaluation function + /// + protected override void Evaluate() + { + Value = evaluator.Evaluate(board, Board.GetOponentPiece(myPiece)); + } + } From 3ca6b9dd60b52216ad7586f1b24b097e72272524 Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 07:05:09 +0530 Subject: [PATCH 12/13] Computer Player --- Computer Player | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Computer Player diff --git a/Computer Player b/Computer Player new file mode 100644 index 0000000..4e6b64b --- /dev/null +++ b/Computer Player @@ -0,0 +1,57 @@ + /// This class represents a "comuter" player. + /// It determines moves using minmax decision rules + /// + public class ComputerPlayer : Player + { + public const int DEFAULT_SEARCH_DEPTH = 3; + + /// + /// Constructs a new computer player. The DEFAULT_SEARCH_DEPTH is used + /// + /// The name of the player + /// The piece this player is using in the came + public ComputerPlayer(string name, Board.Pieces p) : this(name, + p, DEFAULT_SEARCH_DEPTH) + { + } + + /// + /// Constructs a new computer player + /// + /// The name of the player + /// The piece the player is using + /// The depth to search for moves in the game tree. + public ComputerPlayer(string name, Board.Pieces p, int searchDepth) :base(name, p) + { + this.SearchDepth = searchDepth; + } + + /// + /// 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 + /// + public int SearchDepth { get; set; } + + /// + /// Start the computer searching for a move + /// Clients should listen to the OnPlayerMoved event to be notified + /// when the computer has found a move + /// + /// The current game board + 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(); + } + + ... + } From 978a6eed4893904ccdf4c653cf0f67f1e87c2e0d Mon Sep 17 00:00:00 2001 From: Ashish <8013785+ashu-22@users.noreply.github.com> Date: Tue, 29 Aug 2017 07:07:05 +0530 Subject: [PATCH 13/13] Creating Players and Game --- Creating Players and Running the Game | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Creating Players and Running the Game diff --git a/Creating Players and Running the Game b/Creating Players and Running the Game new file mode 100644 index 0000000..d48f8c0 --- /dev/null +++ b/Creating Players and Running the Game @@ -0,0 +1,43 @@ + /// + /// The main entry point for the application. + /// + [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); + + } + }