这道题刚开始本来想直接打表过的,整一手面向结果编程哈哈哈,不过仔细一想这样就失去了刷题的意义,我就从头开始自己一步一步想着写出了通用的写法,可能不是最优解(起码是AC代码),但是我感觉要比题解里的都要更好理解些~
基本思路:
1.写出每一个方向的走向判断,判断大致可以分为两部分:
(1)最外围一圈的判断
(2)其余内圈的判断
2.定义一个变量用来控制行径方向,避免一直在一个方向判断里打转
3.每次循环开始时,在判断前往数组中填入数字,然后进行走下一步的行动
详细代码(拿Dev C++写的,可能有些格式不太标准):
#include<iostream>
#include<string.h>
#define RIGHT 1
#define DOWN 2
#define LEFT 3
#define UP 4
using namespace std;
int main(){
int n;
cin>>n;
//用于填入数组(从1到n*n )
int cnt=1;
//控制二维数组的坐标移动
int i=0;
int j=0;
//数组
int arr[n][n];//用devc++写的代码,支持这种方式创建数组
//全部置0,因为是从1开始的,不用担心重复问题,而且还可以用0表示当前位置空
memset(arr,0,sizeof(arr));
//用于标记下一步要往哪个方向走
int flag = RIGHT;
//由题可知方向转变是固定的“右→下→左→上”
while(1){
//当前点放入数据
arr[i][j]=cnt++;
//循环结束条件
if(cnt>n*n)break;
//向右走判断
if(RIGHT == flag){
if(j<n-1) {//如果不是最外围一侧
if(arr[i][j+1]==0){//如果当前方向的下一个位置是空的(可以放)
//当前位方向 前进一步
j++;
}else{//如果当前方向的下一个位置不是空的(已经放过数字了)
//换下一个方向
i++;
flag = DOWN;
}
continue;//这一步走完了,后面的省略
}else if(j==n-1&&arr[i][j]!=0){//如果是最外围一侧
//(arr[i][j]应该不会是空,不过保险起见我还是加了个判断)
//换方向
i++;
flag = DOWN;
continue;
}
}
//向下走判断
if(DOWN == flag){
if(i<n-1) {
if(arr[i+1][j]==0){
i++;
}else if(arr[i+1][j]!=0){
j--;
flag = LEFT;
}
continue;
}else if(i==n-1&&arr[i][j]!=0){
j--;
flag = LEFT;
continue;
}
}
//向左走判断
if(LEFT == flag){
if(j>0){
if(arr[i][j-1]==0){
j--;
}else{
i--;
flag = UP;
}
continue;
} else if(j==0&&arr[i][j]!=0){
i--;
flag = UP;
continue;
}
}
//向上走判断
if(UP == flag){
if(i>0){
if(arr[i-1][j]==0){
i--;
}else{
j++;
flag = RIGHT;
}
continue;
}
}
}//end of while(1)
//输出
for(int i =0;i<n;i++){
for(int j =0;j<n;j++){
printf("%3d",arr[i][j]);
}
printf("\n");
}
return 0;
}
运行示例: