【问题标题】:Checking for winner in TicTacToe?检查井字游戏的赢家?
【发布时间】:2009-04-11 17:24:01
【问题描述】:

查看(2 人)井字游戏获胜的最佳方式是什么?现在我正在使用类似于以下内容的东西:

if (btnOne.Text == "X" && btnTwo.Text == "X" && btnThree.Text == "X")
{
    MessageBox.Show("X has won!", "X won!");
    return;
}
else
// I'm not going to write the rest but it's really just a bunch
// if statements.

那么我该如何摆脱多重 if 呢?

【问题讨论】:

    标签: c# if-statement


    【解决方案1】:

    有些东西:

    rowSum == 3 || columnSum == 3 || diagnolSum == 3
    

    .. ?

    【讨论】:

    • 不错的更新,我想我可能会采用这种方法,但我会留下未回答的问题,看看是否有其他人能想出更好的东西(我们必须让他们有机会,对吧? )。
    • 提取到另一个答案帖中。
    • 这决定比赛结束但不区分队伍。
    【解决方案2】:

    如果将按钮存储在多维数组中,则可以编写一些扩展方法来获取行、列和对角线。

    public static class MultiDimensionalArrayExtensions
    {
      public static IEnumerable<T> Row<T>(this T[,] array, int row)
      {
        var columnLower = array.GetLowerBound(1);
        var columnUpper = array.GetUpperBound(1);
    
        for (int i = columnLower; i <= columnUpper; i++)
        {
          yield return array[row, i];
        }
      }
    
      public static IEnumerable<T> Column<T>(this T[,] array, int column)
      {
        var rowLower = array.GetLowerBound(0);
        var rowUpper = array.GetUpperBound(0);
    
        for (int i = rowLower; i <= rowUpper; i++)
        {
          yield return array[i, column];
        }
      }
    
      public static IEnumerable<T> Diagonal<T>(this T[,] array,
                                               DiagonalDirection direction)
      {
        var rowLower = array.GetLowerBound(0);
        var rowUpper = array.GetUpperBound(0);
        var columnLower = array.GetLowerBound(1);
        var columnUpper = array.GetUpperBound(1);
    
        for (int row = rowLower, column = columnLower;
             row <= rowUpper && column <= columnUpper;
             row++, column++)
       {
          int realColumn = column;
          if (direction == DiagonalDirection.DownLeft)
            realColumn = columnUpper - columnLower - column;
    
          yield return array[row, realColumn];
        }
      }
    
      public enum DiagonalDirection
      {
        DownRight,
        DownLeft
      }
    }
    

    如果您使用具有 3 行和 3 列的 TableLayoutPanel,您可以轻松地以可编程方式创建按钮并将其存储到 Button[3, 3] 数组中。

    Button[,] gameButtons = new Button[3, 3];
    
    for (int row = 0; column <= 3; row++)
      for (int column = 0; column <= 3; column++)
      {
        Button button = new Button();
        // button...
        gameLayoutPanel.Items.Add(button);
        gameButtons[row, column] = button;
      }
    

    并检查获胜者:

    string player = "X";
    Func<Button, bool> playerWin = b => b.Value == player;
    gameButtons.Row(0).All(playerWin) ||
    // ...
    gameButtons.Column(0).All(playerWin) ||
    // ...
    gameButtons.Diagonal(DiagonalDirection.DownRight).All(playerWin) ||
    // ...
    

    【讨论】:

      【解决方案3】:

      另一种简单的方法是将可获胜的位置保存为数组中的数据,并使用循环检查所有可能的获胜条件,而不是使用多个 ifs 语句

      // winnable positions
      var winnables = new[] {
          "012",
          "345",
          "678",
          "036",
          "147",
          "258",
          "048",
          "246"
      };
      
      // extracted from btnOne Two Three....
      var gameState = new[] { "X", "O", "X", "whatever" };
      
      
      string winner = null;
      
      // check each winnable positions
      foreach (var position in winnables) {
      
          var pos1 = int.Parse(position[0].ToString());
          var pos2 = int.Parse(position[1].ToString());
          var pos3 = int.Parse(position[2].ToString());
      
          if (gameState[pos1] == gameState[pos2] &&
              gameState[pos2] == gameState[pos3])
              winner = gameState[pos1];
      
      }
      
      // do we have a winner?
      if (!string.IsNullOrEmpty(winner))
          /* we've got a winner */
      

      基本上,不要使用 btnOne btnTwo btnThree,使用适当的 Button 数组或以更易于访问的格式保存游戏状态的数组,这样会更容易计算。

      【讨论】:

      • 虽然 int.Parse 有点难看...但它有助于保持可获胜位置易于阅读。
      【解决方案4】:

      我倾向于做这样的事情:

      bool x_wins =
          Enumerable
              .Range(0, 3)
              .SelectMany(i => new Func<int, string>[] { x => array[i, x], x => array[x, i] })
              .Concat(new Func<int, string>[] { x => array[x, x], x => array[2 - x, x], })
              .Where(f => String.Concat(Enumerable.Range(0, 3).Select(x => f(x))) == "XXX")
              .Any();
      

      【讨论】:

        猜你喜欢
        • 2022-12-16
        • 1970-01-01
        • 2012-01-13
        • 2017-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-24
        相关资源
        最近更新 更多