创建一个数独。我应该为此代码使用while语句吗?

时间:2015-09-17 19:17:00

标签: c# winforms

我在Windows窗体应用程序中制作数独游戏。

我有81个文本框,我将它们全部命名为textBox1a,textBox1b ... textBox2a,textBox2b ......

我想这样做,以便如果任何行中的任何文本框等于同一行中的任何其他文本框,那么两个文本框都相等时将获得背景颜色为红色。

我尝试使用此代码进行测试:

private void textBox1a_TextChanged_1(object sender, EventArgs e)
    {
        while (textBox1a.Text == textBox1b.Text)
        {
            textBox1a.BackColor = System.Drawing.Color.Red;
            textBox1b.BackColor = System.Drawing.Color.Red;
        }

它没有用,而且我不知道应该把所有这些代码放在哪里,我知道我不应该在文本框中有它。

我应该使用与此类似的代码还是完全错误?

5 个答案:

答案 0 :(得分:0)

您希望仅对文本框集合进行一次迭代,将其与尚未与之比较的文本框进行比较。如果你有一个数组中的文本框(让我们称之为textBoxes),并知道哪一个刚刚更改(例如从textChanged处理程序),你可以这样做:

void highlightDuplicates(int i) // i is the index of the box that was changed
{
   int iVal = textBoxes[i].Text;
   for (int j = 0; j < 82; j++) 
   {
      // don't compare to self
      if (i == j) return;

      if (textBoxes[j].Text == iVal)
      {
         textBoxes[i].BackgroundColor = System.Drawing.Color.Red;
         textBoxes[j].BackgroundColor = System.Drawing.Color.Red;
      }
   }
}

如果你想获得更好的,你可以把你的数据放在:Dictionary<int, TextBox>,其中键是值,TextBox是带有该值的文本框的引用。然后,您可以使用Dictionary.Contains()快速测试重复值,并通过获取其值来为匹配的文本框着色。

答案 1 :(得分:0)

我认为您当前的代码会导致无限循环。当你仍在事件处理程序中时,文本框的值不能改变,因此循环永远不会退出。

如果你的所有盒子都按照一个约定命名,你可以做这样的事情。多个输入可以使用相同的处理程序,因此您只需将此处理程序分配给所有框。

以下代码未经过测试,可能包含错误

private void textBox_TextChanged(object sender, EventArgs e){
     var thisBox = sender as TextBox;
     //given name like "textBox1a"
     var boxNumber = thisBox.Name.SubString(7,1);
     var boxLetter = thisBox.Name.SubString(8,1);

     //numbers (horizontal?)
     for(int i = 1; i<=9; i++){
          if(i.ToString() == boxNumber)
               continue; //don't compare to self
          var otherBox = Page.FindControl("textBox" + i + boxLetter) as TextBox;

          if (otherBox.Text == thisBox.Text)
          {
               thisBox.BackColor = System.Drawing.Color.Red;
               otherBox.BackColor = System.Drawing.Color.Red;
          }
     }

     //letters (vertical?)
     for(int i = 1; i<=9; i++){
          var j = ConvertNumberToLetter(i); //up to you how to do this
          if(j == boxLetter)
               continue; //don't compare to self
          var otherBox = Page.FindControl("textBox" + boxNumber + j) as TextBox;

          if (otherBox.Text == thisBox.Text)
          {
               thisBox.BackColor = System.Drawing.Color.Red;
               otherBox.BackColor = System.Drawing.Color.Red;
          }
     }
}

答案 2 :(得分:0)

我相信如果创建一个整数数组(或列表)并在内存中比较它们会更有效,而不是在UI(用户界面)中进行比较。

例如,您可以: 1)创建一个包含81个整数的数组。 2)每次用户输入新号码时,您都会在该阵列中搜索它。如果找到,请将文本框设置为RED,否则,将新值添加到该数组。 3)可以在整个文本框中分配ENTER事件(将Handles关键字与所有文本框一起使用;像处理Text1.enter,Text2.enter,Text3.enter ......等等)

类似的东西:

int[] NumbersByUser = new int[81];

 Private Sub Textbox1.Enter(sender as object, e as EventArgs) handles Textbox1.Enter, Textbox2.Enter, Textbox3.enter ...

 int UserEntry = Convert.ToInt32(Sender.text);
 int ValorSelecionado = Array.Find(NumbersByUser, Z => (Z == UserEntry));
 if (ValorSelecionado > 0) {
    Sender.forecolor = Red;
  } 
  else
  {
  NumbersByUser(Index) = UserEntry;

}

答案 3 :(得分:0)

你应该有一个2维数字数组(可能是一维的,但2更有意义)让我们假设它被称为Values。我建议你让每个文本框都有一个递增的数字(从左上角开始,向右,然后是下一行)。现在您可以执行以下操作:

所有TextBox Changed事件都可以指向同一个函数。然后该函数使用标记来计算2dim数组中的位置。 (X坐标为TAG%9,Y坐标为TAG / 9)

在回调中,您可以循环文本框并根据需要着色所有框。首先执行“检查行”循环(伪代码)

var currentTextBox = ((TextBox)sender)
var x = ((int)currentTextBox.Tag) % 9
var y = ((int)currentTextBox.Tag) / 9
// First assign the current value to the backing store
Values[currentTextBox] = int.parse(currentTextBox.Text)

// assuming variable x holding the column and y holding the row of current box
// Array to hold the status of a number (is it already used?)
bool isUsed[9] = {false, false, ...}
for(int col = 0; col <= 9; i++)
{
    // do not compare with self
    if(col == x) continue;
    isUsed[textBox] = true;
}
// now we have the status of all other boxes
if( isUsed[Values[x,y]] ) currentTextBox.Background = Red else currentTextBox.Background = Green
// now repeat the procedure for the column iterating the rows and for the blocks

答案 4 :(得分:0)

我建议采用动态方法。将每个电路板项目视为一个单元格(这将是它自己的类)。该类将包含一个数值和其他可能有用的属性(即可能的值列表)。

然后,您将创建3个单元格集合,这些集合将是:

  1. 9个单元格的行集合(用于跟踪每一行)
  2. 9个单元格的列集合(用于跟踪每列)
  3. 3x3细胞的集合
  4. 这些集合将共享引用 - 每个单元格对象在每个集合中都会出现一次。每个单元格还可以包含对3个集合中每个集合的引用。

    现在,当更改单元格值时,您可以获取对3个集合中的每个集合的引用,然后对任何这些集合应用一组标准的Sudoku逻辑。

    然后你有一些显示逻辑可以走单元板并输出到显示器(你的视图)你的值。

    享受 - 这是一个有趣的项目。