【问题标题】:C# Check if win function for TicTacToeC# 检查 TicTacToe 的 win 函数
【发布时间】:2018-03-10 08:58:57
【问题描述】:

我正在尝试创建一个函数来检查是否有胜利(水平)。 所以我在纸上想到了这一点,但无法让它完全发挥作用。我的代码目前有 2 个缺陷。

  1. 它只检查第一行。之后就不起作用了。
  2. 第一行中的任何内容。让我们说在点 0,1[X] 0,2[O] 0,3[X] 它会返回一个“真”

这里是代码。

//Public Var
int n = 3;

//How I test if function is True and when. (every time an O or X is placed i do this:)

if (checkwinnner() == true)
{
    MessageBox.Show("Someone won.");
}

//Function
public bool checkwinnner() 
{  
    bool bw = true;
    for (int r = 0; r < n; r++)
    {
        bw = true;
        if (bar[r, 0].Text != "")
        {
            for (int c = 1; c < n; c++)
            {
                if (bar[r, 0].Text != bar[r, c].Text)
                {
                    bw = false; break;
                }
            }
            bw = true;
        }
        else 
        { 
            bw = false; 
        }
    }
    return bw;
}

到目前为止,这就是此功能的全部内容。我很忙与它自动取款机。所以。我用bool 来检查是否有人赢了。真的是赢了假的还没有赢。

  • N = 高度和范围。它始终是 3x3,但可以通过文本框进行更改。
  • R = 行
  • C = 列

所以我首先放入了一个 for 循环来循环每一行。 然后我检查文本是否不为空。因为如果它是空的,它不能在水平的 3x3 字段中连续 3 个。之后,我需要为每一列做一个 for 循环。并检查第 1 列中的文本是否等于 2 和 3。

但是我在帖子顶部说明了我的 buggs atm 并想问:

关于我可以解决什么或做错了什么的任何提示。我想使用这段代码,而不是一些 if 语句来检查像 if((0,1 &amp;&amp; 0,2 &amp;&amp; 0,3) == X || Y) 这样的按钮或类似的东西。因为该字段可以是 4x4 和 5x5 to。

提前谢谢你。我希望我的问题格式正确。

编码愉快。

【问题讨论】:

  • FWIW,你可以做if (checkwinnner())。不需要== true 部分。
  • 好吧,假设它总是正方形的……只有行、列和两条对角线。如果在任何给定的行、列或对角线的所有框中都有相同的答案,那么就没有了。
  • 直接 - 你初始化 n=0,然后在你的函数中设置一个默认值 true,并且你的循环检查行
  • @Corak:它甚至不会检查它是否会立即失败 0
  • @PaulF - 对,更糟。

标签: c# for-loop if-statement boolean tic-tac-toe


【解决方案1】:
public bool checkwinnner() 
{  
    int size = n;

    //check rows
    bool okay = true;
    for (int i = 0; i < size; i++)
    {
        bool rowOkay = true;
        //start at 1, compare with previous
        for (int j=1; j<size;j++)
        {
           //this cell is blank or doesn't match it's neighbor
           if (bar[i,j].Text == "" || bar[i, j-1].Text != bar[i,j].Text)
           {
               rowOkay = false;
               j=size;
           }
        }
        if (rowOkay) return true;
    }

    //TODO (per Question OP): Implement columns and diagonals

    return false;
}

你也可以考虑改变这个告诉你赢了(“X”、“O”或“”)。否则,您将不得不再次回到游戏板中才能弄清楚。

public string checkwinnner() 
{  
    int size = n;

    //check rows
    bool okay = true;
    for (int i = 0; i < size; i++)
    {
        bool rowOkay = true;
        //start at 1, compare with previous
        for (int j=1; j<size;j++)
        {
           //this cell is blank doesn't match it's neighbor
           if (bar[i,j].Text == "" || bar[i, j-1].Text != bar[i,j].Text)
           {
               rowOkay = false;
               j=size;
           }
        }
        if (rowOkay) return bar[i,0].Text;
    }

    //TODO (per Question OP): Implement columns and diagonals

    return "";
}

var winner = checkwinnner();
if (winner != "")
{
    MessageBox.Show(winner + " won.");
}

对于列,只需反转 i 和 j:bar[i,j] 变为 bar[j,i]。对于对角线,从左上角到右下角的对角线非常简单 (bar[i,i])。另一个对角线需要一些思考,但由于这看起来像是一个练习题,我希望您先自己尝试一下。

【讨论】:

  • 这不允许扩展到任意数量的行/列
  • 这不容易扩展
  • 很确定这不会成为一个三A游戏。谁在乎它是否不容易扩展呢?只是说,如果它有效,它就有效。
  • 这正是我遇到的问题,但它不可扩展
  • @IamBatman:对于一个人来说,OP 关心它是否可以扩展——所以这并不能解决问题。
【解决方案2】:

部分问题在于,在您循环遍历 c 之后,您会将 bw 设置回 true。该行将始终被击中,因为break 只会让您脱离for 循环。这就是为什么你得到true,不管你在一行中有什么。另一个问题是bw 将在第一个循环重复时继续被覆盖 - 您将只能返回最后一个值。

以下内容应该有效、可扩展并且尽可能接近您的原始内容。它不会告诉你赢了 - 如果你想让它也显示谁赢了,你需要返回 bool 以外的其他类型。

public bool checkwinnner() 
{  
    bool bw = true;
    for (int r = 0; r < n; r++)
    {
        bw = true;
        if (bar[r, 0].Text != "")
        {
            for (int c = 1; c < n; c++)
            {
                if (bar[r, 0].Text != bar[r, c].Text)
                {
                    bw = false;
                }
            }
            //bw will remain true if and only if every cell in the row has the same symbol
            if (bw)
            {
                //if bw is true then someone wins, so return true so the method terminates
                return true;
            }
        }
    }
    //if we haven't already returned true, there is no winning row so return false
    return false;
}

【讨论】:

    【解决方案3】:

    如果你不喜欢循环,我个人会使用 LINQ

    string[][] grid = new string[3][];
    
    grid[0] = new string[3] { "X", "O", "X" };
    grid[1] = new string[3] { "", "", "" };
    grid[2] = new string[3] { "X", "X", "X" };
    
    bool test = grid.Any(r => !r.Contains("") && r.Distinct().Count() == 1);
    

    基本上,您正在查看这些值是否都相同(但不为空)。

    更新,增加垂直测试。

    int n = 3;
    
    string[][] grid = new string[3][];
    
    grid[0] = new string[3] { "X", "O", "X" };
    grid[1] = new string[3] { "", "", "X" };
    grid[2] = new string[3] { "X", "X", "X" };
    
    bool test = grid.Any(r => !r.Contains("") && r.Distinct().Count() == 1);
    
    // for each column, get the distinct elements from it
    for(int i = 0; i < n; i++)
    {
        bool vertTest = grid.Select(r => r[i]).Any(c=> !c.Contains("") && c.Distinct().Count() == 1);
    }
    

    【讨论】:

    • 是的。但它是绑定到一行的。垂直对角线水平。
    • 对,其他的也修改这个例子。您仍然可以使用 linq 来检查其他方向。
    • 但这如何扩展。假设该字段变为 5x5。我需要手动完全添加更多网格项吗?
    • 我只是将网格设置为演示,实际的“检查”不依赖于网格中有多少项目。你可以有 3 个或 300 个,它的工作原理是一样的。
    猜你喜欢
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多