回形矩阵

首先我们来看个问题:

在这里插入图片描述

上面这个n*n的回形矩阵要怎么在程序中输出呢?我们仔细看不难看出数字都像一个海螺一样内旋增大,也就是有一定规律。但要是n一直变大,我们要怎样确定这些数字的位置呢?

下面是我的解决方法:

首先我创建了一个二维数组,用于存放这些数据,到时候打印只需要将这些数一个个打印出来就行了,我们先从简单做起,先创建一个数组并且写好输出的代码,毕竟凡事从简单做起嘛!

int main()
{
	int n = 0;
	scanf("%d", &n);
	int arr[19][19] = { 0 };
	//....
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
			printf("%-1d ", arr[i][j]);
		printf("\n");
	}
	return 0;
}

然后就是要考虑怎么按顺序将这些数字排进去的问题了,我的思路是这样的:

在这里插入图片描述

我们将数据按这样螺旋着排放,首先将数据从左向右排放,直至右边触碰到边界,再调头向下输入数据,然后向左,再向上输入数据。然后重新向右输入.....以此循环直至将n*n输入到数组中。

#define CONDITION m<=n*n
//....
while (m <= n * n)
	{
		int n = 0;
	    scanf("%d", &n);
	    int arr[19][19] = { 0 };
	    int i = 0, j = 0;//控制数组下标的两个变量
	    int cow = n, col = n;//控制递增边界的两个变量
	    int sta1 = 0, sta2 = 0;//控制递减边界的两个变量
		//具体思路是先右转,再下转,再左转,再上转,
		//每一次转弯的标志是碰到边界
		//右转
		while (CONDITION && j < col)
		{
			arr[i][j] = m;
			j++;
			m++;
		}
		//下转
		while (CONDITION && i < cow)
		{
			arr[i][j] = m;
			i++;
			m++;
		}
		//左转
		while (CONDITION && j >= sta1)
		{
			arr[i][j] = m;
			j--;
			m++;
		}
		//上转
		while (CONDITION && i > sta2)
		{
			arr[i][j] = m;
			i--;
			m++;
		}
}

这里要注意一些细节:

  1. 在每次接触到边界后,控制数组下标的i或者j会有出界的现象,因为我们是递增/递减完后再去判断while的条件的。 例如:第一次向右时,j会一直自增到4(但是有效部分是0~3)即结束时i=0,j=4,为了不越界,所以每次转完都要对相应的出界元素进行操作。这里对j进行减减。

  2. 不仅是出界元素的问题,当我们决定从向右转而向下时,右和下的重叠元素究竟算是谁的呢?这里我们算作是上一个操作的元素。所以在对于转动操作完成时,也要对下标元素i / j进行移动。 例如:第一次右转时i会保持不变且一直为0,即第一次右转结束是i=0,j=4,但为了得到第一个向下的元素,即i=1,j=3,所以这里我们对i进行加加,以此类推解决每次递进。

  3. 最后我们不难看出,一次循环中右转、下转、左转的边界元素都不会变化,但是上转时,上边界发生了变化,所以这里注意:

   while (CONDITION && i > sta2)

上边界不能取等号

修改了这些问题后:我们来看看最终的代码:

#define CONDITION m<=n*n
#include<stdio.h>

int main()
{
	int n = 0;
	scanf("%d", &n);
	int arr[19][19] = { 0 };
	int m = 1;//控制自增的变量
	int cow = n, col = n;//控制递增边界的两个变量
	int sta1 = 0, sta2 = 0;//控制递减边界的两个变量
	int i = 0, j = 0;//控制数组下标的两个变量
	while (m <= n * n)
	{
		//具体思路是先右动,再下动,再左动,再上动,每一次转弯的标志是碰到边界
		//右动
		while (CONDITION && j < col)
		{
			arr[i][j] = m;
			j++;
			m++;
		}
		j--;//判断多了一次,越界了
		i++;//位置重复了,坐标要往接下来的趋势变化
		//下动
		while (CONDITION && i < cow)
		{
			arr[i][j] = m;
			i++;
			m++;
		}
		i--;//判断多了一次,越界了
		j--;//位置重复了,坐标要往接下来的趋势变化
		col--; //右动和下动边界要变了
		cow--;
		//左动
		while (CONDITION && j >= sta1)
		{
			arr[i][j] = m;
			j--;
			m++;
		}
		j++;//判断多了一次,越界了
		i--;//位置重复了,坐标要往接下来的趋势变化
		//上动
		while (CONDITION && i > sta2)
		{
			arr[i][j] = m;
			i--;
			m++;
		}
		i++;//判断多了一次,越界了
		j++;//位置重复了,坐标要往接下来的趋势变化
		sta1++;//左动和上动的边界要变
		sta2++;
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
			printf("%-1d ", arr[i][j]);
		printf("\n");
	}
	return 0;
}

下面是我的输出结果:

n=3

在这里插入图片描述

n=5

在这里插入图片描述

n=9

在这里插入图片描述