Example #1
0
 private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
 {
     _game = new TicTacToeGame(NeededForWin);
     s_moves.Clear();
     CurrentPlayer = TicTacToeValue.x;
     tslMoveCount.Text = "";
     Refresh();
 }
        public static LabeledState <GameState, TicTacToeValue> ParsePosition(string position, Func <GameState, double[]> inputTransform)
        {
            string[]  components = position.Split(new string[] { "\r\n", " " }, StringSplitOptions.RemoveEmptyEntries);
            GameState gameState  = GameState.Parse(components[0], components[3], components[6]);

            double[] output = new double[3];
            output[0] = double.Parse(components[0 * 3 + 2]);
            output[1] = double.Parse(components[1 * 3 + 2]);
            output[2] = double.Parse(components[2 * 3 + 2]);
            var probabilities = new TicTacToeValue(output);

            return(new LabeledState <GameState, TicTacToeValue>(gameState, inputTransform(gameState), output, probabilities));
        }
Example #3
0
        public VisualNode AddMove(int x, int y, TicTacToeValue currentPlayer)
        {
            string nodeKey = Constants.GetKey(x, y);

            if (nodes.ContainsKey(nodeKey))
            {
                return(null);
            }

            VisualNode newNode = new VisualNode(x, y, currentPlayer);

            nodes.Add(nodeKey, newNode);

            return(newNode);
        }
Example #4
0
        public GameAction GenerateAction(GameState state)
        {
            var actions     = TicTacToeGame.Instance.GetAllowedActions(state);
            var states      = actions.Select(action => TicTacToeGame.Instance.Play(state, action));
            var predictions = states.Select(Network.Evaluate).Select(prediction => prediction.Probabilities);

            foreach (var prediction in predictions)
            {
                Console.WriteLine($"{string.Join(" ", prediction)}");
            }

            int best = TicTacToeValue.FindBest(predictions, state.CurrentPlayer);

            return(actions.ElementAt(best));
        }
Example #5
0
        private void TraverseBoard(VisualNode node, NodeLocation direction, Action <VisualNode> runAction)
        {
            // flag all the nodes on the winDirection
            var            currentNode = nodes[Constants.GetKey(node.X, node.Y)];
            TicTacToeValue nodeValue   = node.Value;

            // traverse all nodes of the same value
            while (currentNode.Value == nodeValue)
            {
                runAction(currentNode);
                string nodeKey = Constants.MapDirectionToComputation[direction](currentNode.X, currentNode.Y);

                // continue on the direction, if there is anything there.
                if (nodes.ContainsKey(nodeKey))
                {
                    currentNode = nodes[nodeKey];
                }
                else
                {
                    break;
                }
            }
        }
Example #6
0
        private bool PlaceMove(VisualNode move)
        {
            if (_game.GameEnded)
            {
                return false;
            }

            if (move == null)
            {
                MessageBox.Show("Cannot place the move there!");
                return false;
            }

            s_moves.Push(move);

            tslMoveCount.Text = $"Move: {s_moves.Count}";

            Refresh();

            NodeLocation winDirection;
            if (_game.IsWinningMove(move, out winDirection))
            {
                _game.GameEnded = true;
                // Mark the wining nodes.
                _game.MarkWinningNodes(move, winDirection);
                Refresh();

#if !COMPUTER_AGAINST_ITSELF
                MessageBox.Show($"Winner is player {CurrentPlayer}!!!");
#else

                if (CurrentPlayer == TicTacToeValue.x)
                    winX++;
                else
                    winO++;

                if (s_moves.Count > maxMove)
                    maxMove = s_moves.Count;
                if (s_moves.Count < minMove)
                    minMove = s_moves.Count;

                label3.Text = $"X: {winX}, O: {winO}, min:{minMove}, max:{maxMove}";
#endif

                _game = new TicTacToeGame(NeededForWin);
                s_moves.Clear();
                CurrentPlayer = TicTacToeValue.x;
                tslMoveCount.Text = "";
                Refresh();

#if COMPUTER_AGAINST_ITSELF
                PlaceAIMove();
#endif
                return true;
            }
            else
            {
                ChangePlayer();

#if COMPUTER_AGAINST_ITSELF
                PlaceAIMove();
#endif
            }

            Application.DoEvents();
            return false;
        }
Example #7
0
 private void ChangePlayer()
 {
     CurrentPlayer = CurrentPlayer == TicTacToeValue.o ? TicTacToeValue.x : TicTacToeValue.o;
 }
Example #8
0
 public VisualNode(int x, int y, TicTacToeValue value)
 {
     X     = x;
     Y     = y;
     Value = value;
 }
