protected void VictoryConfirmed(DiscColor winner) { if (winner != DiscColor.None) { ShowPlayAgainMenu(winner); } else { if (BitBoardHelpers.GetOpenColumns(GetBitBoard()).Count == 0) { ShowPlayAgainDrawnMenu(); } } }
/// <summary> /// Prompts bot to calculate move in the background /// and updates game state accordingly after. /// </summary> protected async Task GetBotMoveAsync() { int botMove = await Task.Run(() => Bot.Move()); if (botMove == -1) { throw new InvalidOperationException("The bot did not return a valid column."); } _boardColumns[botMove].SetSpace(BotTurn); ChangeTurn(); var winner = BitBoardHelpers.CheckVictory(GetBitBoard()); VictoryConfirmed(winner); _botThinking = false; }
/// <summary> /// Returns the current column's state represented /// in the first six positions of a BitBoard. These bits /// should be shifted according to the columns position /// and then OR'ed to get the board position. /// </summary> // TODO unit tests around this public BitBoard GetBitColumn() { ulong redDiscs = 0; ulong blackDiscs = 0; for (int row = 0; row < LogicalBoardHelpers.NUM_ROWS; row++) { if (GetSpace(row) == DiscColor.Red) { redDiscs = BitBoardHelpers.SetSingleBit(redDiscs, row); } else if (GetSpace(row) == DiscColor.Black) { blackDiscs = BitBoardHelpers.SetSingleBit(blackDiscs, row); } else { break; } } return(new BitBoard(redDiscs, blackDiscs)); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) { EndGame(); } _timeSinceLastMove += gameTime.ElapsedGameTime.TotalSeconds; // TODO should this be a seperate method? // Handle user clicks that could be attempted moves. // Contain mouse will not allow clicks on a full column. LastMouseState = MouseState; MouseState = Mouse.GetState(); Point mousePosition = new Point(MouseState.X, MouseState.Y); switch (CurrentMenu) { case MenuState.Start: if (LastMouseState.LeftButton == ButtonState.Pressed && MouseState.LeftButton == ButtonState.Released) { if (_startMenu.BlackDiscContainsMouse(mousePosition)) { SetGameColors(DiscColor.Black); break; } else if (_startMenu.RedDiscContainsMouse(mousePosition)) { SetGameColors(DiscColor.Red); break; } } break; case MenuState.None: // Check for movement clicks if (_timeSinceLastMove > 0.5) { if (CurrentTurn == PlayerTurn) { for (int col = 0; col < NUM_COLUMNS; col++) { if (_boardColumns[col].ContainMouse(mousePosition)) { _boardColumns[col].IsFocused = true; if (LastMouseState.LeftButton == ButtonState.Pressed && MouseState.LeftButton == ButtonState.Released) { //Perform move and change turn. _boardColumns[col].SetSpace(PlayerTurn); _boardColumns[col].IsFocused = false; _timeSinceLastMove = 0.0; ChangeTurn(); var winner = BitBoardHelpers.CheckVictory(GetBitBoard()); VictoryConfirmed(winner); UpdateBotBoard(); } } else { _boardColumns[col].IsFocused = false; } } } else if (CurrentTurn == BotTurn) { if (!_botThinking) { _botThinking = true; GetBotMoveAsync(); } } } break; case MenuState.PlayAgain: case MenuState.PlayAgainDrawn: // Detect a click on either of the buttons and respond accordingly. if (LastMouseState.LeftButton == ButtonState.Pressed && MouseState.LeftButton == ButtonState.Released) { if (_playAgainMenu.YesButtonContainsMouse(mousePosition)) { ResetGame(); break; } else if (_playAgainMenu.NoButtonContainsMouse(mousePosition)) { EndGame(); break; } } break; } base.Update(gameTime); }