public void VerifyDoubleTurn() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new string[9] { "O", "?", "X", "X", "?", "?", "O", "O", "?" } }; try { ExecuteMoveResponse response = client.ExecuteMove(body); // Fail if an HttpOperationException is not thrown Assert.IsTrue(false); } catch (HttpOperationException error) { Assert.AreEqual(HttpStatusCode.BadRequest, error.Response.StatusCode); Assert.IsTrue(error.Response.Content.Equals("\"There should be less AzurePlayerSymbols than humanPlayerSymbols on the gameBoard\"")); } }
public void VerifyEmptyBoard() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new string[9] { "?", "?", "?", "?", "?", "?", "?", "?", "?" } }; ExecuteMoveResponse response = client.ExecuteMove(body); // Verify that Azure took the first move var azurePlayerSymbolCount = response.GameBoard .Select((value, index) => new { value, index }) .Where((tile) => tile.value.Equals(body.AzurePlayerSymbol)) .Select((tile) => tile.index) .ToArray() .Length; Assert.AreEqual(1, azurePlayerSymbolCount); }
public void VerifyLargerGameBoardLength() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new string[12] { "X", "?", "X", "X", "O", "?", "X", "O", "?", "X", "O", "?" } }; try { ExecuteMoveResponse response = client.ExecuteMove(body); // Fail if an HttpOperationException is not thrown Assert.IsTrue(false); } catch (HttpOperationException error) { Assert.AreEqual(HttpStatusCode.BadRequest, error.Response.StatusCode); Assert.IsTrue(error.Response.Content.Equals("\"gameboard must have a length of 9 (0 - 8)\"")); } }
public void VerifyGameBoardImbalance() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new string[9] { "X", "?", "?", "O", "?", "?", "X", "X", "?", } }; try { ExecuteMoveResponse response = client.ExecuteMove(body); // Fail if an HttpOperationException is not thrown Assert.IsTrue(false); } catch (HttpOperationException error) { Assert.AreEqual(HttpStatusCode.BadRequest, error.Response.StatusCode); Assert.IsTrue(error.Response.Content.Equals("\"The difference in symbol counts should be no greater than 1\"")); } }
public void VerifySamePlayerSymbols() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "X", HumanPlayerSymbol = "X", GameBoard = new string[9] { "O", "?", "X", "X", "O", "?", "O", "?", "?" } }; try { ExecuteMoveResponse response = client.ExecuteMove(body); // Fail if an HttpOperationException is not thrown Assert.IsTrue(false); } catch (HttpOperationException error) { Assert.AreEqual(HttpStatusCode.BadRequest, error.Response.StatusCode); Assert.IsTrue(error.Response.Content.Equals("\"azurePlayerSymbol and humanPlayerSymbol must be opposites\"")); } }
public void VerifyInvalidGameBoardSymbols() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new string[9] { "U", "?", "X", "X", "O", "?", "O", "?", "?" } }; try { ExecuteMoveResponse response = client.ExecuteMove(body); // Fail if an HttpOperationException is not thrown Assert.IsTrue(false); } catch (HttpOperationException error) { Assert.AreEqual(HttpStatusCode.BadRequest, error.Response.StatusCode); Assert.IsTrue(error.Response.Content.Equals("\"gameBoard can only contain 'X', 'O', or '?'\"")); } }
public void VerifyAzureOSymbol() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new string[9] { "X", "?", "X", "X", "O", "?", "O", "?", "?" } }; ExecuteMoveResponse response = client.ExecuteMove(body); // AzurePlayerSymbol is set to O, // verify that the API added another // O to the game board. var xIndicies = response.GameBoard .Select((value, index) => new { value, index }) .Where((tile) => tile.value.Equals("O")) .Select((tile) => tile.index) .ToArray(); Assert.AreEqual(3, xIndicies.Length); }
public async Task OPlayerWinTestAsync() // Validate that the application properly detects a human player "O" victory { //�Arrange ExecuteMove payload = new ExecuteMove() { Move = 1, AzurePlayerSymbol = "X", HumanPlayerSymbol = "O", GameBoard = new List <string> { "X", "O", "X", "?", "O", "?", "?", "O", "?" } }; // Act HttpOperationResponse <object> resultObject = await _client.ExecuteMoveResponseWithHttpMessagesAsync(payload); ExecuteMoveResponse resultPayload = resultObject.Body as ExecuteMoveResponse; // Assert if (resultObject != null) { Assert.AreEqual(resultPayload.Winner, "O"); } else { Assert.Fail("Expected an ExecuteMoveResponse but didn't recieve one."); } }
[ProducesResponseType(typeof(int), StatusCodes.Status400BadRequest)] // Tells swagger that the response format will be an int for a BadRequest (400) public ActionResult <ExecuteMoveResponse> ExecuteMoveResponse([FromBody] ExecuteMove inputPayload) { if (PayloadValidation.ValidatePayload(inputPayload) == false) { return(BadRequest(4)); } ExecuteMoveResponse response = CalculateResponse.CalculateMoveResponse(inputPayload); return(response); }
public void VerifyInconclusive() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "X", HumanPlayerSymbol = "O", GameBoard = new string[9] { "O", "?", "O", "O", "X", "?", "X", "?", "?" } }; ExecuteMoveResponse response = client.ExecuteMove(body); Assert.AreEqual("inconclusive", response.Winner); Assert.IsNull(response.WinPositions); Assert.IsNotNull(response.Move); }
public async Task ValidResponseTestAsync() // Validates that the ExecuteMove Response is properly formatted // Validate that the Azure and Human player symbols are either "X" or "O" and are not the same. { //�Arrange ExecuteMove payload = new ExecuteMove() { Move = 2, AzurePlayerSymbol = "O", HumanPlayerSymbol = "X", GameBoard = new List <string> { "X", "O", "X", "O", "?", "?", "?", "?", "?" } }; // Act HttpOperationResponse <object> resultObject = await _client.ExecuteMoveResponseWithHttpMessagesAsync(payload); ExecuteMoveResponse resultPayload = resultObject.Body as ExecuteMoveResponse; // Assert if (resultObject != null) { // Validate that the Azure and Human player symbols are either "X" or "O" and are not the same. Assert.IsTrue(resultPayload.AzurePlayerSymbol == "O" || resultPayload.AzurePlayerSymbol == "X"); Assert.IsTrue(resultPayload.HumanPlayerSymbol == "O" || resultPayload.HumanPlayerSymbol == "X"); Assert.AreNotEqual(resultPayload.AzurePlayerSymbol, resultPayload.HumanPlayerSymbol); // Validate that the gameBoard is the proper size and all values are 'X', 'O', or '?' Assert.AreEqual(resultPayload.GameBoard.Count, 9); for (int i = 0; i < resultPayload.GameBoard.Count; i++) { Assert.IsTrue(resultPayload.GameBoard[i] == "X" || resultPayload.GameBoard[i] == "O" || resultPayload.GameBoard[i] == "?"); } } else { Assert.Fail("Expected an ExecuteMoveResponse but didn't recieve one."); } }
public void VerifyPlayerOWinner() { MessagePayload body = new MessagePayload() { Move = 0, AzurePlayerSymbol = "X", HumanPlayerSymbol = "O", GameBoard = new string[9] { "O", "X", "?", "O", "X", "?", "O", "?", "?" } }; ExecuteMoveResponse response = client.ExecuteMove(body); Assert.AreEqual("O", response.Winner); Assert.IsTrue(new List <int?>() { 0, 3, 6 }.SequenceEqual(response.WinPositions)); Assert.AreEqual(null, response.Move); }
public static ExecuteMoveResponse CalculateMoveResponse(ExecuteMove messagePayload) // Calculates { int[,] victoryConditions = new int[8, 3] // Defines all 8 possible winning combinations in Tic Tac Toe { { 0, 1, 2 }, { 0, 3, 6 }, { 0, 4, 8 }, { 1, 4, 7 }, { 2, 4, 6 }, { 2, 5, 8 }, { 3, 4, 5 }, { 6, 7, 8 } }; string[,] gameState = new string[8, 3] // Tracks player positions against possible victories { { "0", "1", "2" }, { "0", "3", "6" }, { "0", "4", "8" }, { "1", "4", "7" }, { "2", "4", "6" }, { "2", "5", "8" }, { "3", "4", "5" }, { "6", "7", "8" } }; //========== 1. SET UP THE GAME BOARD ========== // This section sets Human/Azure positions on an array called "gameState". It also checks if the Human has won or the game is tied. // (We can assume Azure has not won before making its move.) // Prepare known elements of Azure's response ExecuteMoveResponse response = new ExecuteMoveResponse() { azurePlayerSymbol = messagePayload.azurePlayerSymbol, humanPlayerSymbol = messagePayload.humanPlayerSymbol, gameBoard = messagePayload.gameBoard }; // Creates two lists: for gameBoard human and azure player positions List <int> humanPositions = new List <int>(); List <int> azurePositions = new List <int>(); for (int i = 0; i < messagePayload.gameBoard.Length; i++) { if (messagePayload.gameBoard[i] == messagePayload.humanPlayerSymbol) { humanPositions.Add(i); } else if (messagePayload.gameBoard[i] == messagePayload.azurePlayerSymbol) { azurePositions.Add(i); } } // Compare gameState to humanPositions. // Replace any values in gameState with humanSymbol if they match (indicating that the human owns that space) string humanSymbol = messagePayload.humanPlayerSymbol.ToString(); foreach (int i in humanPositions) { for (int row = 0; row < gameState.GetLength(0); row++) { for (int column = 0; column < gameState.GetLength(1); column++) { if (i.ToString() == gameState[row, column]) { gameState[row, column] = humanSymbol; } } // Check to see if the human has met any of the victory conditions if (gameState[row, 0] == humanSymbol && gameState[row, 1] == humanSymbol && gameState[row, 2] == humanSymbol) { response.winner = humanSymbol; // Set winPositions response.winPositions = new int[3]; for (int j = 0; j < 3; j++) { response.winPositions[j] = victoryConditions[row, j]; } return(response); } } } // Check for a tie game resulting from Player's move if (Array.IndexOf(messagePayload.gameBoard, '?') == -1) { response.winner = "tie"; return(response); } // Compare gameState to azurePositions. // Replace any values in gameState with azureSymbol if they match (indicating that Azure owns that space) string azureSymbol = messagePayload.azurePlayerSymbol.ToString(); foreach (int i in azurePositions) { for (int row = 0; row < gameState.GetLength(0); row++) { for (int column = 0; column < gameState.GetLength(1); column++) { if (i.ToString() == gameState[row, column]) { gameState[row, column] = azureSymbol; } } } } //========== 2. CALCULATE AZURE'S MOVE ========== // This section calculate's Azure's next move and checks if that move results in a win or tie. // Look for any possible winning moves or blocking moves for (int row = 0; row < gameState.GetLength(0); row++) { string[] gameStateRow = { gameState[row, 0], gameState[row, 1], gameState[row, 2] }; // Winning moves int?winningMove = WinBlock(gameStateRow, azureSymbol, humanSymbol); if (winningMove != null) { response.move = winningMove; response.gameBoard[(int)winningMove] = messagePayload.azurePlayerSymbol; response.winner = azureSymbol; response.winPositions = new int[3]; for (int j = 0; j < 3; j++) { response.winPositions[j] = victoryConditions[row, j]; } return(response); } // Blocking moves int?blockingMove = WinBlock(gameStateRow, humanSymbol, azureSymbol); if (blockingMove != null) { response.move = blockingMove; response.gameBoard[(int)blockingMove] = messagePayload.azurePlayerSymbol; } } // If no winning or blocking moves have been found, select the first available move from a predetermined order of priority if (response.move == null) { int[] movePriority = { 4, 8, 6, 2, 0, 7, 5, 3, 1 }; List <int> occupiedPositions = humanPositions.Concat(azurePositions).ToList(); for (int i = 0; i < movePriority.Length; i++) { if (occupiedPositions.IndexOf(movePriority[i]) == -1) { response.move = movePriority[i]; response.gameBoard[movePriority[i]] = messagePayload.azurePlayerSymbol; break; } } } // Check for a tie game resulting from Azure's move if (Array.IndexOf(messagePayload.gameBoard, '?') == -1) { response.winner = "tie"; return(response); } response.winner = "inconclusive"; return(response); }