private void StartGame() { //Play the preparation music soundPlayer.Stream = Properties.Resources.Preparation; soundPlayer.Play(); //Prompt the player for the difficulty of the match DifficultyPrompt diffPrompt = new DifficultyPrompt(); diffPrompt.ShowDialog(); //Create a new "game" currentGame = new Game((Difficulty)diffPrompt.selectedDifficulty); //Let the player choose the piece they wish to be, and assign it PiecePrompt piecePrompt = new PiecePrompt(); piecePrompt.ShowDialog(); currentGame.PlayerPiece = piecePrompt.selectedPiece; //Create a new AI player, and assign it the piece opposite of the player currentGame.aiPlayer = new AI(); currentGame.aiPlayer.AIPiece = Game.GetOppositePiece(currentGame.PlayerPiece); currentGame.AIPiece = currentGame.aiPlayer.AIPiece; //Determine who goes first DiceRollPrompt diceRoll = new DiceRollPrompt(); diceRoll.ShowDialog(); currentGame.CurrentPlayer = diceRoll.firstToGo; //Start the game currentGame.GameStarted = true; currentGame.GameState = Game.State.Playing; //Start the game timers gameTimer.Start(); countdownTimer.Start(); //Play battle music soundPlayer.Stop(); soundPlayer.Stream = Properties.Resources.BattleMusic; soundPlayer.PlayLooping(); }
private void StartGame() { //Create a new "game" currentGame = new Game(matchDifficulty[matchIndex]); //Repaint the grid RepaintGame(); //Determine if this is the champion match championMatchStarted = (matchIndex + 1 == NUMBER_OF_T_MATCHES) ? true : false; //Display the proper round roundLabel.Text = (championMatchStarted) ? "Final Round" : "Round " + (matchIndex + 1); //Assign the player's piece currentGame.PlayerPiece = playerPiece; //Create a new AI player, and assign it the piece opposite of the player currentGame.aiPlayer = new AI(); currentGame.aiPlayer.AIPiece = Game.GetOppositePiece(currentGame.PlayerPiece); currentGame.AIPiece = currentGame.aiPlayer.AIPiece; //Determine who goes first DiceRollPrompt diceRoll = new DiceRollPrompt(); if (championMatchStarted) { //Change the controls and time the music for the reveal of the champion if (!championMusicPlayed) { soundPlayer.Stop(); } diceRoll.Controls["aiNameLabel"].Text = "Champion"; PictureBox pb = diceRoll.Controls["aiPictureBox"] as PictureBox; pb.Image = Properties.Resources.championai; } diceRoll.ShowDialog(); currentGame.CurrentPlayer = diceRoll.firstToGo; //Start the game currentGame.GameStarted = true; currentGame.GameState = Game.State.Playing; //Start the game timers gameTimer.Start(); countdownTimer.Start(); //Play champion music for last fight, and set up champion profile if (!championMusicPlayed && championMatchStarted) { soundPlayer.Stop(); soundPlayer.Stream = Properties.Resources.ChampionMusic; soundPlayer.PlayLooping(); championMusicPlayed = true; aiNameLabel.Text = "The Champion"; aiPictureBox.Image = Properties.Resources.championai; } //Only battle music at beginning else if (!battleMusicPlayed) { soundPlayer.Stop(); soundPlayer.Stream = Properties.Resources.BattleMusic; soundPlayer.PlayLooping(); battleMusicPlayed = true; } }
/* * A little explanation here: The normal AI's priority is to build as much matches * as possible, completely ignoring the player. It will place the piece in * a row/column/diagonal with the most matches. For example, a diagonal with two cells * occupied and an empty third one will override a row with one cell occupied. The AI * ignores any row/column/diagonal block off by the player. This same concept is used * throughout this loop. */ private void CalculateNormalMove(ref Board board) { //The amount of matches of the AI's piece int matches = 0; //Coordinates and piecePlaced flag Vector2D cellCoord = new Vector2D(0, 0); bool piecePlaced = false; while (!piecePlaced) { //Check row for (int row = 0; row < board.Grid.GetLength(0); row++) { int colMatches = CheckHorizontal(ref board, AIPiece, row); int playerColMatches = CheckHorizontal(ref board, Game.GetOppositePiece(AIPiece), row); //If the row has not been blocked by the player, and the matches in this row is greater //than any matches found previously, then we use this row. This is the same throughout the //other checks. if (playerColMatches == 0 && colMatches > matches) { //This is now the new highest match. matches = colMatches; //Get the free cell in this row cellCoord = GetFreeCellRow(ref board, row); //Flag the piece as placed. piecePlaced = true; } } //Check column for (int col = 0; col < board.Grid.GetLength(1); col++) { int rowMatches = CheckVertical(ref board, AIPiece, col); int playerRowMatches = CheckVertical(ref board, Game.GetOppositePiece(AIPiece), col); if (playerRowMatches == 0 && rowMatches > matches) { matches = rowMatches; cellCoord = GetFreeCellCol(ref board, col); piecePlaced = true; } } //Gets the smallest of the row or column, as that will give the number of diagonal cells. int diagonalSpaces = (board.Grid.GetLength(0) < board.Grid.GetLength(1)) ? board.Grid.GetLength(0) : board.Grid.GetLength(1); //Check the left diagonal for matches int leftDiagMatches = CheckLeftDiagonal(ref board, AIPiece); if (CheckLeftDiagonal(ref board, Game.GetOppositePiece(AIPiece)) == 0 && leftDiagMatches > matches) { matches = leftDiagMatches; cellCoord = GetFreeCellLeftDiag(ref board, diagonalSpaces); piecePlaced = true; } //Check the right diagonal for matches int rightDiagMatches = CheckRightDiagonal(ref board, AIPiece); if (CheckRightDiagonal(ref board, Game.GetOppositePiece(AIPiece)) == 0 && rightDiagMatches > matches) { matches = rightDiagMatches; cellCoord = GetFreeCellRightDiag(ref board, diagonalSpaces); piecePlaced = true; } //If we can not find a move, the AI defaults to Easy AI. if (!piecePlaced) { piecePlaced = true; CalculateEasyMove(ref board); } else { //Place the piece down. board.Grid[cellCoord.x, cellCoord.y].CellPiece = AIPiece; } } }
/* * A step up from Normal, this now checks for if the player is about to win. * If so, the AI will sabotage them. It will, however, prioritize itself first. * If it's about to get a row/column/diagonal of full matches, it will do that instead, * hence the selfVictory flag. The only weakness of this AI is that a smart player can * devise a strategy that can create two openings for the player to win in one turn, as the AI can * only block one of them. */ private void CalculateAdvancedMove(ref Board board) { //Stores the coordinate of where the piece is to be placed Vector2D cellCoord = new Vector2D(0, 0); //Whether a piece has been placed or not bool piecePlaced = false; //Whether the AI has chosen a move the will ensure victory bool selfVictory = false; while (!piecePlaced) { //Check row for whether AI can win in next move, then whether player win in next move int rowLength = board.Grid.GetLength(0); for (int row = 0; row < rowLength; row++) { int colMatches = CheckHorizontal(ref board, AIPiece, row); int playerColMatches = CheckHorizontal(ref board, Game.GetOppositePiece(AIPiece), row); //Checks whether the AI will win first, then whether or not the player will win in the next move //Notice that this checks whether or not the AI is one move away from winning, and whether the last slot of the row is free if (colMatches == rowLength - 1 && playerColMatches == 0) { cellCoord = GetFreeCellRow(ref board, row); piecePlaced = true; selfVictory = true; break; } //This checks the same thing as the previous if statement, but with the player. //This is the part that the AI determines whether or not it should block the player else if (!selfVictory && playerColMatches == rowLength - 1 && colMatches == 0) { cellCoord = GetFreeCellRow(ref board, row); piecePlaced = true; } } //Check column for self win, then player win int colLength = board.Grid.GetLength(1); for (int col = 0; col < colLength; col++) { int rowMatches = CheckVertical(ref board, AIPiece, col); int playerRowMatches = CheckVertical(ref board, Game.GetOppositePiece(AIPiece), col); //Checks whether the AI will win first, then whether or not the player will win in the next move if (rowMatches == colLength - 1 && playerRowMatches == 0) { cellCoord = GetFreeCellCol(ref board, col); piecePlaced = true; selfVictory = true; break; } else if (!selfVictory && playerRowMatches == colLength - 1 && rowMatches == 0) { cellCoord = GetFreeCellCol(ref board, col); piecePlaced = true; } } //Determine the amount of diagonal spaces int diagonalSpaces = (board.Grid.GetLength(0) < board.Grid.GetLength(1)) ? board.Grid.GetLength(0) : board.Grid.GetLength(1); //Check the left diagonal for self win, then player. int lDiagMatches = CheckLeftDiagonal(ref board, AIPiece); int playerLDiagMatches = CheckLeftDiagonal(ref board, Game.GetOppositePiece(AIPiece)); if (lDiagMatches == diagonalSpaces - 1 && playerLDiagMatches == 0) { cellCoord = GetFreeCellLeftDiag(ref board, diagonalSpaces); piecePlaced = true; selfVictory = true; } else if (!selfVictory && playerLDiagMatches == diagonalSpaces - 1 && lDiagMatches == 0) { cellCoord = GetFreeCellLeftDiag(ref board, diagonalSpaces); piecePlaced = true; } //Check the right diagonal for self win, then player. int rDiagMatches = CheckRightDiagonal(ref board, AIPiece); int playerRDiagMatches = CheckRightDiagonal(ref board, Game.GetOppositePiece(AIPiece)); if (rDiagMatches == diagonalSpaces - 1 && playerRDiagMatches == 0) { cellCoord = GetFreeCellRightDiag(ref board, diagonalSpaces); piecePlaced = true; selfVictory = true; } else if (!selfVictory && playerRDiagMatches == diagonalSpaces - 1 && rDiagMatches == 0) { cellCoord = GetFreeCellRightDiag(ref board, diagonalSpaces); piecePlaced = true; } //If a piece still isn't placed, we default to the Normal AI. if (!piecePlaced) { piecePlaced = true; CalculateNormalMove(ref board); break; } else { //Place the piece down. board.Grid[cellCoord.x, cellCoord.y].CellPiece = AIPiece; break; } } }