Exercise(20):蛇形填数

/*
    张理想
        蛇形填数
    描述
        在n*n方陈里填入1,2,...,n*n,要求填成蛇形。例如n=4时方陈为:
        10 11 12 1
        9 16 13 2
        8 15 14 3
        7 6 5 4
    输入
        直接输入方陈的维数,即n的值。(n<=100)
    输出
        输出结果是蛇形方陈。
    样例输入
        3
    样例输出
        7 8 1
        6 9 2
        5 4 3

    问题分析:
    以下为递归解决: 
        为了方便计算,将方阵大小设置为map[n+2][n+2],并将四周设置为-1,中部待填数的区域设为0
        由栗子可知,从右上角开始填数. 递归填数,当遇到边界(-1)便更换方向.
        注意:本题亮点在于方向的变换.
        为了处理方向变更的问题,设置一个参数direct表示当前方向0,1,2,3分别表示下左上右.
        (1)当direct == 0时,向下填数并判断下一个位置 if( 碰到边界 Or 已经填了数字 ):
                            是,则将方向改为向左(direct == 1)并向左填数.
                            否,则继续沿着原方向填数.
        (2)当direct == 1时,向左填数并判断下一个位置 if( 碰到边界 Or 已经填了数字 ):
                            是,则将方向改为向上(direct == 2)并向上填数.
                            否,则继续沿着原方向填数.
        (1)当direct == 2时,向上填数并判断下一个位置 if( 碰到边界 Or 已经填了数字 ):
                            是,则将方向改为向右(direct == 3)并向右填数.
                            否,则继续沿着原方向填数.
        (1)当direct == 3时,向右填数并判断下一个位置 if( 碰到边界 Or 已经填了数字 ):
                            是,则将方向改为向下(direct == 0)并向下填数.
                            否,则继续沿着原方向填数.
    代码实现如下... 
*/
#include <iostream>
using std::cin;
using std::cout;
using std::ends;
using std::endl;
int n;              // 方阵规格 
bool flag;          // 判断是否填满 
int cc = 0;         // 填写的数 
int map[102][102];  // 方阵 (为了方便计算,添加额外的4条边界)

void Init()                         // 初始化方阵 
{
    int i,j;
    for(i=0;i<n+2;i++)          
    {
        for(j=0;j<n+2;j++)
        {
            if(i==0 || i==n+1)      // 为了方便计算 方阵的最顶行、最底行、最左列、最右列皆设为-1
                map[i][j] = -1;
            else if(j==0 || j==n+1)
                map[i][j] = -1;
            else 
                map[i][j] = 0;
        }
    }
}

void Handle(int x,int y,int direct) // 在阵内填数 x,y分别代表横纵坐标 
{                                   // direct代表当前填数的方向 0,1,2,3 分别表示下左上右 
    if(cc == (n*n))                 // 当计数器达到n*n时,填数完毕 
    {
        flag = true;
        return;
    }

    map[x][y] = ++cc;                   // 填数 

    if(!flag)
    {
        if(direct == 0)                     
        {
            if(map[x+1][y] == 0)        // 向下
                Handle(x+1,y,direct);
            else                        // 碰到边界 Or 已经填了数字 
            {   
                direct = 1;             // 变向:向左    
                Handle(x,y-1,direct);
            }
        }
        else if(direct == 1)            
        {
            if(map[x][y-1] == 0)        // 向左 
                Handle(x,y-1,direct);
            else                        // 碰到边界 Or 已经填了数字
            {
                direct = 2;             // 变向:向上 
                Handle(x-1,y,direct);
            }
        }   
        else if(direct == 2)
        {
            if(map[x-1][y] == 0)        // 向上 
                Handle(x-1,y,direct);
            else                        // 碰到边界 Or 已经填了数字
            {
                direct = 3;             // 变向:向右 
                Handle(x,y+1,direct);
            }
        }
        else if(direct == 3)
        {
            if(map[x][y+1] == 0)        // 向右 
                Handle(x,y+1,direct);
            else                        // 碰到边界 Or 已经填了数字
            {
                direct = 0;             // 变向:向下 
                Handle(x+1,y,direct);
            }
        }
    }
}

void Show()                         // 打印方阵 
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            cout<<map[i][j]<<ends;
        }
        cout<<endl;
    }
}

int main()
{
    cin>>n;
    if(n<0 || n>100) return -1;

    Init();             // 初始化方阵
    Handle(1,n,0);      // 在阵内填数 
    Show();             // 打印方阵 

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值