Example #9
0
        public VisualNode GetAIMove(TicTacToeValue currentPlayer)
        {
            if (nodes.Count == 0)
            {
                return(AddMove(15, 15, currentPlayer));
            }

            string myMove = string.Empty;
            // figure out all the empty nodes outthere.
            HashSet <string> positions = GetEmptyNeighBours();

            // we are going to count (-1, 1) based on the counts for each position.
            // we don't need to actually place the move, just compute the neighbours we need to check for.
            Dictionary <string, int> mapPositionContributions = new Dictionary <string, int>();
            int bestX = 0, bestO = 0;

            foreach (var position in positions)
            {
                int currentX, currentY;
                Constants.GetCoordinates(position, out currentX, out currentY);

                // find all the nei

                int positionValues = 0; // consider it neutral for now.

                positionValues = Max(CountOnDirection(NodeLocation.TopCenter, currentX, currentY, currentPlayer),
                                     CountOnDirection(NodeLocation.Left, currentX, currentY, currentPlayer),
                                     CountOnDirection(NodeLocation.TopLeft, currentX, currentY, currentPlayer),
                                     CountOnDirection(NodeLocation.TopRight, currentX, currentY, currentPlayer));

                // keep a running total of best X and best O positions
                if (positionValues >= 0 && positionValues > bestX)
                {
                    bestX = positionValues;
                }

                if (positionValues <= 0 && positionValues < bestO)
                {
                    bestO = positionValues;
                }

                Debug.WriteLine($"Computed value {position}={positionValues}");
                mapPositionContributions[position] = positionValues;
            }

            Debug.WriteLine($"Best X postion has value {bestX}, Best O position has value {bestO}");

            // we now need to figure out the win move.
            int bestMoveCount;

            if (currentPlayer == TicTacToeValue.o)
            {
                //if we have a tie, prefer to win the game!
                if (Math.Abs(bestO) == Math.Abs(bestX))
                {
                    bestMoveCount = bestO;
                }
                else
                {
                    bestMoveCount = Math.Abs(bestO) > Math.Abs(bestX) ? bestO : bestX;
                }
            }
            else
            {
                //if we have a tie, prefer to win the game!
                if (Math.Abs(bestO) == Math.Abs(bestX))
                {
                    bestMoveCount = bestX;
                }
                else
                {
                    bestMoveCount = Math.Abs(bestX) > Math.Abs(bestO) ? bestX : bestO;
                }
            }

            Random r = new Random((int)DateTime.Now.Ticks);
            var    possibleMoves = mapPositionContributions.Where(pair => pair.Value == bestMoveCount);

            myMove = possibleMoves.Skip(r.Next(possibleMoves.Count() - 1)).First().Key;
            Debug.WriteLine($"The best move for {currentPlayer} is {myMove}");

            int x = 0, y = 0;

            Constants.GetCoordinates(myMove, out x, out y);
            return(AddMove(x, y, currentPlayer));
        }
Example #10
0
        private int CountOnDirection(NodeLocation direction, int currentX, int currentY, TicTacToeValue currentPlayer)
        {
            int countForX = CountOnBothDirectionsUsingBoard(direction, currentX, currentY, TicTacToeValue.x);
            int countForO = CountOnBothDirectionsUsingBoard(direction, currentX, currentY, TicTacToeValue.o);

            return(currentPlayer == TicTacToeValue.x ? countForX - countForO : countForO - countForX);
        }
Example #11
0
        private int CountOnBothDirectionsUsingBoard(NodeLocation direction, int currentX, int currentY, TicTacToeValue currentPlayer)
        {
            var moveFirstDir  = CountOnSingleDirectionUsingBoard(direction, currentX, currentY, currentPlayer);
            var moveSecondDir = CountOnSingleDirectionUsingBoard(direction.GetReverseDirection(), currentX, currentY, currentPlayer);

            int count = moveFirstDir.countPerDirection + moveSecondDir.countPerDirection;

            // this is the case where we have something like: o x _ x x o
            // there is no point to put an o in there as that can never ever be a winning move from x
            if (count <= 3 && (moveFirstDir.endsWithOpponentMove && moveSecondDir.endsWithOpponentMove))
            {
                count = 0;
            }

            if (count >= 4)
            {
                count *= count;
            }
            else if (count >= 3)
            {
                count *= 2;
            }

            if (count >= 2 && !moveFirstDir.endsWithOpponentMove)
            {
                count++;
            }

            if (count >= 2 && !moveSecondDir.endsWithOpponentMove)
            {
                count++;
            }

            return(count);
        }
Example #12
0
        private AIMove CountOnSingleDirectionUsingBoard(NodeLocation direction, int currentX, int currentY, TicTacToeValue currentPlayer)
        {
            AIMove move = new AIMove();
            //int count = 0;
            string nodeKey = Constants.MapDirectionToComputation[direction](currentX, currentY);

            if (!nodes.ContainsKey(nodeKey))
            {
                return(move);
            }

            TraverseBoard(nodes[nodeKey], direction, (node) =>
            {
                if (node.Value == currentPlayer)
                {
                    move.countPerDirection++;
                }
                else
                {
                    move.endsWithOpponentMove = true;
                }

                // check to see if there is a next neighbor
                string nk = Constants.MapDirectionToComputation[direction](node.X, node.Y);
                if (!nodes.ContainsKey(nk))
                {
                    move.endsWithOpponentMove = false;
                }
                else
                {
                    if (nodes[nk].Value != currentPlayer)
                    {
                        move.endsWithOpponentMove = true;
                    }
                }
            });
            return(move);
        }