Beispiel #1
0
        public bool DoesPlayer1HaveZugzwang(Board board)
        {
            //find threats, label even or odd
            var boardSearch = new BoardSearch(4);

            var groups       = boardSearch.FindGroups(1, board, 1);
            var hasOddThreat = groups.Select(g => g.Coords.Any(t => t.Row % 2 != 0)).Any();

            return(hasOddThreat);
        }
Beispiel #2
0
        public int Run(Board board, int numToWin, int playerNumber = 2)
        {
            PLAYERNUM = playerNumber;
            var search = new BoardSearch(numToWin);

            var legalMoves = search.FindAllLegalMoves(board);

            var yourThreats = search.FindGroups(PLAYERNUM, board, 1);
            var oppThreats  = search.FindGroups(1, board, 1);

            int?columnToPlay = 0;

            //can you win?
            columnToPlay = MatchThreatsWithLegal(yourThreats, legalMoves);
            if (columnToPlay.HasValue)
            {
                return(columnToPlay.Value);
            }

            //should you block?
            columnToPlay = MatchThreatsWithLegal(oppThreats, legalMoves);
            if (columnToPlay.HasValue)
            {
                return(columnToPlay.Value);
            }

            //are there hidden forks for player 1?
            //look for threats with 2 blanks
            var forkThreats = search.FindGroups(1, board, 2);
            //do any threats share a blank?
            var forkPositions = new List <Position>();

            for (var i = 0; i < forkThreats.Count; i++)
            {
                var ft     = forkThreats[i];
                var blanks = ft.Coords.Where(c => c.Mark == 0);

                for (var j = 0; j < forkThreats.Count; j++)
                {
                    if (j == i)
                    {
                        continue;
                    }

                    var jft     = forkThreats[j];
                    var jBlanks = jft.Coords.Where(c => c.Mark == 0);

                    var shared = jBlanks.Intersect <Position>(blanks, new PositionEqualityComparer());
                    forkPositions.AddRange(shared);
                }
            }

            //are any blanks legal moves?
            columnToPlay = MatchPositionsThreatsWithLegal(forkPositions, legalMoves);
            if (columnToPlay.HasValue)
            {
                return(columnToPlay.Value);
            }

            //should we remove a legal move if it will harm us?
            //can player1 score after this move?
            //take all legal moves and transpose one row up - do any fulfill player 1 threats?
            var toRemove = new List <Position>();

            foreach (var legalMove in legalMoves)
            {
                var transposedMove = new Position(legalMove.Row + 1, legalMove.Col, 0);
                foreach (var threat in oppThreats)
                {
                    var blank = threat.Coords.Single(t => t.Mark == 0);
                    if (blank.Equals(transposedMove))
                    {
                        toRemove.Add(legalMove);
                    }
                }
            }

            toRemove.ForEach(r => legalMoves.Remove(r));

            //claimeven
            var claimevens = search.FindPossibleClaimEvens(board);

            foreach (var claimEven in claimevens)
            {
                foreach (var move in legalMoves)
                {
                    if (claimEven == move.Col)
                    {
                        return(claimEven);
                    }
                }
            }

            var moveIndex = random.Next(0, legalMoves.Count());

            return(legalMoves[moveIndex].Col);
        }