#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
#define LL long long
int main()
{
int a[15][15];
int n;
while(scanf("%d",&n))
{
memset(a,0,sizeof(a));
int l,r;
int num;
a[l=1][r=n]=num=1;
while(num<n*n)
{
while(l+1!=n+1&&!a[l+1][r]) {a[++l][r]=++num;}
while(r-1!=0&&!a[l][r-1]) {a[l][--r]=++num;}
while(l-1!=0&&!a[l-1][r]) {a[--l][r]=++num;}
while(r+1!=n+1&&!a[l][r+1]) {a[l][++r]=++num;}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<n;j++)
printf("%2d ",a[i][j]);
printf("%2d\n",a[i][n]);
}
}
return 0;
}
我们从1开始依次填写。设“笔”的坐标为(x,y),则一开始x=1,y=n。
然后先是下,到不能填了为止,然后是左,接着是上,最后是右。
“不能填是指在走就出界,或者再走就要走到以前填过的格子。如果我们把所有
的格子初始化为0,就能很方便地加以判断。
(此处分析很重要,有时候不要感觉不能一口气敲出来就不敲了,有时候灵感会在一点点的敲代码的
时候涌现出来)。
此外,自己敲的代码不够简洁,改了一下,按照下面的改几处,可以使代码比较简洁,且保持了代码的可读性。
首先,赋值x=1和y=n后马上要把它们作为a数组的下标,因此可以合并完成;num和a[1][n]都要赋值1,也可以合并完成。
另外那四天while语句,起初自己写的代码比较麻烦,是用了”悔棋“的思想敲的,这里要注意是用”预判“的思想。
例如第一个while语句,我们的原则是:先判断,再移动,而不是走一步以后发现越界了再退回来。这样,我们需要
进行“预判”,即是否越界,以及如果继续往下走会不会到达一个已经填过的格子。越界只需判断l+1<n+1,因为r的值没有修改;
下一个格子是(l+1,r),因此只需a[l+1][r]==0,简写成!a[l+1][r](这个简写也要注意,简洁性).
(特别注意这里的用l+1进行预判,自己起初敲的代码,用的是“悔棋”的思想,比较麻烦,注意这个“预判”的思想)。
自己的代码,改良版。