Zadání
Vytvořte program na naplnění a tisk matice znaků o rozměru 25*70. Automatickým plněním vhodnými znaky do matice znázorníte kruh o průměru 1.
Vstup: žádný
Výstup: Tisk matice s pseudografickým obrazem kruhu:
Teorie
Vzhledem k rozměrům matice (70x25) nepůjde tak úplně o kruh, ale spíše o elipsu. Vzorec pro elipsu je v analytické geometrii:
Střed umístíme do středu naší matice, takže bude v matici na souřadnicích [35,12] s tím, že parametry budou a=30 a b=12 (na obrázku to asi přesně takhle není, ale takhle se nám to taky hezky do výpisu vejde).
Pro "vybarvení" i vnitřku elipsy bude stačit, když místo "=" použijeme "<=" - všechny body splňující tuto nerovnici jsou totiž uvnitř elipsy.
Řešení
Nejprve si vytvoříme třídu obsahující všechny proměnné, které budeme potřebovat, společně s konstruktorem. Proměnné centreX a centreY obsahují souřadnice středu, a a b jsou hlavní a vedlejší poloosy elipsy, dvourozměrné pole matrix je samotná matice, do které budeme elipsu vypisovat, a dále tu jsou jen konstanty velikostí matice a RADIUS, abychom ve vzorci elipsy neměli magická čísla.
class AsciiEllipse {
int centreX, centreY, a, b;
String[][] matrix;
final int SIZE_X = 70;
final int SIZE_Y = 25;
final int RADIUS = 1;
public AsciiEllipse(){
this.centreX = 35;
this.centreY = 12;
this.a = 30;
this.b = 12;
this.matrix = new String[SIZE_Y][SIZE_X];
}
}
Dále si vytvoříme metodu pro vyplnění celé matice tečkami (kromě prostředního řádku, který bude vyplněn mínusem jako osa). Pokud změníme souřadnice středu, tak se nám osa x bude vždy vypisovat na stejném řádku se středem, pokud tomu chceme zabránit, stačí si na začátku definovat další konstantu označující číslo řádku a místo this.centreY bychom porovnávali proměnnou i s touto konstantou.
public void emptyMatrix(){
for(int i = 0; i < this.matrix.length; i++)
for(int j = 0; j < this.matrix[i].length; j++)
if(i == this.centreY)
matrix[i][j] = "-";
else matrix[i][j] = ".";
}
Následně si napíšeme metodu pro vlastní vyplnění obrazce elipsy do matice - stačí dodržet vzorec elipsy, použijeme typy double, protože jsou v tomto případě přesnější než typ int (porovnáváme s jedničkou).
public void fillEllipse(){
for(int i = 0; i < SIZE_Y; i++){
for(int j = 0; j < SIZE_X; j++){
double first = (double)((j - this.centreX) * (j - this.centreX)) / ((this.a) * (this.a));
double second = (double)((i - this.centreY) * (i - this.centreY)) / ((this.b) * (this.b));
if((first + second) <= RADIUS)
this.matrix[i][j] = "+";
}
}
}
A teď už zbývá jen metoda pro výpis celé matice - procházíme matici po řádcích a vypisujeme jednotlivé znaky. Pokud se dostaneme na konec řádku, vypíšeme konec řádku a pokračujeme dalším:
public void drawEllipse(){
for(int i = 0; i < SIZE_Y; i++){
for(int j = 0; j < SIZE_X; j++)
System.out.print(this.matrix[i][j]);
System.out.println();
}
}
A nakonec samotná aplikace, která vytváří objekt třídy AsciiEllipse a volá její metody:
public class AsciiEllipseApplication {
public static void main(String[] args){
AsciiEllipse elipse = new AsciiEllipse();
elipse.emptyMatrix();
elipse.fillEllipse();
elipse.drawEllipse();
}
}
Tento program by se dal určitě vylepšit například vypisováním elipsy "zrcadlově" podle středu - pak by stačilo projít jen polovinu cyklu, a nikoli celý cyklus, nebo ještě lépe, vypsat jen čtvrtinu a tu zrcadlově otočit - tím bychom měli vypsánu celou polovinu elipsy. Tu bychom opět zrcadlově otočili a elipsa by byla celá, zbývalo by jen do okolí doplnit tečky..
A už by chybělo jen vypisovat souřadnice a osy, což je jednoduché, každý řádek má určité číslo, které stačí vypsat ještě před samotným řádkem - buď úpravou metody na výpis matice, nebo třeba vytvořením o kus větší matice, kde by tyto souřadnice byly, a do zbytku bychom vložili již námi vytvořenou elipsu..
Žádné komentáře:
Okomentovat