XTU-OJ 《C语言程序设计》 1441-素数螺旋

本文介绍了一种编程方法,通过逆时针模拟生成一个逆时针的素数螺旋线图形,利用C++编写代码实现了从输入的整数n生成对应样例的螺旋图案,重点在于理解逆时针打印和边界处理的思路。

素数螺旋

题目描述

绘制一个逆时钟的螺旋线,一开始方向向右,边长依次为第i个素数,即2,3,5,7,⋯ 。 使用_ 表示横线,| 表示竖线,要求图形的每行行尾无多余的空格。

比如n=5时,

 _____
|     |
|     |
|   __|
|
|
|
|___________

输入格式

第一行是一个整数T (1≤T≤20),表示样例的个数。

以后每行一个整数n(1≤n≤168)。

输出格式

依次按要求输出对应的图形。每个样例之后输出一个空行。

样例输入

4
1
2
3
4

样例输出

__

  |
  |
__|

_____
     |
     |
   __|

 _____
|     |
|     |
|   __|
|
|
|
|

提示

第168个素数是997。

解题思路: 如果按照以往的找规律然后 从左到右,从上到下依次打印的方法去思考,这道题或许有点难。我们就纯粹的按题目所给的方法模拟,逆时针记录好图像,最后再打印。这样会简单很多。

1. 定制一个 2000*2000的字符数组,从(1000,1000)开始素数螺旋的起点,(开始设置为 1001,999 是为了和42/43行以及打印左边框的代码配合,如果不理解可以先从 1000,1000 模拟一遍,令n==5)。

2. 选定好起点之后就非常容易了, 我们在大脑中将如何逆时针打印图像的步骤过一遍,所想到的步骤即是程序实现的方法。

3.  虽然我们画图的时候是逆时针画出去的,但是打印的时候还是要按从左上到右下的顺序打印,所以我们记录一个整个图像的边框极限,上下左边框极限是根据整个图形判定的,右边框每一行都可能不一样(行末无多余空格)。打印右边框时要更新 上极限(ups),打印上边框时要更新左极限(lefts),打印左边框时要更新 下极限(downs)。 tags 数组记录每一行的右极限。

代码写的有些麻烦,但是思路一点不难。思路一下可能也不能把所以疑点都理清。如果还有疑问且想要弄明白的同学,请按照代码思路模拟一遍,肯定就能弄懂(或者评论留言)。

AC代码:

#include <stdio.h>

bool flag;
int ups,downs,lefts,stx,sty;
int cnt = 1;
int prime[200];
char maps[2000][2000];

void isPrime()
{
    for (int i = 2; i <= 1000; i ++)
    {
        flag = true;
        for (int j = 2; j*j <= i; j ++)
        {
            if (i%j == 0)
            {
                flag = false;
                break;
            }
        }
        if (flag)   prime[cnt++] = i;
    }
}

void drawmap()
{
    for (int i = 0; i < 2000; i ++)
        for (int j = 0; j < 2000; j ++)
            maps[i][j] = ' ';
}

void draw(int n)
{
    ups = 1000,downs = 1000,lefts = 1000;    //  螺旋 上下边框极限坐标
    stx = 1001,sty = 999;                    //  x为行,y为列
    int tags[2000] = {0};                    //  螺旋 右边框极限坐标
    for (int i = 1; i <= n; i ++)
    {
        if (i % 4 == 1)             //  打印下边框
        {
            stx --;
            sty ++;
            for (int j = 1; j <= prime[i]; j ++)
            {
                maps[stx][sty] = '_';
                sty ++;
            }
            tags[stx] = sty;
        }                           
        else if (i % 4 == 2)        //  打印右边框
        {
            for (int j = 1; j <= prime[i]; j ++)
            {
                maps[stx][sty] = '|';
                tags[stx] = sty+1;
                stx --;
            }
            if (i == n)       ups = stx + 1;   
            else              ups = stx;
        }
        else if (i % 4 == 3)        //  打印上边框
        {
            tags[stx] = sty;
            sty --;
            for (int j = 1; j <= prime[i]; j ++)
            {
                maps[stx][sty] = '_';
                sty --;
            }
            if (i == n)       lefts = sty + 1;
            else              lefts = sty;
        }
        else                        //  打印左边框
        {
            stx ++;
            for (int j = 1; j <= prime[i]; j ++)
            {
                maps[stx][sty] = '|';
                if (tags[stx] == 0)
                    tags[stx] = sty + 1;
                stx ++;
            }
            downs = stx - 1;
        }
    }
    // 打印
    for (int i = ups; i <= downs; i ++)
    {
        for (int j = lefts; j < tags[i]; j ++)
            printf("%c",maps[i][j]);
        puts("");
    }
    puts("");
}

int main()
{
    isPrime();         // 这么几个素数,这次就不用欧拉筛了
    drawmap();
    int T,n;
    scanf ("%d",&T);
    while ( T -- )
    {
        scanf("%d",&n);
        draw(n);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值