我在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;
}
它没有用,而且我不知道应该把所有这些代码放在哪里,我知道我不应该在文本框中有它。
我应该使用与此类似的代码还是完全错误?
答案 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个单元格集合,这些集合将是:
这些集合将共享引用 - 每个单元格对象在每个集合中都会出现一次。每个单元格还可以包含对3个集合中每个集合的引用。
现在,当更改单元格值时,您可以获取对3个集合中的每个集合的引用,然后对任何这些集合应用一组标准的Sudoku逻辑。
然后你有一些显示逻辑可以走单元板并输出到显示器(你的视图)你的值。
享受 - 这是一个有趣的项目。