public Othello( ) { InitializeComponent( ); //Initialize the lists in squaresOf squaresOf[Players.Black] = new List<Square>( ); squaresOf[Players.White] = new List<Square>( ); squaresOf[Players.Empty] = new List<Square>( ); //Initialize the squares and the buttons and set their properties. for (int left = 0; left < 8; left++) { //For each column for (int top = 0; top < 8; top++) { //For each row Square squareToCreate = new Square(left, top); squares[left, top] = squareToCreate; //Add square to squares squareToCreate.PlayerChanged += OnPlayerChanged; //Set the PlayerChanged event to OnPlayerChanged Button buttonToCreate = new Button( ) { Size = buttonSize, //Position the button so that it is right of the square left of it and below the square on top of it. Left = left * buttonSize.Width, Top = top * buttonSize.Height, BackColor = Pens.Green.Color, //Set the color to green Tag = squareToCreate //The tag of each button should be the corresponding square. }; buttonToCreate.Paint += button_Paint; buttonToCreate.Click += button_Click; buttons[left, top] = buttonToCreate; //Add button to buttons Controls.Add(buttonToCreate); squaresOf[Players.Empty].Add(squareToCreate); } } squares[3, 3].Player = squares[4, 4].Player = Players.White; //The square to the top-left and bottom-right of the center of the board should start out white squares[4, 3].Player = squares[3, 4].Player = Players.Black; //The square to the top-right and bottom-left of the center of the board should start out black. }
/// <summary> /// Groups the squares by player. /// </summary> /// <param name="squares">A list of the squares in the board.</param> /// <returns>A dictionary where the key is the player and the value is a list the squares belonging to that player.</returns> public static Dictionary<Players, List<Square>> GroupSquares(Square[,] squares) { Dictionary<Players, List<Square>> retVal = new Dictionary<Players, List<Square>>( ); //Initialize the lists. retVal[Players.Black] = new List<Square>( ); retVal[Players.White] = new List<Square>( ); retVal[Players.Empty] = new List<Square>( ); //Add each square to the appropriate list. foreach (Square item in squares) { retVal[item.Player].Add(item); } return retVal; }
/// <summary> /// Returns the squares that would be flipped had the specified player choosen the specified square. /// </summary> /// <param name="squareToTest">The square that would have caused the squares to be flipped.</param> /// <param name="playerToTest"></param> /// <returns>A list of the squares that would be flipped had the specified </returns> public static List<Square> SquaresFlipped(Square[,] squares, Square squareToTest, Players playerToTest) { Dictionary<Players, List<Square>> squaresOf = GroupSquares(squares); List<Square> retVal = new List<Square>( ); //For each square that playerToTest owns, add all squares between it and squareToTest if there are no squares that does not belong to his opponent among those squares. foreach (Square cSquare in squaresOf[playerToTest]) { if (cSquare == squareToTest) continue; List<Square> squaresBetween = SquaresBetween(squares, squareToTest, cSquare); if (squaresBetween.Any(square => square.Player != Opponent(playerToTest))) //If any of the squares in squaresBetween do not belong to playerToTest's opponent then do not add anything to retVal. If squaresBetween contains squares that should be flipped then they will be added when the loop is up to the nearest square that belongs to playerToTest continue; else retVal.AddRange(squaresBetween); } return retVal; }
/// <summary> /// Returns the squares between the two specified squares. /// </summary> /// <param name="squares">An array of the squares in the board</param> /// <param name="firstSquare"></param> /// <param name="secondSquare"></param> /// <returns></returns> public static List<Square> SquaresBetween(Square[,] squares, Square firstSquare, Square secondSquare) { List<Square> retVal = new List<Square>( ); //If no squares can are between firstSquare and secondSquare because first square and secondSquare are not is the same row or column and are not across from eachother if (!(firstSquare.Left == secondSquare.Left || firstSquare.Top == secondSquare.Top //If both squares are not in the same row or column || Math.Abs(firstSquare.Left - secondSquare.Left) == Math.Abs(firstSquare.Top - secondSquare.Top))) //and are not across from eachother return retVal; //Return retval, which is empty else { //For every square between firstSquare and secondSquare, add it to retVal for (int x = firstSquare.Left, y = firstSquare.Top; x != secondSquare.Left || y != secondSquare.Top; //Until leftCounter and rightCounter refer to secondSquare x += Math.Sign(secondSquare.Left - firstSquare.Left), //If secondSquare.Left is greater than firstSquare.Left then increments leftCounter and adds the square to the left (closer to secondSquare) to retVal. If secondSquare.Left equals firstSquare.Left then leftCounter remains unchanged and the square above or below the previous square is added to retVal. If secondSquare.Left is less than firstSquare.Left then leftCounter is decremented. y += Math.Sign(secondSquare.Top - firstSquare.Top)) { Square squareToAdd = squares[x, y]; if (squareToAdd != firstSquare && squareToAdd != secondSquare) retVal.Add(squares[x, y]); } return retVal; } }
private void OnPlayerChanged(Square sender, Players oldValue) { buttons[sender.Left, sender.Top].Invalidate( ); //Invalidate the control so that the circle in the control is redrawn based on the new value of sender.Player //Modify the appropriate lists. squaresOf[oldValue].Remove(sender); //Remove the square from the list that it used to be in squaresOf[sender.Player].Add(sender); //Add the square to the list that it should now be in blackScore.Text = squaresOf[Players.Black].Count.ToString( ); //Update the text of the status bar to show the number of squares that belong to each player. whiteScore.Text = squaresOf[Players.White].Count.ToString( ); }