本题思路为:先创建一个二维数组,然后找到填数的起始位置,之后用“下-左-上-右”的走法实现一个循环,然后不断重复这个循环就可以实现指定大小的填数了。
那么如何保证填数的时候不会填到已经填完数的位置呢?如果仅仅靠单纯的循环显然无法做到这一点,所以我们需要在循环的条件控制中加入一些“特殊”的限制。那么,这些限制是什么?
这个时候就要引出我认为这个题目想要告诉我们的最核心的思想:先判断,再行动。
这个思想个人认为应当十分重要,并且在今后做题时可能还会多次遇到,而这也是我写本篇博客的理由——帮助记忆这个思想并能在今后的做题过程中加以运用。
好了,这个思想在本题中的体现就是——先判断“下一个”位置是否被填数,如果没有,那么再行动。
#include<stdio.h>
#include<string.h>
#define maxn 20
int arr[maxn][maxn]; //tip:在主函数外定义数组不需要初始化,直接全为0
int main(){
int x,n,tot= 0;
int y = maxn;
scanf("%d",&n);
memset(arr,0,sizeof(arr));//实现对arr数组的初始化 (属于是多次一举,不过为了和书上格式一样就无所谓了)
tot = arr[x=0][y=n-1] = 1;
while(tot<n*n)
{
//下移动
while(x+1<n && !arr[x+1][y])
arr[++x][y] = ++tot;//同时实现向下一行与数值+1
//左移动
while(y-1>=0 && !arr[x][y-1])
arr[x][--y] = ++tot;
//上移动
while(x-1>=0 && !arr[x-1][y])
arr[--x][y] = ++tot;
//右移动
while(y+1<n && !arr[x][y+1])
arr[x][++y] = ++tot;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
printf("%3d",arr[i][j]);
}
printf("\n");
}
return 0;
}
在做这题的时候出了两个错误:
1.把memset行和tot行搞反了,导致arr[0][n-1]刚赋成1又被归0了(arr[0][n-1]:玩我呢?)
2.++tot写成了tot++,导致输出结果中出现了上下两个1(即arr[0][n-1]与arr[1][n-1]),属于前++与后++的错误,希望大家引以为戒吧。