(完全新手)函数递归注意事项:扫雷 其一(未完成)
其一:铺好通往递归出口的路
之前码走迷宫的时候看到别人码的走迷宫程序,里头用了函数递归,从那以后递归耍的飞起-----个屁,现在死循环才是我最眼熟的。
前几天码扫雷的时候,想着扫雷不是点一下duang一大块嘛,用用递归从内到外挺好的。
以下是错误范例://基本思路是:在前期准备中已经将每个坐标周围8个坐标的雷数存入了二维数组lei中。
//基本思路是:在前期准备中已经将每个坐标周围8个坐标的雷数存入了二维数组lei中。
//输入坐标(x、y),在终端对应位置打印其周围雷数--lei[x][y]。 //若lei[x][y]==0,则对周围所有坐标重复上述操作。 //x、y=输入坐标,h=扫雷行数,w=扫雷列数 void saolei(int x,int y,int h,int w) { int m=0,n=0; //m、n 参与递归的坐标 printf("\033[%d;%dH%d",x,2*y,lei[x][y]); //在终端对应位置打印其周围雷数lei[x][y] if(lei[x][y]==0) { //循环嵌套,目的是:1、打印输入坐标附近八个位置的周围雷数--lei[m][n] //2、将这八个位置的坐标作为saolei函数的实参运行 for(m=max(x-1,1);m<=min(x+1,h);m++) { for(n=max(y-1,1);n<=min(y+1,w);n++) { saolei(m,n,h,w); } } }
return;
}
现在是能看出问题很大了,可当时不行。
于是漫漫死循环路开始了。
直到突然想到:1、假设输入点A坐标,如果点A的对应二维数组lei中的值为零,那么就会判断并在终端输出A周围八个点的lei值;
2、如果这八个点中有点B的lei值也0,就会判断并在终端输出B周围八个点的lei值;
3、然后程序判断到在点B周围的点A,其lei=0,于是不断重复1、2两步,死循环开始了。
这时候我才注意到到设置递归终止条件(出口)的概念。之前的函数就是限制条件给的不全,导致没法返回。
接着顺着这个思路想了下去,改了程序。
//基本思路是:在前期准备中已经将每个坐标周围8个坐标的雷//输入坐标(x、y),在终端对应位置打印其周围雷数--l
//若lei[x][y]==0,则对周围所有坐标重复上述操作。
//x、y=输入坐标,h=扫雷行数,w=扫雷列数
void saolei(int x,int y,int h,int w)
{ int m=0,n=0; //m、n 参与递归的坐标 a[x][y]=9; //定义了一个二维数组a,每次执行saolei函数时,給a[x][y]一个定值,用它判断某一点是否运行过saolei函数 printf("\033[%d;%dH%d",x,2*y,lei[x][y]); //在终端对应位置打印其周围雷数lei[x][y] if(lei[x][y]==0) { //循环嵌套,目的是:1、打印输入坐标附近八个位置的周围雷数--lei[m][n] //2、将这八个位置的坐标作为saolei函数的实参运行 for(m=max(x-1,1);m<=minh);m++) { for(n=max(y-1,1);n<=min(y+1,w);n++) {
//如果a[m][n]==9,则说明m、n已经作为参数执行过saolei函数,再执行会导致死循环,所以跳过本次循环。而且当m、n与x,y相等时,由于a[x][y]=9,所以一并略过了,不用写程序略过。
if(a[m][n]==9) continue;
saolei(m,n,h,w); } } }
else
return ; }
虽然之前的函数也有一个return 摆着,也有if语句限制递归的继续,看起来像是有个出口的样子了。
但由于条件没有思考完整,导致这个出口总是失灵,改正过后的函数里才算有了一个完整的出口。
浙公网安备 33010602011771号