java心形打印999


心形打印999

農歷七月初七,七夕節也就是中國民間版的所謂情人節,利用java打印心型999個圖案可以讓程序員更浪漫一些。現在下面由小編簡要的說一下如何做到。
首先下面是打印心形但卻不是999個
的代碼,然后在上面將其修改就好了。

 注意:
1.愛心的公式 (x²+y²-1)³-x²*y³=0 
2.x和y的取值范圍[-1.5, 1.5]
原型代碼:

/* 程序Ⅰ,程序可以在控制台打印由*號構成的心形圖案。*/
public class HeartV1 {
    /* 愛心的公式 (x²+y²-1)³-x²*y³=0 */
    public static void main(String[] args) {
        int cx = 0, cy = 0; // 問y 、 x 總共循環了多少次
        float dx = 0.05f, dy = 0.1f;
        int stars=0;//計數器
        for (float y = (float)1.5; y > -1.5; y -= dy, cy++){
            cx = 0;
            for (float x = (float) -1.5; x < 1.5; x += dx, cx++){
                float a = x * x + y * y - 1;
                if ((a * a * a - x * x * y * y * y) <= 0.0){
                    System.out.print("*");// 心形區域內打印*
                    stars++;
                } else{
                    System.out.print(" "); // 心形區域外打印空格
                }
            }
            System.out.println("");    // 本行結束,換行准備下一行的輸出
        }
        
        System.out.printf("cx=%d, cy=%d%n", cx, cy);
        System.out.printf("count=%d", stars);
    }
}

該程序可以正常執行得到的輸出結果如下:
在這里插入圖片描述
cx=61, cy=30
stars=736
最后一行輸出的cx和cy表示y循環(最外層循環)次數是30次;cx表示每次外循環需要執行的x循環(內層循環)次數是61次。

於是利用java打印心型999個*圖案總體思想就是調整原版程序x和y的循環次數,其它參數保持不變,比如x和y的取值范圍[-1.5, 1.5]不變,即調整dx或/和dy。

△第一種參數修改:保持dx也不變,確定能輸出999個*號的心形圖案的最小的dy。結果保留7位小數。

