Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 404|回复: 0

[Swing学习]控制台上“画”五角星

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-10 23:56:59 | 显示全部楼层 |阅读模式
    刚开始学习语言的时候,老师都很喜欢让我们在控制台上使用“*”来输出某些图形,比如:三角形、菱形、方块什么的,这主要能让我们能更好地理解循环的语法和逻辑思维能力。     这些图形基本上都是直线的,所以在控制台上可以很方便地进行输出,不知道有没有人想过在控制台上输出一条有斜率的斜线呢? 在 AWT 上使用 Graphics 对象来做这些事的话是相当简单的,其中有内置的 drawLine 方法,告诉它 4 个点的坐标就可以很方便地在界面上画出一条斜线,但是在控制台我们如何做到这些呢? 闲着没事的时候,写了一个在控制台上输出五角星的小程序,不过这里面有点小小的 bug,bug 是什么、究竟在什么地方呢?先买个关子吧,我弄了好久头都大了不想去想了,如果看官们发现的话或者是解决了的话,别忘记告诉我哦~~ Test.java 测试类


      public class
       Test {
         public static void
       main(String[] args) {
             // 画一个半径为10,旋转为0,空白为全身空格,填充为★的五角星
      

              Pentagram pen = new Pentagram(10, 0, " ", "★"
      );
             // 在控制台上输出这个五角星
      

              Draw.printCanvas(pen.getPentagram());
         }
    }
      
    Pentagram.java 五角星类


      
      public class
      
       Pentagram {
         private final char FILL_CHAR;   // 填充字符
      

      
          private final char SPACE_CHAR;  // 空档字符
      

      
          private final int R;            // 五角星的外接圆半径
      

      
          private final float ROTATION;   // 五角星逆时针旋转角度
      

      
          private final int X;            // 用于生成画图数组
      

      
          private final int Y;            // 用于生成画图数组
      

      
          
         /**
      
          * 构造一个Pentagram对象
          *
      @param
      
       radius 五角星的半径
          * @param
      
       rotation 五角星的逆时针旋转度数
          * @param
      
       spaceChar 画布上空白处填充字符
          * @param
      
       fillChar 画布上线条部分填充字符
          */
      
         
      
      public Pentagram(int radius, float rotation, char spaceChar, char
      
       fillChar) {
             this.R =
      
       radius;
             this.ROTATION =
      
       rotation;
             this.FILL_CHAR =
      
       fillChar;
             this.SPACE_CHAR =
      
       spaceChar;
             this.X = 2 * R + 1
      
      ;
             this.Y = 2 * R + 1
      
      ;
         }
         

         public char
      
      [][] getPentagram() {
             char[][] canvas =
      
       initCanvas();
             Draw draw = new
      
       Draw(FILL_CHAR);
             //
      
       设五角星的最右边的一个点为 A,逆时针选取点 B~E
             //
      
       通过圆的极坐标公式可以得出:
             //
      
       得出以下各点的坐标
             //
      
       A 点坐标(0.951R, 0.309R)
             //
      
       B 点坐标(0, R)
             //
      
       C 点坐标(-0.951R, 0.309R)
             //
      
       D 点坐标(-0.588R, -0.809R)
             //
      
       E 点坐标(0.588R, -0.809R)
             
             // 画线段CA
      

      
              draw.drawLine(mcos(162) * R, msin(162) * R, mcos(18) * R, msin(18) *
      
       R, canvas);
             // 画线段DA
      

      
              draw.drawLine(mcos(234) * R, msin(234) * R, mcos(18) * R, msin(18) *
      
       R, canvas);
             // 画线段CE
      

      
              draw.drawLine(mcos(162) * R, msin(162) * R, mcos(306) * R, msin(306) *
      
       R, canvas);
             // 画线段DB
      

      
              draw.drawLine(mcos(234) * R, msin(234) * R, mcos(90) * R, msin(90) *
      
       R, canvas);
             // 画线段BE
      

      
              draw.drawLine(mcos(90) * R, msin(90) * R, mcos(306) * R, msin(306) *
      
       R, canvas);
             return
      
       canvas;
         }

         //
      
       在方形的字符数组中指定两点画线条
         // 对图形数组进行初始化,填充空格
      

      
          private char
      
      [][] initCanvas() {
             char[][] canvas = new char
      
      [Y][X];
             for (int i = 0; i < Y; i++
      
      ) {
                 for (int j = 0; j < X; j++
      
      ) {
                     canvas[j] =
      
       SPACE_CHAR;
                 }
             }
             return
      
       canvas;
         }

         // 根据角度求正弦值,保留两位小数
      

      
          private double msin(float
      
       a) {
             return ((int) (Math.sin(Math.toRadians(a + ROTATION)) * 100)) / 100.0
      
      ;
         }

         // 根据角度求余弦值,保留两位小数
      

      
          private double mcos(float
      
       a) {
             return ((int) (Math.cos(Math.toRadians(a + ROTATION)) * 100)) / 100.0
      ;
         }
    }
      
       Draw.java 画图工具类


      public class
       Draw {   
         
         private char
       fillChar;
         
         public Draw(char
       fillChar) {        
             this.fillChar =
       fillChar;
         }

         /**
      
          * 根据两个点画线在二维字符数组上画线
          *
      @param
       x1
          * @param
       y1
          * @param
       x2
          * @param
       y2
          * @param
       canvas
          */
      
         
      public void drawLine(double x1, double y1, double x2, double y2, char
      [][] canvas) {
             int radius = (canvas.length - 1) / 2
      ;
             // 从 x 方向进行填充
      

              if (x1 >
       x2) {
                 double t =
       x1;
                 x1 =
       x2;
                 x2 =
       t;
                 t =
       y1;
                 y1 =
       y2;
                 y2 =
       t;
             }

             // 获得直线方程的两个系数
      

              double a = (y1 - y2) / (x1 -
       x2);
             double b = y1 - a *
       x1;

             // 根据 x 方向的值求出 y 值,并填充图形
      

              for (int i = (int) Math.round(x1); i <= (int) Math.round(x2); i++
      ) {
                 // 根据直线方程 y = ax + b,求 y
      

                  int y = (int) Math.round(a * i +
       b);

                 //
       因为 y 和 i 算出来的结果有可能是负数,
                 //
       为了采用数组来表示坐标,做了以下变换
                 //
       c[R][R] 即为坐标原点
                 //
       c[R][0..R] 为 x 方向的负半轴
                 //
       c[R][R+1..2*R] 为 x 方向的正半轴
                 //
       c[0..R][R] 为 y 方向的正半轴
                 // c[R+1..2*R][R] 为 y 方向的负半轴
      

                  int yy = radius -
       y;
                 int xx = radius +
       i;

                 yy = yy < 0 ? 0
       : yy;
                 yy = yy > 2 * radius ? 2 *
       radius : yy;
                 xx = xx < 0 ? 0
       : xx;
                 xx = xx > 2 * radius ? 2 *
       radius : xx;

                 canvas[yy][xx] =
       fillChar;
             }

             // 从 y 方向进行填充,便于减少间距问题产生的字符空档
      

              if (y1 >
       y2) {
                 double t =
       x1;
                 x1 =
       x2;
                 x2 =
       t;
                 t =
       y1;
                 y1 =
       y2;
                 y2 =
       t;
             }

             // 根据 y 方向的值求出 x 值,并填充图形
      

              for (int i = (int) Math.round(y1); i <= (int) Math.round(y2); i++
      ) {
                 // 根据 x = (y - b) / a,求 x
      

                  int y = (int) Math.round((i - b) /
       a);

                 int yy = radius -
       i;
                 int xx = radius +
       y;

                 yy = yy < 0 ? 0
       : yy;
                 yy = yy > 2 * radius ? 2 *
       radius : yy;
                 xx = xx < 0 ? 0
       : xx;
                 xx = xx > 2 * radius ? 2 *
       radius : xx;

                 canvas[yy][xx] =
       fillChar;
             }
         }
         
         /**
      
          * 将画完图之后的画布输出到控制台上
          *
      @param
       canvas
          */
      
         
      public static void printCanvas(char
      [][] canvas) {
             for (int i = 0; i < canvas.length; i++
      ) {
                 for (int j = 0; j < canvas.length; j++
      ) {
                     System.out.print(canvas[j]);
                 }
                 System.out.println();
             }
         }
    }
      

      下图是一个半径为 20,旋转度为 0 度的五角星控制台输出。 下图是一个半径为 20,旋转度为 15 度的五角星控制台输出。

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1904452

      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/11/10/235658937.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 08:07 , Processed in 0.362985 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表