public async Task <GameSolution> SolveGameAsync(GameState initialGameState, CancellationToken cancellationToken = default(CancellationToken)) { return(await Task.Run(() => { HashSet <GameState> gameStates = new HashSet <GameState>(); Queue <GameState> gameStatesToProcess = new Queue <GameState>(); IWordStateMachine wordStateMachine = this.wordStateMachineFactory.GetWordStateMachine(); gameStates.Add(initialGameState); gameStatesToProcess.Enqueue(initialGameState); while (gameStatesToProcess.Count != 0) { cancellationToken.ThrowIfCancellationRequested(); var currentGameState = gameStatesToProcess.Dequeue(); foreach (var newGameState in CreateGameStates(currentGameState, wordStateMachine)) { if (gameStates.Add(newGameState)) { gameStatesToProcess.Enqueue(newGameState); } } } return new GameSolution(gameStates.Where(gameState => IsGameStateFinal(gameState))); })); }
private IEnumerable <GameState> CreateGameStates(GameState gameState, IWordStateMachine wordStateMachine) { for (int index = 0; index < gameState.OccupationField.Length; index++) { GamePoint startGamePoint = new GamePoint(gameState.GameInformation, index); wordStateMachine.Reset(); if (wordStateMachine.CanNavigateForward(startGamePoint.ToChar()) && !gameState.OccupationField[startGamePoint.Index]) { TemporaryGameState temporaryGameState = new TemporaryGameState(gameState, startGamePoint, wordStateMachine); foreach (var newGameState in CreateGameStates(temporaryGameState)) { yield return(newGameState); } } } }
public TemporaryGameState(GameState initialGameState, GamePoint initialPoint, IWordStateMachine wordStateMachine) { this.wordStateMachine = wordStateMachine; this.wordStateMachine.Reset(); this.wordStateMachine.NavigateForward(initialPoint.ToChar()); this.gamePoints = new Stack <GamePoint>(); this.gamePoints.Push(initialPoint); this.GameInformation = initialGameState.GameInformation; this.GameState = initialGameState; this.InitialPoint = initialPoint; this.currentPoint = initialPoint; this.occupationField = new BitArray(initialGameState.OccupationField) { [currentPoint.Index] = true }; }