先说说驱动吧,这是数据结构的作业,要是没有这作业的话,我今天还是不想写代码的,想放天假呢,奈何实验课已然排到了周日。。oh no。。
说一下作业要求吧:
初始时,各行皇后均放在第0列,然后从第0行开始逐行布局;
设前i-1行已布好,现考虑第i行皇后的位置,从其当前位置A[i]开始向右探察:
算法语言描述:
for(inti=0;i<n;i++)A[i]=0;
i=0;
while(i>=0){
if(A[i]<=n-1) {
检测A[i]与A[0]~A[i-1]是否有冲突;
if(有冲突)A[i]++;
else if(i<n-1)i++;
else {输出布局;A[n-1]++;}
}
else { A[i]=0;i--;
if(i>=0)A[i]++;
}
}
啥还没写就这么多了。
好了现在一点点实现吧:
先写一个类EightQueue,然后声明两个构造函数,EightQueue()和EightQueue(int n),无参构造函数里边写this(6),有参的里边粘贴上要求给的代码。如图:
然后把中文的部分翻译一下,感觉目前还很简单。。上面说了第i行与第j行上的皇后互不攻击的充要条件是:|A[i]-A[j]|==|i-j|;很明显这里是个循环检测,那最好写成一个方法,又因为下边有一个“有冲突”的判断,所以这个方法一定要有个返回值,这个返回值要赋值给一个标志符。所以再次声明一个boolean型变量HasCollide.创建方法CheckCollide(int i,int[] A);充要条件写上去。
对于循环检测我一般是这样写的,先写一个,再循环,听不懂?代码解释:
if (Math.abs(A[i]-A[0])==Math.abs(i-0)) {
return false;
}
else{
return true;
}
abs是求绝对值的,这样检测的是A[i]和A[0]的,然后上循环。
private boolean CheckCollide(int i, int[] A) {
// TODO Auto-generated method stub
boolean result = true;
for (int j = 0; j < i - 1; j++) {
if (Math.abs(A[i] - A[j]) == Math.abs(i - j)) {
result = false;
}
}
return result;
}
好了这个检测方法就写完了,下面是输出布局,总觉得少点什么==,不会就这么简单吧。。想想这个输出布局要输出啥。。
恩,这个布局应该是A[i]的数据,顺便说一下,这个要求的代码风格很不舒服,整理之后如下:
EightQueue(int n){
int [] A=new int[n];
int i;
boolean HasCollide=false;
for(i=0;i<n;i++)
A[i]=0;
i=0;
while(i>=0)
{
if(A[i]<=n-1)
{
HasCollide=CheckCollide(i,A);
if(HasCollide)
A[i]++;
else if(i<n-1)
i++;
else {
输出布局;
A[n-1]++;
}
}
else {
A[i]=0;
i--;
if(i>=0)
A[i]++;
}
}
}
之前我的风格一直是if(){/r/n},最近因为写C#代码里边Vs有个插件叫intend guide,缩进指南,这样上下两个大括号之前会用虚线连起来,这样一下就能看出来这个循环是哪部分,刚才以我原来的风格确实看的有点乱,又整理成了C#的风格了。果然看着很方便。不说废话了,A[]是记录布局数据的,A[i]的数字就是说明第i行的棋子的位置,所以输出布局就简单多了。
写个方法Print(int [] A);
一个种棋叫啥来的忘了,反正棋子是用O和X表示的,觉得很显眼,这里就采用这个了。空的地方为O,棋子为X.两层循环。
private void Print(int[] a2) {
// TODO Auto-generated method stub
int j ;
for (int i = 0; i < a2.length; i++) {
for (j = 0; j < a2[i]; j++) {
System.out.print("O");
}
System.out.print("X");
for (; j < a2.length; j++) {
System.out.println("O");
}
}
}
这样,好了现在测试一下,==,发现个问题,啥玩意 都没输出来。我就说没有这么简单。。又到了激动人心的调bug的时候了。。
好,现在把在这个while循环的结束之后调用Print方法发现输出的是:
XOOOOOOXOOOOOOXOOOOOOXOOOOOOXOOOOOOXOOOOOO
也就是有两个问题。。1,这一行多了一个,这个好办。2,while循环很可能就没有执行。先解决第一个。
多输出了一个在第二个循环里改成length-1,第一个问题解决。
现在第二个问题:读代码发现while循环肯定执行了,下一步,找别的疑点。
分析一下代码觉得是检测冲突那里出现问题了。。于是加了一个输出:
if (Math.abs(A[i] - A[j]) == Math.abs(i - j)) {
result = false;
System.out.println("dasd");
}
发现完全没有输出。现在问题找到了,原因是?
再往上找一步,发现是循环都未启动过,输出一下i,发现传过来的i都是0.。汗。。
看题:若A[i]<=n-1,则检查i行皇后与前i-1行皇后是否互不攻击。若有攻击,则i行皇后右移一位,重复这个过程;
N久之后,,自觉是自己的检测冲突写错了。马上改正,成功。。原因:老师给的结论就是错误的!!互不攻击的条件写错了她!!不过也赖我没动脑子。。不过这么关键的点上写错了条件直接耽误了十多分钟!
private boolean CheckCollide(int i, int[] A) {
// TODO Auto-generated method stub
boolean result = false;
for (int j = 0; j < i; j++) {
if (Math.abs(A[i] - A[j]) == Math.abs(i - j)||A[i]==A[j]) {
result=true;
break;
}
}
return result;
}