问题描述: 输入一个数n(要求该数可开平方),生成回字蛇形方阵。
如:输入25,输出:
一、初版(方阵):
思路: 撇开第一行不看,可以观察到明显规律
代码:
#include<stdio.h>
#include<math.h>
int main(){
int n,k,d=0,i,j,num=1,x=0,y=0; //d表示方向;
scanf("%d",&n);
k=sqrt(n); //方阵的行列数;
int a[k][k]; //声明蛇形方阵;
n=k; //记录蛇形方阵的边长,主要用于方阵输出;
for(i=1;i<=k;i++){
a[x][y++]=num++; //先将方阵第一行赋值;
}
num--;y--; //由于上面赋值运算,导致num,y需要回溯一下 ;
while(k-->0){ //k为0时,方阵构造完成 ;
for(i=1;i<=2;i++){ //走2次;
for(j=1;j<=k;j++){ //每次走k步 ;
switch(d%4){
case 0: ++x;break;//向下运动,横坐标增大
case 1: --y;break;//向左运动,纵坐标减小
case 2: --x;break;//向上运动,横坐标减小
case 3: ++y;break;//向右运动,纵坐标增大
}
a[x][y]=++num;//每走一步num都加1;
}
d++; //每次走完k步,都需要转向一次
}
}
for(i=0;i<n;i++){//输出方阵
for(j=0;j<n;j++){
printf("%4d",a[i][j]);
}
printf("\n");
}
}
二、改进版(方阵)
下面算法比较简单易懂,借鉴自码诗~前辈的文章
6.用c语言实现蛇形数组_码诗~的博客-CSDN博客_蛇形数组c语言
思路:
由外内逐层赋值,m控制每次赋值开始位置,k控制要赋值矩阵的行列,每次循环将k限制的方阵缩小一圈,直到m==k(也可以是num>n*n)时,方阵构造结束;每次循环赋值方向都遵循
→ ↓ ← ↑
运动规律,每次转向时只需要更新起始位置下标即可,比如:右转下,列下标j不变,只需将行下标i起始位置改为m+1就可以实现,赋值到i<=k即可;(抱歉,水平有限,辞不达意)
代码:
#include <stdio.h>
// 回形遍历方阵
int main()
{
int num = 1;
int n;
int i, j;
scanf("%d", &n);
int arr[n][n]={0};
for (int m = 0, k = n - 1; m <= k/*num<=n*n*/; m++, k--)
{
for (i = m, j = m; j <= k; j++)//往右走
{
arr[i][j] = num++;
}
for (i = m + 1, j = k; i <= k; i++)//往下走
{
arr[i][j] = num++;
}
for (i = k, j = k - 1; j >= m; j--)//往左走
{
arr[i][j] = num++;
}
for (i = k - 1, j = m; i >= m + 1; i--)//往上走
{
arr[i][j] = num++;
}
}
//遍历输出
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
printf("%4d", arr[i][j]);
}
printf("\n");
}
}
三、延伸版(矩阵)
根据改进版得出的n*m阶回字形蛇形矩阵,大致思路与改进版方阵一样。
思路:
输入行n,列m,矩阵中元素最多为nm个,通过num++(初值为1)为元素赋值,当num>nm时,矩阵构造完成。
通过观察发现,赋值呈周期性规律:每次赋值一个矩阵框,为矩阵框赋值方向遵循先右,再下,后左,最后上。因此,可以以一个矩阵框为一个循环,通过kx,ky变量控制矩阵框长宽的步长(此处为步长,即在一个方向上赋值次数),每次循环矩阵框都缩小,因此步长也相应减小1。
通过(i,i)标记每次矩阵框的起始赋值位置,每轮循环都加1,结合kx,ky就可以确定每轮循环的矩阵框。重点:循环判断条件“num<=n*m”是为了避免覆盖已赋值区域!!!每次赋值操作都要判断!
代码:
#include <stdio.h>
// 回形遍历矩阵
int main()
{
int num = 1;
int n,m,kx,ky;
int i,x,y;
scanf("%d %d", &n,&m);//n,m分别为矩阵的行列。
int arr[n][m]={0};
//循环判断条件“num<=n*m”是为了避免覆盖已赋值区域。
for (i=0,kx=n-1,ky=m-1;num<=n*m;i++,kx--,ky--) //由外而内逐层赋值。
//i,i标记矩阵框赋值起始位置,kx,ky控制每次赋值的矩阵框大小 。
{
for ( x = i , y = i ;y<=ky && num<=n*m; y++ )//往右走,(i,i)为每个矩阵框赋值起始位置 。
{
arr[x][y] = num++;
}
for ( x = i + 1, y = ky;x<=kx && num<=n*m; x++ )//往下走,此时起点为kx+1,ky 。
{
arr[x][y] = num++;
}
for ( x = kx, y = ky - 1;y>=i && num<=n*m; y-- )//往左走,此时起点为kx,ky-1 。
{
arr[x][y] = num++;
}
for (x = kx - 1, y = i;x>i && num<=n*m; x--)//往上走,此时起点为,kx-1,i。
{
arr[x][y] = num++;
}
}
//遍历输出
for (x = 0; x < n; x++)
{
for (y = 0; y < m; y++)
{
printf("%4d", arr[x][y]);
}
printf("\n");
}
}