观察可以发现该从0开始的序列从【0】【0】位置开始向右递增,“撞墙后”(遇到边界),向下递增,再次撞墙后向左,碰到左边界后向上,向上遇到【0】【0】已填充转而向右。
关键在于
1.怎么实现方向控制
2.撞墙的判断以及转向
于是我们可以记录当前位置向上下左右各个方向的偏移量
例如【3】【3】位置右边是【3】【4】相当于x不变y+1;
此时x的偏移量为0,y的偏移量为+1;
于是我们遵循右下左上的顺序记录x和y的偏移量;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
当向右时x始终不变,y+1;
设a,b为当前已填充位置的下一个x,y,位置;
判断是否撞墙,若不撞墙,则直接更新x,y的值,令x=a,y=b;
在下一次循环时写入;
撞墙时的转向可以用d=(d+1)%4;控制 。
d一开始向右=0;当要向下时d+1即可 ;对4取余是为了让d始终等于0 1 2 3 四个值
下面附上代码
#include<iostream>
using namespace std;
int q[101][101];
int main(){
int n,m;
cin>>n>>m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
//记录各坐标x,y方向偏移量;
int x=0,y=0;
int d=0;
//d=0 初始方向向右
for(int i=1;i<=n*m;i++){
q[x][y]=i;
int a=x+dx[d];
int b=y+dy[d];
//定义当前方向 下个位置的坐标
if(a<0||a>=n||b>=m||b<0||q[a][b]){
//判断是否越界或者遇到已经填入数字的数组元素
d=(d+1)%4;
//若“撞墙”则调转方向;
a=x+dx[d];
b=y+dy[d];
//重新设定方向后 下个位置坐标更新
}
x=a,y=b;
//更新x,y到新位置
}
for(int i=0;i<n;i++){
for(int k=0;k<m;k++){
printf("%d ",q[i][k]);
}
printf("\n");
}
return 0;
}