打印十字图

问题描述
小明为某机构设计了一个十字型的徽标,如下所示:

..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..

对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。 

输入格式
一个正整数 n (n < 30) ,表示要求打印图形的层数
输出格式
对应包围层数的该标志

样例输入
1
样例输出
..$$$$$..
..$...$..
$$$.$.$$$
$...$...$
$.$$$$$.$
$...$...$
$$$.$.$$$
..$...$..
..$$$$$..

注:本文参考于https://blog.csdn.net/the_ZED/article/details/104149128
题目分析:
把题目的图形变形一下就可以很清楚地看到十字了

请添加图片描述

(1)当 n = 1 时 (为了让这个图更加直观,重新画了这个图)

在这里插入图片描述
中间十字的位置是固定的,它的坐标是(N / 2 + 1, N / 2 + 1)
假设当图像的规格为 N*N ,且储存在二维数组中的横坐标均从1开始

那么打印中间黄色十字架的代码为

for (int i = N/2 -1; i <= N/2 + 3; i++) {
            cross[N/2 + 1][i] = cross[i][N/2 + 1] = $;
        }
2.当 n = 2 时,观察黄色部分

在这里插入图片描述
假设从最外面的层数到最里面的层数分别为 1 , 2 , 3 , …… ,n-3 , n-2 , n-1 , n(图像规格 N* N)
假设当前为第 i 层,那第 i 层的四个黄色部分边角坐标与 i 和 N 的关系如下:

(1)左上角的边角(格子1)坐标为(x ,y), x = 2 i + 1 , y = 2 i + 1
格子1 上面的格子左边(x - 1 , y), 格子1 左面的格子左边(x , y - 1)

(2)右上角的边角(格子2)坐标为(x ,y), x = 2 i + 1 , y = N - 2 i
格子2 上面的格子左边(x - 1 , y), 格子1 左面的格子左边(x , y +1)

(3)右上角的边角(格子3)坐标为(x ,y), x = N - 2 i , y = N - 2 i
格子3 上面的格子左边(x + 1 , y), 格子1 左面的格子左边(x , y +1)

(4)右上角的边角(格子4)坐标为(x ,y), x = N - 2 i , y = 2 i + 1
格子4 上面的格子左边(x + 1 , y), 格子1 左面的格子左边(x , y - 1)

那么这四个边角位置的打印代码 如下:

        for (int i = 1; i <= n; i++) {
           int x = 2 * i + 1;
           int y = 2 * i + 1;
           
           //左上角
            cross[x][y] = cross[x][y-1] = cross[x-1][y] = 1;
            //右上角
            y = N - 2 * i;
            cross[x][y] = cross[x][y+1] = cross[x-1][y] = 1;
            //左下角
            y = 2 * i  + 1;
            cross[x][y] = cross[x][y-1] = cross[x+1][y] = 1;
            //右下角
            x = N - 2 * i;
            cross[x][y] = cross[x][y+1] = cross[x+1][y] = 1;
        }
3. 当 n = 3 时,观察下图黄色部分

在这里插入图片描述

同样假设从最外面的层数到最里面的层数分别为 1 , 2 , 3 , …… ,n-3 , n-2 , n-1 , n(图像规格 N* N)
最外层4条黄色的边长度都一样,都是 N - 4个格子 (层数逐渐往里时减去的格子数量也逐渐增加)

(1)十字架上方黄色部分
行数:第一层黄色部分的行数是 1 ,第二层黄色部分的行数是 3 ,第一层黄色部分的行数是 5 ,即十字架上方黄色部分的行数随着层数的增加其变化规律是: 2* i - 1 (i 为当前十字架的层数)
列数:起点坐标:2* i + 1,终点坐标 :N - 2* i

打印十字架上方黄色部分的代码

for (int i = 1; i <= n; i++) {
            for (int j = 2*i + 1; j <= N - 2*i ; j++) {
                corss[2*i - 1][j] = 1;
            }
        }

(2)十字架右方黄色部分
行数:起点坐标 2* i + 1 , 终点坐标 N - 2* i
列数:第一层列数 N ,第二层 N - 2,第三层 N - 4,变化规律:N - 2 * (i - 1)

 for (int i = 1; i <= n; i++) {
            for (int j = 2*i - 1; j <= N - 2*i ; j++) {
                cross[j][N - 2*(i - 1)] = 1;
            }
        }

(3)十字架下方黄色部分
行数:第一层列数 N ,第二层 N - 2,第三层 N - 4,变化规律:N - 2 * (i - 1)
列数:起点坐标 2* i + 1 , 终点坐标 N - 2* i

 for (int i = 1; i <= n; i++) {
            for (int j = 2*i + 1; j <= N - 2*i ; j++) {
                cross[N - 2*(i - 1)][j] = 1;
            }
        }

(4)十字架左方黄色部分
行数:起点坐标 2* i + 1 , 终点坐标 N - 2* i
列数:第一层黄色部分的行数是 1 ,第二层黄色部分的行数是 3 ,第一层黄色部分的行数是 5 ,即十字架上方黄色部分的行数随着层数的增加其变化规律是: 2* i - 1

for (int i = 1; i <= n; i++) {
            for (int j = 2*i + 1; j <= N - 2*i ; j++) {
                corss[j][2*i - 1] = 1;
            }
        }

行列变化时,外层条件一致
把行列变化放到一个循坏体中

 for (int i = 1; i <= n; i++) {
            for (int j = 2*i + 1; j < N - 2*i; j++) {
                cross[2*i -1][j] = cross[j][N - 2*(i - 1)] 
                = cross[N - 2*(i - 1)][j] = cross[j][2*i - 1] = true;
            }
        }
完整代码
import java.util.Scanner;

public class PrintCrossGraphics {
    final int MAX = 130;
    boolean[][] cross = new boolean[MAX][MAX];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt();
        PrintCrossGraphics print = new PrintCrossGraphics();
        print.PrintCross(n);

    }

    //打印十字图形
    public  void PrintCross(int n){
        int N = 5 + 4 * n; //通过n计算打印图形的规格(N * N)

        //中间十字架
        for (int i = N/2 -1; i <= N/2 + 3; i++) {
            cross[N/2 + 1][i] = cross[i][N/2 + 1] = true;
        }

        //四个边角
        for (int i = 1; i <= n; i++) {

            int x = 2 * i + 1;
            int y = 2 * i + 1;
            //左上角
            cross[x][y] = cross[x][y-1] = cross[x-1][y] = true;
            //右上角
            y = N - 2 * i;
            cross[x][y] = cross[x][y+1] = cross[x-1][y] = true;
            //右下角
            x = N - 2 * i;
            cross[x][y] = cross[x][y+1] = cross[x+1][y] = true;
            //左下角
            y = 2 * i  + 1;
            cross[x][y] = cross[x][y-1] = cross[x+1][y] = true;


            //行列变化的循坏体
                for (int j = 2*i + 1; j <= N - 2*i; j++) {
                    cross[2*i -1][j] = cross[j][N - 2*(i - 1)] =
                            cross[N - 2*(i - 1)][j] = cross[j][2*i - 1] = true;
                }

        }

        //打印
        for (int i = 1; i <= N ; i++) {
            for (int j = 1; j <= N; j++) {
                if (cross[i][j]  )
                    System.out.print("$");
                else
                System.out.print(".");
            }
            System.out.print("\n");
        }
    }
}

运行结果
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值