AcWing 727. 菱形——像拼图一样做题

题目描述


分析:

利用程序根据输入的整数,画出由字符*构成的该整数阶的实心菱形。给出一个示例: n = 7 n=7 n=7

      *       
    * * *     
  * * * * *   
* * * * * * * 
  * * * * *   
    * * *     
      *       

我们将采取拆解问题,通过四个部分的组合最终拼出这个菱形。通过观察,可以看出不管给出的整数是多少,最终形成的图形一定是一由空格 和星星*构成个正方形(记为s)。如图1所示。
在这里插入图片描述

图1 正方形
#### 拼出第一部分-对角线 另外我们可以知道正方形有两条相交的对角线,它将正方形分成了四个相等的部分。如图2所示。

在这里插入图片描述

图2 对角线示意

基于此我们可以先将这两条对角线画出来,是不是就成功了一半了呢?这两条对角线也很容易画,一条线是 x = 3 ( n / 2 ) x=3(n/2) x=3(n/2),另一条是 y = n / 2 y=n/2 y=n/2。给出画对角线的代码:

	for (int i = 0; i < n; i ++) { // 画出十字架对角线
		for (int j = 0; j < n; j ++) {
			if (i == n / 2 || j == n / 2) res[i][j] = '*';
		}
	}

通过这一步画出的图形为:

      *       
      *       
      *       
* * * * * * * 
      *       
      *       
      *       
拼出第二部分-左上角

有了这两条相交的对角线,我们只需要处理左上角需要描的点即可,然后利用相交的对角线通过关于 x x x轴对称与 y y y轴对称的方法映射到其他的三个区域!如图3所示。

在这里插入图片描述

图3 x、y映射

那么该怎么计算左上角的该描的点呢?我们可以观察这三个点的坐标 ( 1 , 2 ) , ( 2 , 1 ) , ( 2 , 2 ) {(1,2), (2,1), (2, 2)} (1,2),(2,1),(2,2),也可以表示为 ( 1 , n / 2 − 1 ) , ( 2 , 1 ) , ( 2 , n / 2 − 1 ) {(1,n/2-1), (2,1), (2, n/2-1)} (1,n/21),(2,1),(2,n/21)。因此可以用双层循环进行遍历,伪代码如下:

	// 左上角描点
	for (int i = 1; i <= n / 2 - 1; i ++) { // 1到n/2-1行
		for (int j = n / 2 - 1; j>= n / 2 - i; j --) { // 倒着来,从n/2-1到n/2-i列
			res[i][j] = '*';
		}
	}

经过这一步,我们所画出来的图形为:

      *       
    * *       
  * * *       
* * * * * * * 
      *       
      *       
      *       
拼出第二部分-右上角

当我们画出左上角后,可以将 n / 2 n/2 n/2视作 y y y轴,进行关于y轴的对称实现映射效果。具体流程为:先遍历一遍左上角,遇到为*的就进行映射,只需要更改列的坐标即可,给出代码:

        for (int i = 1; i <= n / 2 - 1; i ++) { // 对称到右上角
            for (int j = 1; j <= n / 2 - 1; j ++) {
                if (res[i][j] == '*') {
                    res[i][n / 2 + (n / 2 - j)] = res[i][j];
                }
            }
        }

此时生成的图形为:

      *       
    * * *     
  * * * * *   
* * * * * * * 
      *       
      *       
      *       
接下来该怎么拼?

后面有多种拼法,可以先做左上角/右上角关于 x x x轴的对称,映射到左下角/右下角。这里我将上半部分当作一个整体,进行 x x x轴对称,一步到位!代码为:

	for (int i = 1; i <= n - 1; i ++) { // 对称到整个下方
		for (int j = 1; j <= n - 1; j ++) {
			if (res[i][j] == '*') {
				res[n / 2 + (n / 2 - i)][j] = res[i][j];
			}
		}
	}

图像为:

      *       
    * * *     
  * * * * *   
* * * * * * * 
  * * * * *   
    * * *     
      *      

至此,菱形就被我们画出来。这道题有需要不同的画法,上面只是笔者自己的理解,关于其他更优雅更简洁的方法请大家开动脑筋去尽情尝试吧!!

代码(Java)

import java.util.*;

public class Main {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int x = n / 2;
        char[][] res = new char[n][n];

        for (int i = 0; i < n; i ++) { // 画出十字架
            for (int j = 0; j < n; j ++) {
                if (i == n / 2 || j == n / 2) res[i][j] = '*';
            }
        }

        for (int i = 1; i <= n / 2 - 1; i ++) { // 左上角
            for (int j = n / 2 - 1; j>= n / 2 - i; j --) {
                res[i][j] = '*';
            }
        }

        for (int i = 1; i <= n / 2 - 1; i ++) { // 对称到右上角
            for (int j = 1; j <= n / 2 - 1; j ++) {
                if (res[i][j] == '*') {
                    res[i][n / 2 + (n / 2 - j)] = res[i][j];
                }
            }
        }

        for (int i = 1; i <= n - 1; i ++) { // 对称到整个下方
            for (int j = 1; j <= n - 1; j ++) {
                if (res[i][j] == '*') {
                    res[n / 2 + (n / 2 - i)][j] = res[i][j];
                }
            }
        }


        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < n; j ++) {
                if (res[i][j] == '*') System.out.print('*');
                else System.out.print(' ');
            }
            System.out.println();
        }
    }
}
  • 19
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值