INSTRUKCJA DO ĆWICZENIA 4 Utworzymy aplikacje umożliwiające oszacowanie szukanych wartości przez symulację doświadczenia losowego, z ilustracją graficzną wyników doświadczenia. Zadanie wykonamy dla przykładów szacowania następujących wartości: 1. prawdopodobieństwa określonego wyniku rzutów kostkami do gry. 2. stałej (metodą geometryczną) 3. stałej (metodą Buffona) 4. całki oznaczonej 0 2 2 x *sin( x) dx I Rzuty kostkami Oszacujemy prawdopodobieństwo, że rzucając 5 kostkami do gry, co najmniej raz uzyskamy 6 oczek 1. Utwórz projekt wykorzystujący pakiet Swing. Projektowi nadaj nazwę Projekt41, a klasie głównej nazwę Kostki. 2. Nadaj ramce tytuł Rzuty kostkami i w dolnej części ramki umieść komponenty jak na rysunku obok: obszar jtextarea1 z opisem zadania dwa przyciski o tytułach Losuj i Restart tabelę jtable1 o 1 wierszu i 4 kolumnach; tytułami kolumn są kolejno Liczba rzutów, Liczba sukcesów, Oszacowanie wyniku, Wartość teoretyczna (odpowiednio określ właściwość model komponentu jtable1) Górną część ramki pozostaw pustą, programowo utworzymy w niej panel a na panelu umieścimy przyciski, na których będą wyświetlane obrazy ścianek kostki (klasy ImageIcon). 3. Skopiuj do foldera projektu obrazki z foldera I2\cw4. 4. Pod nagłówkiem klasy Kostki zadeklaruj pola: long lrzutów, lsukcesów; final double W = 0.598; // wartość teoretyczna wyniku double wynik = 0; // oszacowanie wyniku JPanel panel; JButton[] kostki = new JButton[5]; Icon [] ikony={new ImageIcon("1.gif"), new ImageIcon("2.gif"), new ImageIcon("3.gif"), new ImageIcon("4.gif"), new ImageIcon("5.gif"), new ImageIcon("6.gif"); 5. Zmodyfikuj konstruktor klasy Kostki dodając instrukcje, które określają rozmiary i położenie panelu, tworzą kostki w postaci przycisków, przypisują im obrazki i umieszczają przyciski na panelu. Konstruktor powinien mieć ostatecznie postać: public Kostki() { initcomponents(); panel = new JPanel(new GridLayout(1, 5, 3, 0)); panel.setbounds(50, 50, 400, 50); for (int i = 0; i < 5; i++) { kostki[i] = new JButton(); kostki[i].seticon(ikony[i]); panel.add(kostki[i]); 6. Uruchom aplikację i sprawdź efekt wprowadzonych modyfikacji. 7. Utwórz metodę losowanie() która dla każdej z 5 kostek losuje liczbę oczek od 1 do 6, wyświetla na przycisku odpowiednią ikonę oraz zlicza wylosowane szóstki. Sukcesem jest wylosowanie co najmniej jednej szóstki. int x, s = 0; // s - licznik szóstek for (int i = 0; i < 5; i++) { x = 1 + r.nextint(6); // x wylosowana liczba oczek na kostce kostki[i].seticon(ikony[x - 1]); // przypisanie odpowiedniej ikony if (x == 6) { s++; // zliczanie szóstek if (s > 0) { lsukcesów++; jbutton1.setbackground(color.green); else { jbutton1.setbackground(null); wynik = (double) lsukcesów / lrzutów; Materiały do użytku wewnętrznego strona 1
8. Utwórz metodę start(), która określa stan początkowy dla serii losowań: lrzutów = lsukcesów = 0; // zerowanie liczników jtable1.setvalueat(0, 0, 0); jtable1.setvalueat(0, 0, 1); jtable1.setvalueat(null, 0, 2); // usunięcie oszacowania wyniku jbutton1.setbackground(null); for (int i = 0; i < kostki.length; i++) { kostki[i].seticon(null); 9. Na końcu konstruktora klasy Kostki dopisz wywołanie powyższej metody oraz dodaj instrukcję wpisującą teoretyczną wartość wyniku do ostatniej komórki tabeli: 10. Dla przycisku Losuj utwórz metodę obsługi zdarzenia actionperformed o treści: lrzutów++; losowanie(); jtable1.setvalueat(lrzutów, 0, 0); 11. Dla przycisku Restart utwórz metodę obsługi zdarzenia actionperformed, w jej treści:wywołaj metodę start() 12. Uruchom aplikację i sprawdź jej działanie. II Losowanie punktów w kwadracie oszacowanie wartości liczby W kolejnym przykładzie oszacujemy wartość stałej za pomocą losowania serii punktów. Losujemy punkty wewnątrz kwadratu; sukcesem jest, gdy wylosowany punkt leży w kole wpisanym w kwadrat. Stosunek pola koła do pola kwadratu, równy, jest w przybliżeniu równy ilorazowi liczby sukcesów przez liczbę wszystkich punktów. 1. Utwórz projekt wykorzystujący pakiet Swing. Projektowi nadaj nazwę Projekt42, a klasie głównej nazwę LiczbaPi 2. Zdefiniuj klasę wewnętrzną PanelGraficzny dziedziczącą od klasy JPanel: class PanelGraficzny extends JPanel { 3. W klasie tej zadeklaruj obiekt r klasy Random, do generowania liczb losowych: Random r= new Random(); 4. Zadeklaruj w klasie PanelGraficzny metodę paintcomponent() a w niej zmienne lokalne typu int: R -dla promienia koła o wartości początkowej 100 maxp - dla ograniczenia liczby losowanych punktów, o wartości początkowej 25000 ls -dla zliczania punktów leżących wewnątrz koła, o wartości początkowej 0 5. W dalszej treści metody paintcomponent() wpisz instrukcje, które losują punkty i rysują je w kolorze zależnym od ich położenia (czarny dla punktów w kole lub biały - poza kołem): g.translate(50, 50); for (int lp = 0; lp < maxp; lp++) { double x = 2 * R * r.nextdouble(); // (x,y) wylosowany punkt kwadratu double y = 2 * R * r.nextdouble(); if ((x - R)*(x - R) + (y - R)*(y - R) <= R*R) { // punkt (x,y) leży w kole wpisanym w kwadrat ls++; g.setcolor(color.black); //warunkowe zwiększenie liczby sukcesów else {g.setcolor(color.white); g.drawline((int) x, (int) y, (int) x, (int) y); //rysowanie punktu 6. W klasie głównej LiczbaPi zadeklaruj i utwórz obiekt: 7. W konstruktorze klasy głównej określ rozmiary ramki na 500x500. Dodaj do ramki obiekt panel i ustal jego rozmiary i położenie tak, by zajmował on całą powierzchnię ramki Uruchom aplikację i zaobserwuj przebieg losowania. 8. W metodzie paintcomponent(), poniżej pętli for, dopisz instrukcje, które wyświetlają oszacowanie liczby : g.translate(2 * R, 2 * R); g.clearrect(0, 0, 250, 100); g.setcolor(color.red); g.drawstring("liczba wszystkich punktów = " + maxp, 20, 20); g.drawstring("liczba punktów w kole = " + ls, 20, 40); g.drawline(20, 60, 200, 60); g.drawstring("liczba pi = " + 4.0 * ls / maxp, 20, 80); 9. Uruchom aplikację i zaobserwuj nowe szacowanie liczby Pi przy zmianie rozmiarów ramki. Materiały do użytku wewnętrznego strona 2
III Szacowanie liczby Pi metodą Buffona 1. Utwórz nowy projekt wykorzystujący pakiet Swing. Projektowi nadaj nazwę Projekt43, a klasie głównej nazwę Buffon. Nadaj ramce tytuł Igła Buffona i umieść w jej dolnej części komponenty identyczne jak w p.i.2. Górną część ramki pozostaw pustą, programowo umieścimy tam panel graficzny z rysunkiem. 2. Pod nagłówkiem klasy Buffon zadeklaruj pola: long lrzutów, lsukcesów; final double W = Math.PI; double wynik = 0; double x1, y1, x2, y2; int dl, ig ; boolean sukces; // stała W - wartość teoretyczna wyniku // oszacowanie wyniku // współrzędne końców odcinka (igły Buffona) // dl- odleglosc linii, ig - długość igły // zmienna o wartości true gdy igła przecina linię 3. Zdefiniuj klasę wewnętrzną PanelGraficzny dziedziczącą od klasy JPanel, która posłuży do ilustracji graficznej doświadczenia. W klasie PanelGraficzny wpisz konstruktor, nadający panelowi położenie, rozmiar i obramowanie: public PanelGraficzny() { setbounds(20, 20, 200, 200); setborder(borderfactory.createlineborder(color.blue)); 4. W klasie Buffon zadeklaruj i utwórz obiekt: 5. Wewnątrz konstruktora klasy Buffon, wpisz instrukcje dodające panel do ramki oraz dopisz instrukcje obliczające odległość linii i długość igły: dl = (panel.getheight()) / 2; // odleglosc linii ig = (panel.getheight()) / 3; // długość igły 6. Dopisz w klasie PanelGraficzny metodę rysowania komponentu: public void paintcomponent(graphics g) { g.setcolor(color.white); // białe tło obrazu g.fillrect(0, 0, panel.getwidth(), panel.getheight()); g.setcolor(color.blue); g.drawline(0, dl, panel.getwidth(), dl); // linia if (sukces) { g.setcolor(color.red); else { g.setcolor(color.black); g.drawline((int) x1, (int) y1, (int) x2, (int) y2); //rysowanie igły 7. Uruchom aplikację i sprawdź efekt wprowadzonych modyfikacji. 8. W klasie Buffon utwórz metodę losowanie() w której losujemy położenie środka igły oraz losujemy wartość kąta nachylenia igły do linii. Na podstawie tych wartości wyliczamy współrzędne położenia końców igły (x1, y1) i (x2, y2). Sprawdzamy warunek sukcesu czyli przecięcia linii przez igłę. double x, y, a; // (x, y) - środek igły, a - kąt nachylenia igły do linii x = ig / 2 + (panel.getwidth() - ig) * r.nextdouble(); y = dl * r.nextdouble() - dl / 2; a = 2 * Math.PI * r.nextdouble(); x1 = x - ig / 2 * Math.cos(a); y1 = dl - y - ig / 2 * Math.sin(a); x2 = x + ig / 2 * Math.cos(a); y2 = dl - y + ig / 2 * Math.sin(a); if (((y2 - dl) * (y1 - dl)) < 0) { // igła przecina linię lsukcesów++; sukces = true; else { sukces = false; if (lsukcesów>0) wynik = 2.0 * ig / dl / lsukcesów * lrzutów; 9. W klasie Buffon utwórz metodę start(), która określa stan początkowy i odświeża rysunek na panelu: lrzutów = lsukcesów = 0; wynik = 0; // zerowanie liczników jtable1.setvalueat(0, 0, 0); jtable1.setvalueat(0, 0, 1); jtable1.setvalueat(null, 0, 2); jbutton1.setbackground(null); x1=y1=x2=y2=0; // usunięcie oszacowania wyniku Materiały do użytku wewnętrznego strona 3
10. Na końcu konstruktora klasy Buffon dopisz wywołanie powyższej metody oraz dodaj instrukcję wpisującą teoretyczną wartość wyniku do ostatniej komórki tabeli: 11. Dla przycisku Losuj utwórz metodę obsługi zdarzenia actionperformed o treści: lrzutów++; losowanie(); jtable1.setvalueat(lrzutów, 0, 0); 12. Dla przycisku Restart utwórz metodę obsługi zdarzenia actionperformed, w jej treści:wywołaj metodę start() 13. Uruchom aplikację i wykonaj symulację doświadczenia Buffona. IV Szacowanie wartości całki oznaczonej 1. Utwórz projekt wykorzystujący pakiet Swing. Projektowi nadaj nazwę Projekt44, a klasie głównej nazwę Calka. 2. Nadaj ramce tytuł Szacowanie całki. Analogicznie do p.i.2 umieść komponenty jak na rysunku obok: obszar jtextarea1 z opisem zadania dwa przyciski o tytułach Losuj i Restart tabelę jtable1 o 1 wierszu i 4 kolumnach; tytułami kolumn są kolejno Liczba punktów, Liczba sukcesów, Oszacowanie wyniku, Wartość teoretyczna Lewą górną część ramki pozostaw pustą, programowo umieścimy tam panel graficzny z rysunkiem. 3. Pod nagłówkiem klasy Calka zadeklaruj pola: long lpunktow, lsukcesów; int maxp = 1000; // liczba punktów losowanych w serii final double W = 2.469; // stała W - wartość teoretyczna wyniku double wynik = 0; // oszacowanie wyniku Image obraz; Graphics bufor ; // obraz, bufor - posłużą do ilustracji graficznej losowania punktów prostokąta 4. Zdefiniuj klasę wewnętrzną PanelGraficzny dziedziczącą od klasy JPanel, która posłuży do ilustracji graficznej doświadczenia. W klasie PanelGraficzny wpisz konstruktor, nadający panelowi położenie, rozmiar i obramowanie: public PanelGraficzny() { setbounds(20, 20, 200, 200); setborder(borderfactory.createlineborder(color.blue)); Dopisz w klasie PanelGraficzny metodę rysowania komponentu: public void paintcomponent(graphics g) { g.drawimage(obraz, 0, 0, this); 5. W klasie Całka zadeklaruj i utwórz obiekt: 6. Wewnątrz konstruktora klasy Całka, wpisz instrukcje dodające panel do ramki oraz dopisz instrukcje tworzenia obiektów graficznych: obraz=createimage(panel.getwidth(),panel.getheight()); bufor=obraz.getgraphics(); 7. Uruchom aplikację i sprawdź wygląd ramki. 8. Utwórz metodę losowanie() która losuje punkt wewnątrz prostokąta o wymiarach 2 4; losowanie przynosi sukces, jeśli współrzędna y wylosowanego punktu nie przekroczy wartości całkowanej funkcji: double x = 2 * r.nextdouble(); //(x,y) wylosowany punkt x 0,2), y 0,4) double y = 4 * r.nextdouble(); if (y <= x * x * Math.sin(x)) { lsukcesów++; bufor.setcolor(color.red); else { bufor.setcolor(color.yellow); int xp = (int) (x / 2 * panel.getwidth()) ;//przeliczenie współrzędnych punktu na panelu int yp = panel.getheight() - (int) (y / 4 * panel.getheight()); bufor.drawline(xp, yp, xp, yp); //rysowanie punktu wynik = 8.0 * lsukcesów / lpunktow; Materiały do użytku wewnętrznego strona 4
9. Utwórz metodę start(), która określa stan początkowy dla serii losowań: lpunktow = lsukcesów = 0; // zerowanie liczników jtable1.setvalueat(0, 0, 0); jtable1.setvalueat(0, 0, 1); jtable1.setvalueat(null, 0, 2); // usunięcie oszacowania wyniku bufor.setcolor(color.white); bufor.fillrect(0, 0, panel.getwidth(), panel.getheight()); // wpisanie odpowiednich zer do tabeli //białe tło obrazu 10. Na końcu konstruktora klasy Calka dopisz wywołanie powyższej metody oraz dodaj instrukcję wpisującą teoretyczną wartość wyniku do ostatniej komórki tabeli: 11. Dla przycisku Losuj utwórz metodę obsługi zdarzenia actionperformed o treści: for (int i = 0; i < maxp; i++) { // wykonanie serii losowań lpunktow++; losowanie(); jtable1.setvalueat(lpunktow, 0, 0); 12. Dla przycisku Restart utwórz metodę obsługi zdarzenia actionperformed, w jej treści:wywołaj metodę start() 13. Uruchom aplikację i sprawdź jej działanie. Zadania do samodzielnego wykonania 1. Zmodyfikuj klasę LiczbaPi na wzór klasy Całka wstawiając na ramkę przycisk, tabelę oraz pole z opisem zadania. Każde kliknięcie przycisku powoduje wykonanie kolejnego doświadczenie losowego ( tu - losowanie punktów w kwadracie i kolejne oszacowanie wartości liczby Pi) Ilustracja graficzna doświadczenia wymaga zastosowania bufora graficznego( tak jak w klasie Całka), w celu zachowania na panelu punktów wylosowanych w poprzedmim eksperymencie. 2. Zmodyfikuj klasę Kostki tak, aby celem symulacji było oszacowanie prawdopodobieństwa, że na żadnej kostce nie wypadną trzy oczka. Wartość teoretyczna prawdopodobieństwa wynosi 0,402 3. Zmodyfikuj klasę Kostki tak, aby celem symulacji było oszacowanie wartości oczekiwanej sumy oczek na 6 kostkach. Skorzystaj ze wzoru podanego w materiałach pomocniczych. Wartość teoretyczna wynosi 17,5 4. Zmodyfikuj klasę Calka tak, aby umożliwić oszacowanie całki funkcji y = ln(x) w przedziale (1, e). Wartość całki obliczona analitycznie wynosi 1. 5. Zmodyfikuj klasę Calka tak, aby umożliwić określanie przez użytkownika liczby punktów losowanych w serii (wartości zmiennej maxp). Dodaj na ramce pole tekstowe i wykorzystaj je do wczytania danej w metodzie start(). Materiały do użytku wewnętrznego strona 5