火龙果的小窝

火龙果——外而美,内则实

火龙果ID:bao110908
1976次访问,排名2万外好友127人,关注者245
爱好:玩,没事的时候看着食谱上的图解解眼馋。
另外,我最喜欢火龙果了,不但外表长得很漂亮,而且里面也很充实~~
bao110908的文章
原创 5 篇
翻译 0 篇
转载 1 篇
评论 18 篇
火龙果的公告
最近评论
hemaily:呵呵,很有创意啊........
bao110908:不是,旋转度在 18 度时会有些问题,哎,懒得改了,估计是计算精度方面的问题。锯齿问题,Java 在控制台中没有办法的,又不能让一个字符偏移半个字的。
billgacsli:牛文!!
学习了,知道了还有Scanner和Console类
要学的东西可真多~~~~~~~~~~~~
billgacsli:真佩服你的“编辑”功底!!
billgacsli:bug应该就是锯齿太严重吧?

这种图形处理中,很头痛的一个问题就是反锯齿,确实很头疼,貌似图形学中涉及过,总之是头大
文章分类
收藏
    相册
    Unicode
    数据库
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 博客首篇:控制台上“画”个五角星玩玩收藏

    新一篇: 法莱数列 | 

    刚开始学习语言的时候,老师都很喜欢让我们在控制台上使用“*”来输出某些图形,比如:三角形、菱形、方块什么的,这主要能让我们能更好地理解循环的语法和逻辑思维能力。

    这些图形基本上都是直线的,所以在控制台上可以很方便地进行输出,不知道有没有人想过在控制台上输出一条有斜率的斜线呢?

    在 AWT 上使用 Graphics 对象来做这些事的话是相当简单的,其中有内置的 drawLine 方法,告诉它 4 个点的坐标就可以很方便地在界面上画出一条斜线,但是在控制台我们如何做到这些呢?

    闲着没事的时候,写了一个在控制台上输出五角星的小程序,不过这里面有点小小的 bug,bug 是什么、究竟在什么地方呢?先买个关子吧,我弄了好久头都大了不想去想了,如果发现的话或者是解决了的话,别忘记告诉我哦~~

    顺便谨以此文作为博客的开篇祝贺!撒花~~

     Test.java 测试类

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

            Pentagram pen = new Pentagram(100' ''');
            
    // 在控制台上输出这个五角星

            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[i][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[i].length; j++
    ) {
                    System.out.print(canvas[i][j]);
                }
                System.out.println();
            }
        }
    }

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

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

    发表于 @ 2007年11月27日 16:49:00|评论(loading...)|收藏

    新一篇: 法莱数列 | 

    评论

    #CodingMouse 发表于2008-05-07 00:18:29  IP: 222.210.93.*
    太帅了!从未看到在控制台下打印五角星的。谢谢博主!学习ing...
    #Maojm 发表于2008-07-02 22:05:37  IP: 60.176.36.*
    bug是什么啊?
    是不是斜线不直? 这个要它直好像很难啊!
    #billgacsli 发表于2008-07-03 13:18:22  IP: 159.226.148.*
    bug应该就是锯齿太严重吧?

    这种图形处理中,很头痛的一个问题就是反锯齿,确实很头疼,貌似图形学中涉及过,总之是头大
    #bao110908 发表于2008-07-05 14:19:13  IP: 116.234.114.*
    不是,旋转度在 18 度时会有些问题,哎,懒得改了,估计是计算精度方面的问题。锯齿问题,Java 在控制台中没有办法的,又不能让一个字符偏移半个字的。
    #hemaily 发表于2008-07-23 21:44:45  IP: 58.247.207.*
    呵呵,很有创意啊........
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 火龙果