void OpenClean( int i, int j) {
bnt[i, j] = new Button();
if (!bnt[i,j].Enabled) return;
bnt[i, j].Enabled = false;
bnt[i,j].BackColor = Color.Aquamarine;
bnt[i, j].Text = data[i, j].ToString();
if (data[i, j] == 0) {
if (i > 0 && j > 0 && data[i - 1, j - 1] == 0) OpenClean(i - 1, j - 1);
if (i > 0 && data[i - 1, j] == 0) OpenClean(i - 1, j);
if (i > 0 && j < 8 && data[i - 1, j + 1] == 0) OpenClean(i - 1, j + 1);
if (j > 0 && data[i, j - 1] == 0) OpenClean(i, j - 1);
if (j < 8 && data[i, j + 1] == 0) OpenClean(i, j + 1);
if (i < 8 && j > 0 && data[i + 1, j - 1] == 0) OpenClean(i + 1, j - 1);
if (i < 8 && data[i + 1, j] == 0) OpenClean(i + 1, j);
if (i < 8 && j < 8 && data[i + 1, j + 1] == 0) OpenClean(i + 1, j + 1);
}
它告诉我进程因 StackOverflowException 而终止。 由于我的经验有限,我没有找到有效的方法。 这个问题困扰我很久了。 请帮助或尝试给我一些解决方法的想法。
提前致谢!
答案 0 :(得分:0)
您从未将 data[i, j]
设置为除 0
以外的值。因此,递归永远不会停止。您必须将检查的单元格设置为不同的值,以便它们不会被一次又一次地检查...
您还可以使用 bnt[i, j] = new Button();
创建一个新按钮,而不是检查现有按钮。因此,您永远不会看到带有 Enabled == false
的按钮,因为 default value for Enabled
is true
。
最好将逻辑基于模型(即 data[,]
),并将 UI(控件)仅用于显示。
const int Inspected = -1;
void OpenClean( int i, int j) {
...
if (data[i, j] == 0) {
data[i, j] = Inspected; // <====== This stops the endless recursion!
if (i > 0 && j > 0 && data[i - 1, j - 1] == 0) OpenClean(i - 1, j - 1);
...
}
}
顺便说一句,您正在测试 0
两次。在再次调用 OpenClean
和内部 OpenClean
之前。只做一次。
void OpenClean( int i, int j) {
if (data[i, j] == 0) { // This one does the job.
data[i, j] = Inspected; // <======
// bnt[i, j] = new Button(); <=== drop this!
// if (!bnt[i,j].Enabled) return; <=== drop this! We test data instead.
bnt[i, j].Enabled = false;
bnt[i,j].BackColor = Color.Aquamarine;
bnt[i, j].Text = data[i, j].ToString();
if (i > 0 && j > 0) OpenClean(i - 1, j - 1);
if (i > 0 ) OpenClean(i - 1, j);
if (i > 0 && j < 8) OpenClean(i - 1, j + 1);
if ( j > 0) OpenClean(i, j - 1);
if ( j < 8) OpenClean(i, j + 1);
if (i < 8 && j > 0) OpenClean(i + 1, j - 1);
if (i < 8 ) OpenClean(i + 1, j);
if (i < 8 && j < 8) OpenClean(i + 1, j + 1);
}
}
如果在OpenClean
开头做范围测试,可以去掉所有其他范围测试。
void OpenClean( int i, int j) {
if (i > 0 && i < 8 && j > 0 && j < 8 && data[i, j] == 0) { // This one does the job.
data[i, j] = Inspected; // <======
bnt[i, j].Enabled = false;
bnt[i,j].BackColor = Color.Aquamarine;
bnt[i, j].Text = data[i, j].ToString();
OpenClean(i - 1, j - 1);
OpenClean(i - 1, j);
OpenClean(i - 1, j + 1);
OpenClean(i, j - 1);
OpenClean(i, j + 1);
OpenClean(i + 1, j - 1);
OpenClean(i + 1, j);
OpenClean(i + 1, j + 1);
}
}
使用 C# 9.0 模式,您可以稍微简化条件
if (i is > 0 and < 8 && j is > 0 and < 8 && data[i, j] == 0)