(1)首先,提點一下此問題的解決思路,以便更好閱讀程序。更詳細的算法解讀可以到下面的代碼后面看算法描述。按問題要求,dx 不變,要去確定最小的 dy,這里其實提示了你 dy 要在一個基數上向上增加(其實降低了難度,如果要判斷 dy 要增加,即 y 要減少,還需做一兩次測試才能確定),基本思路就是,不停增加 y 的變化量——即增加 dy,因為要保留 7 位小數,於是只要 dy 的增加量是0.0000001 即可。這樣得到最小的可以打印出心形的dy。
計算最小dy的代碼:
【算法描述】結合程序,簡單描述一下,
(1)首先,為了每一個 dy,我們都要嘗試去“打印”一遍心型循環(打印加引號是指我們不必真要輸出,要不然命令行很難看,我們只走循環,並對計數,走完了循環且等於了 999 就可結束。
(2)其次,我們就不能固定 dy 了,而要讓 dy 變化,且因為按題意,只要 7 位小數,所以 dy的變化步長取為 0.0000001f。
(3)再次,dy 到底是增量還是減量呢?這里就有一個訣竅,在問題 1 的程序基礎上,把 dy 增大或減小,觀察
號計數,最終確定 dy 可以在 0.05 基礎上,不停累加 0.0000001f,對每次累加,都去執行“打印”心型程序,然后判斷該程序循環走完時號計數是否是 999,如果執行過程中號計數超過了999 就立即返回,增量到下一個 dy;如果程序循環走完時,*號數不是 999 也要返回不滿足要求的標記。
(4)最后,觀察主程序,套用一個大循環去枚舉 dy 的每一個 0.0000001f 增量。因為是 7 位小數,所以理論上最大到 Integer.MAX_VALUE(即 2147483647)就可以了。

public class B03EE2s1 {
/**
* 適用暴力獲取指定total數的心型參數
* @param s0//@Param:用來在DAO層中聲明參數
* @param dx
* @param dy
* @param total
* @return
*/
public static boolean heart(float s0, float dx, float dy, int total){
    int stars = 0;
    int cx = 0, cy = 0; // 問y 、 x 總共循環了多少次
    float e0 = -s0;
    for (float y = s0; y > e0; y -= dy, cy++) {
        cx = 0;
        for (float x = e0; x < s0; x += dx, cx++) {
            float a = x * x + y * y - 1;
            if ((a * a * a - x * x * y * y * y) <= 0.0) {
                //System.out.print("*");
                stars++; // *計數
                /* 此處不能用=比較,原因在於等於999的*號未必
                 * 就是心形的圖案,必須是走完循環才能出心形圖案。 */
                if(stars > total){
                    return false; // 已經超過,直接返回
                }
            } else{
                //System.out.print(" ");//這里個源文件主要來計算dy值不是來輸出的所以這里可以不用輸出直接空過
            }
        }
    }
    System.out.printf("cx=%d, cy=%d, stars=%d%n", cx, cy, stars);
    if(stars != total){
        return false; // 不等於返回false
    }else {
        return true;
    }
    }
public static void main(String[] args) {
    /* 為了找到含有999顆*的心型參數,不斷枚舉——暴力方式。 */
    int total = 999, loops = 0; // *的總數,loops=循環次數,超過int的MAX退出for
    /* 0.1是736顆,再試一下0.06,也是*增多,但是比0.05要少,所以應該增量dy,故原版程
    序y是要不停往下遞減才能讓*增多 */
    float dy = 0.05f;
    float sdy = 0.0000001f; // 保留7位,我們就從這個開始對
    float s0 = 1.5f, dx = 0.05f;
    for(; loops++ < Integer.MAX_VALUE; dy += sdy) {
        System.out.printf("loops=%d, dx=%.7f, dy=%.7f%n", loops, dx, dy);
        if(heart(s0, dx, dy, total)) {
            break;
        }
    }
    }
}

即可得到最后兩行的結果是:

在這里插入圖片描述
可知最小 dy 的值就是紅色線所示。不用再往大的 dy 找了。
(2)接着打印出來999個*心形

import java.util.*;
public class HeartV2 {
/* 愛心的公式 (x²+y²-1)³-x²*y³=0 */
public static void main(String[] args) {
    int stars = 0;
    int cx = 0, cy = 0; // 問y 、 x 總共循環了多少次
    float dx = 0.05f;
    float dy = 0.0735288f; /*【2】 f;*/ /* 原dy = 0.1f,這個有7位小數的float
    數dy是能輸出999個*之心圖案的最小數。f表示單精度浮點類型常量后綴 */
for (float y = (float)1.5; y > -1.5; y -= dy, cy++){
    cx = 0;
for (float x = (float) -1.5; x < 1.5; x += dx, cx++){
    float a = x * x + y * y - 1;
    if ((a * a * a - x * x * y * y * y) <= 0.0){
    System.out.print("*");// 心形區域內打印*
    stars++;
} else{
    System.out.print(" "); // 心形區域外打印空格
}
}
    System.out.println(""); // 本行結束,換行准備下一行的輸出
}
// 打印包括*數的信息
    System.out.printf("stars=%d, cx=%d, cy=%d%n", stars, cx, cy);
}
}

執行結果:
stars=999, cx=61, cy=41
此時:stars=999, cx=61, cy=41
最后一行顯示有999個*號,而且x循環不變,但是縱向的y循環變成了41次,這就導致輸出的心形圖案呈現廋扁狀。
你的意中人未必滿意喲!

△第二種參數修改:觀察原版程序及原理和輸出,我們調整dx和dy並保持dx:dy=1:2不變,確定能輸出999個*號的心形圖案的最小的dx和dy。結果保留7位小數。

這個問題比問題 2 稍微復雜“一丟丟”,即保持 dy:dx=2 即可,這樣確定了 dx 就知道 dy。
(1)先計算dx和dy代碼(跟修改參數一時的算法思想差不多):

public class B03EE2s3 {
/**
* 適用暴力獲取指定total數的心型參數
* @param s0//@Param:用來在DAO層中聲明參數
* @param dx
* @param dy
* @param total
* @return
*/
public static boolean heart(float s0, float dx, float dy, int total){
    int stars = 0;
    int cx = 0, cy = 0; // 問y 、 x 總共循環了多少次
    float e0 = -s0;
    for (float y = s0; y > e0; y -= dy, cy++) {
        cx = 0;
        for (float x = e0; x < s0; x += dx, cx++) {
            float a = x * x + y * y - 1;
            if ((a * a * a - x * x * y * y * y) <= 0.0) {
                //System.out.print("*");
                stars++; // *計數
                /* 此處不能用=比較,原因在於等於999的*號未必
                 * 就是心形的圖案,必須是走完循環才能出心形圖案。 */
                if(stars > total){
                    return false; // 已經超過,直接返回
                }
            } else{
                //System.out.print(" ");//這里個源文件主要來計算dy值不是來輸出的所以這里可以不用輸出直接空過
            }
        }
    }
    System.out.printf("cx=%d, cy=%d, stars=%d%n", cx, cy, stars);
    if(stars != total){
        return false; // 不等於返回false
    }else {
        return true;
    }
    }
public static void main(String[] args) {
    /* 為了找到含有999顆*的心型參數,不斷枚舉——暴力方式。 */
    int total = 999, loops = 0; // *的總數,loops=循環次數,超過int的MAX退出for
    /* 0.1是736顆,再試一下0.06,也是*增多,但是比0.05要少,所以應該增量dy,故原版程
    序y是要不停往下遞減才能讓*增多 */
    float dx = 0.05f;
    float sdx = 0.0000001f; // 保留7位,我們就從這個開始對
    float s0 = 1.5f, dy = 2*dx;
    for(; loops++ < Integer.MAX_VALUE; dx -= sdx) {
        System.out.printf("loops=%d, dx=%.7f, dy=%.7f%n", loops, dx, dy);
        if(heart(s0, dx, dy, total)) {
            break;
        }
    }
    }
}

執行結果:
在這里插入圖片描述
(2)接着打印出來999個*心形

import java.util.*;
public class HeartV3 {
/* 愛心的公式 (x²+y²-1)³-x²*y³=0 */
public static void main(String[] args) {
    int stars = 0;
    int cx = 0, cy = 0; // 問y 、 x 總共循環了多少次
    float dx = 0.0368397f;
    float dy = 0.1000000f; /*【2】 f;*/ /* 原dy = 0.1f,這個有7位小數的float
    數dy是能輸出999個*之心圖案的最小數。f表示單精度浮點類型常量后綴 */
for (float y = (float)1.5; y > -1.5; y -= dy, cy++){
    cx = 0;
for (float x = (float) -1.5; x < 1.5; x += dx, cx++){
    float a = x * x + y * y - 1;
    if ((a * a * a - x * x * y * y * y) <= 0.0){
    System.out.print("*");// 心形區域內打印*
    stars++;
} else{
    System.out.print(" "); // 心形區域外打印空格
}
}
    System.out.println(""); // 本行結束,換行准備下一行的輸出
}
// 打印包括*數的信息
    System.out.printf("stars=%d, cx=%d, cy=%d%n", stars, cx, cy);
}
}

執行結果:

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

stars=999, cx=82, cy=30

完事哈哈哈啊哈哈哈


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM