Java遞歸方法實現(xiàn)山脈繪制
本文實例為大家分享了Java遞歸方法實現(xiàn)山脈繪制的具體代碼,供大家參考,具體內(nèi)容如下
一、山脈繪制的思路
給定兩個點A(x1,y1),B(x2,y2),遞歸不斷取中點,同時給定一個范圍[-range,range]和一個比率rate。每次取中點后,這個中點的縱坐標的值加上這個范圍內(nèi)的隨機值,同時通過range=range*rate來縮小這個變化的范圍,最后,通過相鄰的點連線,繪制成一個山脈的形狀。
二、整段代碼如下
package com.yf1031; import java.awt.FlowLayout; import java.awt.Graphics; import java.util.Random; import javax.swing.JFrame; public class Drawpanel { ?? ?public static void main(String[] args) { ?? ??? ?Drawpanel drawpanel = new Drawpanel(); ?? ??? ?drawpanel.showUI(); ?? ??? ? ?? ?} ?? ? ?? ?public void showUI() { ?? ??? ?JFrame jf = new JFrame(); ?? ??? ?jf.setTitle("山脈"); ?? ??? ?jf.setSize(800, 800); ?? ??? ?jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ?? ??? ?jf.setLayout(new FlowLayout()); ?? ??? ?jf.setLocationRelativeTo(null); ?? ??? ? ?? ??? ?jf.setVisible(true); ?? ??? ? ?? ??? ?Graphics g = jf.getGraphics(); ?? ??? ?int xl = 10, yl =500 , xr = 750, yr = 600, range = 300; ?? ??? ?double rate = 0.5; ?? ??? ? ?? ??? ?try { ?? ??? ??? ?Thread.sleep(566); ?? ??? ?} catch (Exception e) { ?? ??? ??? ?// TODO: handle exception ?? ??? ??? ?e.printStackTrace(); ?? ??? ?} ?? ??? ? ?? ??? ?divide(xl, yl, xr, yr, g, range, rate); ?? ??? ? ?? ?} ?? ? ?? ?public void divide(int xl, int yl, int xr, int yr, Graphics g, int range, double rate) { ?? ??? ? ?? ??? ?if(Math.abs(xr - xl) <= 1 | range == 0) { ?? ??? ??? ?g.drawLine(xl, yl, xr, yr); ?? ??? ?}else { ?? ??? ??? ?int x=(xr+xl)/2; ?? ??? ??? ?int y = (yl+yr)/2; ?? ??? ??? ? ?? ??? ??? ?//按比例縮小range ?? ??? ??? ?Random rand = new Random(); ?? ??? ??? ?int num = rand.nextInt(range*2) - range; ?? ??? ??? ?range = (int)(range*rate); ?? ??? ??? ? ?? ??? ??? ?//與B點遞歸,迭代A點 ?? ??? ??? ?divide(x, y+num, xr, yr, g, range, rate); ?? ??? ??? ?//與A點遞歸,迭代B點 ?? ??? ??? ?divide(xl, yl, x, y+num, g, range, rate); ?? ??? ??? ? ?? ??? ?} ?? ?} }
結(jié)果為:
現(xiàn)在,我們來對整段代碼進行分析,這個整個代碼主要通過divide方法 進行遞歸取中點畫圖形,代碼如下:
public void divide(int xl, int yl, int xr, int yr, Graphics g, int range, double rate) { ?? ??? ? ?? ??? ?if(Math.abs(xr - xl) <= 1 | range == 0) { ?? ??? ??? ?g.drawLine(xl, yl, xr, yr); ?? ??? ?}else { ?? ??? ??? ?int x=(xr+xl)/2; ?? ??? ??? ?int y = (yl+yr)/2; ?? ??? ??? ? ?? ??? ??? ?//按比例縮小range ?? ??? ??? ?Random rand = new Random(); ?? ??? ??? ?int num = rand.nextInt(range*2) - range; ?? ??? ??? ?range = (int)(range*rate); ?? ??? ??? ? ?? ??? ??? ?//與B點遞歸,迭代A點 ?? ??? ??? ?divide(x, y+num, xr, yr, g, range, rate); ?? ??? ??? ?//與A點遞歸,迭代B點 ?? ??? ??? ?divide(xl, yl, x, y+num, g, range, rate); ?? ??? ??? ? ?? ??? ?} ?? ?}
在這段代碼中,我們首先需要去判斷一下傳入進來的兩個點A,B的橫坐標的差值是否小于等于1或者是變量range等于0,如果是,則直接畫線即可,因為像素最小單位就為1,不能用小數(shù)表示;否則,就要取遞歸取中點了,然后,通過給A,B兩個點上加上動態(tài)的變化量range,從而實現(xiàn)不停的遞歸畫線,最終形成了山脈的形狀。
三、實現(xiàn)山脈的填充功能
山脈填充功能的效果圖:
那它是如何實現(xiàn)該功能的呢?
那先來看一段代碼:
public void divide(int xl, int yl, int xr, int yr, Graphics g, int range, double rate) { ?? ??? ? ?? ??? ?if(Math.abs(xr - xl) <= 10 | range == 0) { ?? ??? ??? ?g.drawLine(xl, yl, xr, yr); ?? ??? ??? ?Polygon p = new Polygon(); ?? ??? ??? ?p.addPoint(xl, yl);//這里需要連接幾個點就添加幾個點,而且按一定的順序,順時針和逆時針都行 ?? ??? ??? ?p.addPoint(xl, 800); ?? ??? ??? ?p.addPoint(xr, 800); ?? ??? ??? ?p.addPoint(xr, yr); ?? ??? ??? ?g.fillPolygon(p); ?? ??? ??? ? ?? ??? ?}else { ?? ??? ??? ?int x=(xr+xl)/2; ?? ??? ??? ?int y = (yl+yr)/2; ?? ??? ??? ? ?? ??? ??? ?//按比例縮小range ?? ??? ??? ?Random rand = new Random(); ?? ??? ??? ?int num = rand.nextInt(range*2) - range; ?? ??? ??? ?range = (int)(range*rate); ?? ??? ??? ? ?? ??? ??? ?//與B點遞歸,迭代A點 ?? ??? ??? ?divide(x, y+num, xr, yr, g, range, rate); ?? ??? ??? ?//與A點遞歸,迭代B點 ?? ??? ??? ?divide(xl, yl, x, y+num, g, range, rate); ?? ??? ??? ? ?? ??? ?} ?? ?}
根據(jù)上述的這段代碼,我們可以看到本文利用Polygon類創(chuàng)建了一個對象,Polygon類封裝了對坐標空間內(nèi)封閉的二維區(qū)域的描述。 該區(qū)域由任意數(shù)量的線段界定,每個線段都是多邊形的一側(cè)。 在內(nèi)部,多邊形由(x,y)個坐標對列表組成,其中每對坐標定義了多邊形的頂點,兩個連續(xù)的對是作為多邊形側(cè)面的線的端點。 (x,y)點的第一對和最后一對通過封閉多邊形的線段相連。 當這四個點按一定順序(順時針和逆時針都行)連接起來,然后利用fillPolygon方法進行填充,最終得到了上面山脈填充效果圖。
四、使用緩沖圖片畫圖
我們都知道,當你需要畫好幾張圖片的時候,會發(fā)現(xiàn)畫的速度很慢,這個時候BufferedImage類就應運而生,Java中畫圖一般會使用該類創(chuàng)建對象去實現(xiàn)更快的畫圖。
它的原理: 是先將一幅圖片加載到內(nèi)存中(BufferedImage生成的圖片在內(nèi)存里有一個圖像緩沖區(qū),利用這個緩沖區(qū)我們可以很方便地操作這個圖片),提供獲得繪圖對象、圖像縮放、選擇圖像平滑度等功能,通常用來做圖片大小變換、圖片變灰、設置透明不透明等。
關(guān)鍵程序的代碼為:
//創(chuàng)建緩沖圖片 BufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_RGB); //獲取緩沖圖片的畫筆 Graphics buffg = bufferedImage.getGraphics(); divide(xl, yl, xr, yr, buffg, range, rate); //將緩沖圖片畫在窗體上 g.drawImage(bufferedImage, 0, 0, null);?
讀者可以自己結(jié)合上面的 “二、整段代碼” 去比較所改動的地方,除了這段關(guān)鍵的代碼改動了,其余并沒有改動
實現(xiàn)的效果圖為:
看到這樣的效果圖,我發(fā)現(xiàn)跟我之前所畫的山脈不一樣,“三、山脈填充功能” 所畫的山脈是黑色來填充,白色為天空,但我現(xiàn)在所畫的這個就剛剛相反,剛開始的我百思不得其解,因此,我想這給這個填充色不要弄成默認的填充色,而是設置成藍色,則效果圖如下:
這個圖與上面的圖片進行對比,可以得到的結(jié)論是: 當使用BufferedImage類來創(chuàng)建緩沖圖片時,緩沖圖片的背景色就是黑色,而當你使用默認的填充時,Java中為了區(qū)分,會將默認填充黑色改為默認填充白色,只是為了做區(qū)分而已,而當你將填充的顏色改為藍色,那么下面就是藍色了,不再是白色了。
通過上面的實驗,得到一個結(jié)論: 當你的程序出現(xiàn)了跟你的預期結(jié)果不一致的時候,你可以去多做實驗,多設置輸出來弄清楚自己編寫代碼什么時候出錯了?。?!
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java中URLencode、URLdecode及Base64加解密轉(zhuǎn)換
本文主要介紹了java中URLencode、URLdecode及Base64加解密轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-01-01java8新特性 stream流的方式遍歷集合和數(shù)組操作
這篇文章主要介紹了java8新特性 stream流的方式遍歷集合和數(shù)組操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08java 定義長度為0的數(shù)組/空數(shù)組案例
這篇文章主要介紹了java 定義長度為0的數(shù)組/空數(shù)組案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03SpringBoot favicon Chrome設置問題解決方案
在本篇文章里小編給大家分享的是關(guān)于SpringBoot favicon Chrome設置問題實例內(nèi)容,小的朋友們可以參考學習下。2020-02-02Java打包之后讀取Resources下的文件失效原因及解決方法
這篇文章主要給大家介紹了Java打包之后讀取Resources下的文件失效的問題分析和解決方法,文中通過代碼示例和圖文結(jié)合給大家講解非常詳細,需要的朋友可以參考下2023-12-12數(shù)據(jù)結(jié)構(gòu)與算法之手撕排序算法
排序算法看似簡單,其實不同的算法中蘊涵著經(jīng)典的算法策略。通過熟練掌握排序算法,就可以掌握基本的算法設計思想,本文主要介紹了Java中的排序算法,需要的朋友歡迎閱讀2023-04-04使用SpringBoot項目導入openfeign版本的問題
這篇文章主要介紹了使用SpringBoot項目導入openfeign版本的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03