Podstawy współbieżności - Uniwersytet Ekonomiczny w Krakowie
Transkrypt
Podstawy współbieżności - Uniwersytet Ekonomiczny w Krakowie
2011-01-18 Algorytmy z powrotami. Algorytm minimax Algorytmy i struktury danych. Wykład 7. Rok akademicki: 2010/2011 Algorytm z powrotami • rozwiązanie problemu budowane jest w kolejnych krokach, • po stwierdzeniu (w trakcie realizacji i-tego kroku), że rozwiązanie problemu nie jest możliwe do osiągnięcia następuje powrót do kroku wcześniejszego i badana jest możliwośd wykonania innego kroku zapoczątkowującego inną ścieżkę poszukiwao; • sposób wyznaczania rozwiązania można przedstawid jako wędrówkę po drzewie. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 2 1 2011-01-18 Algorytm z powrotami – schemat działania Stan początkowy Poziom 1 Wariant 1 Poziom 2 Wariant 1.1 Poziom 1 Wariant 3 Poziom 2 Wariant 1.2 Poziom 3 Wariant 1.2.1. Poziom 2 Wariant 3.1 Poziom 2 Wariant 3.2 Poziom 2 Wariant 3.3 Poziom 3 Wariant 1.2.2. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 3 Problem ośmiu hetmanów Ułożyd na szachownicy osiem hetmanów tak, aby się wzajemnie nie szachowały. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 4 2 2011-01-18 Opis algorytmu problem ośmiu hetmanów • Figury ustawiane są w kolejnych kolumnach (począwszy od pierwszej od lewe strony), • Jeśli ustawienie hetmana w danej kolumnie nie jest możliwe, to następuje powrót do kolumny wcześniejszej i dokonywana jest próba zmiany położenia znajdującego się tam hetmana; po jej dokonaniu poszukiwania są kontynuowane. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 5 Problem ośmiu hetmanów class PierwszeUstawienie { boolean [][] szachownica = new boolean[8][8]; int ileUstawiono = 0; void usunWszystko() { for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) szachownica[i][j] = false; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 6 3 2011-01-18 Problem ośmiu hetmanów void drukujSzachownice() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) if (szachownica[i][j] == true) System.out.print('*'); else System.out.print('.'); System.out.println(); } } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 7 Problem ośmiu hetmanów boolean czyPoprawne(int x, int y) { int i, j; //czy jest w tym samym wierszu? for (j = 0; j < 8; j++) if (szachownica[x][j] == true) return false; //czy jest w tej samej kolumnie? for (i = 0; i < 8; i++) if (szachownica[i][y] == true) return false; Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 8 4 2011-01-18 Problem ośmiu hetmanów //czy jest na przekatnej prawo-gora ? for (i = x, j = y; (i >= 0) && (j < 8); i --, j++) if ((i != x) && (j != y) && (szachownica[i][j] == true)) return false; //czy jest na przekatnej prawo-dol? for (i = x, j = y; (i < 8) && (j < 8); i++, j++) if ((i != x) && (j != y) && (szachownica[i][j] == true)) return false; //czy jest na przekatnej lewo-gora? for (i = x, j = y; (i >= 0) && (j >= 0); i--, j--) if ((i != x) && (j != y) && (szachownica[i][j] == true)) return false; //czy jest na przekatnej lewo-dol? for (i = x, j = y; (i < 8) && (j >= 0); i++, j--) if ((i != x) && (j != y) && (szachownica[i][j] == true)) return false; } return true; Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 9 Problem ośmiu hetmanów boolean ustaw(int kolumna) { int wiersz = 0; do { } if (czyPoprawne(wiersz,kolumna)) { szachownica[wiersz][kolumna] = true; ileUstawiono++; if (kolumna + 1 < 8) if (ustaw(kolumna + 1)) return true; else { szachownica[wiersz][kolumna] = false; ileUstawiono--; } } wiersz++; } while ((ileUstawiono < 8) && (wiersz < 8)); if (ileUstawiono == 8) return true; else return false; Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 10 5 2011-01-18 Problem ośmiu hetmanów void rozwiazZadanie() { usunWszystko(); if (ustaw(0)) drukujSzachownice(); else System.out.println("Brak rozwiazaia!!!"); } } public class OsiemHetmanow01 { public static void main(String [] args) { PierwszeUstawienie u = new PierwszeUstawienie(); u.rozwiazZadanie(); } } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 11 Problem ośmiu hetmanów Rezultat uruchomienia programu: *....... ......*. ....*... .......* .*...... ...*.... .....*.. ..*..... Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 12 6 2011-01-18 Algorytm minimax • Algorytm minimax jest podstawowym algorytmem wykorzystywanym przy tworzeniu gier dwuosobowych rozgrywanych w układzie: człowiek - komputer. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 13 Kółko i krzyżyk jako przykład gry dwuosobowej Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 14 7 2011-01-18 Kółko i krzyżyk – wersja I class KK01 { static final int NIKT = 0; static final int KOMPUTER = 1; static final int CZLOWIEK = 2; int n; int [][] plansza; KK01(int n) { this.n = n; plansza = new int[n][n]; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 15 Kółko i krzyżyk – wersja I char symbolGracza(int zawodnik) { switch(zawodnik) { case CZLOWIEK: return 'X'; case KOMPUTER: return 'O'; case NIKT: return '.'; } return '?'; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 16 8 2011-01-18 Kółko i krzyżyk – wersja I void wyswietl() { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) System.out.print(symbolGracza(plansza[i][j])); System.out.println(); } } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 17 Kółko i krzyżyk – wersja I void ruchGracza() { int wiersz = 0, kolumna = 0; System.out.println("RUCH GRACZA:\n"); wyswietl(); System.out.println(); Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 18 9 2011-01-18 Kółko i krzyżyk – wersja I try { BufferedReader klawiatura = new BufferedReader(new InputStreamReader(System.in)); do { System.out.print("Podaj numer wiersza (1," + (n) + "): "); wiersz = Integer.parseInt(klawiatura.readLine()); System.out.print("Podaj numer kolumny (1," + (n) + "): "); kolumna = Integer.parseInt(klawiatura.readLine()); } while (plansza[wiersz-1][kolumna-1] != NIKT); plansza[wiersz-1][kolumna-1] = CZLOWIEK; System.out.println(); } catch (Exception e) { System.out.println(e.getMessage()); } } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 19 Kółko i krzyżyk – wersja I boolean czyWygral(int zawodnik) { int suma; //czy jest wiersz for (int i = 0; i < n; i++) { suma = 0; for (int j = 0; j < n; j++) if (plansza[i][j] == zawodnik) suma++; if (suma == n) return true; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 20 10 2011-01-18 Kółko i krzyżyk – wersja I //czy jest kolumna for (int j = 0; j < n; j++) { suma = 0; for (int i = 0; i < n; i++) if (plansza[i][j] == zawodnik) suma++; if (suma == n) return true; } //pierwsza przekatna suma = 0; for (int i = 0; i < n; i++) if (plansza[i][i] == zawodnik) suma++; if (suma == n) return true; Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 21 Kółko i krzyżyk – wersja I //druga przekatna suma = 0; for (int i = 0; i < n; i++) if (plansza[i][n-1-i] == zawodnik) suma++; if (suma == n) return true; return false; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 22 11 2011-01-18 Kółko i krzyżyk – wersja I int ocenaSytuacji(int ktoWykonalRuch) { return czyWygral(ktoWykonalRuch) ? 1000 : 0; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 23 Kółko i krzyżyk – wersja I int wybierzNajlepszyRuch() { int sytuacja = -9999; int ruch = -1; int ocena; for (int i = 0; i < n * n; i++) if (plansza[i/n][i%n] == NIKT) { plansza[i/n][i%n] = KOMPUTER; if ((ocena = ocenaSytuacji(KOMPUTER)) > sytuacja) { sytuacja = ocena; ruch = i; } } } plansza[i/n][i%n] = NIKT; return ruch; Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 24 12 2011-01-18 Kółko i krzyżyk – wersja I void ruchKomputera() { System.out.println("RUCH KOMPUTERA ...\n"); int pozycja = wybierzNajlepszyRuch(); plansza[pozycja/n][pozycja%n] = KOMPUTER; wyswietl(); System.out.println(); } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 25 Kółko i krzyżyk – wersja I boolean czySaPuste() { int suma = 0; for (int i = 0; i < n * n; i++) if (plansza[i/n][i%n] == NIKT) suma++; return (suma > 0 ? true: false); } int nastepny(int zawodnik) { return 3 - zawodnik; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 26 13 2011-01-18 Kółko i krzyżyk – wersja I void rozgrywka() { int nastepnyZawodnik = CZLOWIEK, zawodnik; do { zawodnik = nastepnyZawodnik; switch (zawodnik) { case CZLOWIEK: ruchGracza(); break; case KOMPUTER: ruchKomputera(); break; } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 27 Kółko i krzyżyk – wersja I nastepnyZawodnik = nastepny(zawodnik); } while (!czyWygral(zawodnik) && czySaPuste()); System.out.println("\n\nKoniec gry!!!\n"); wyswietl(); System.out.println("\n"); if (czyWygral(CZLOWIEK)) System.out.println("Wygrales z komputerem!!!"); else if (czyWygral(KOMPUTER)) System.out.println("Wygral KOMPUTER!!!"); else System.out.println("REMIS!!!"); } } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 28 14 2011-01-18 Kółko i krzyżyk – wersja I class KolkoKrzyzyk02 { public static void main(String [] args) { KK01 kk = new KK01(3); kk.rozgrywka(); } } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 29 Kółko i krzyżyk – wersja I RUCH GRACZA: ... ... ... Podaj numer wiersza (1,3): 1 Podaj numer kolumny (1,3): 1 RUCH KOMPUTERA ... XO. ... ... RUCH GRACZA: XO. ... ... Podaj numer wiersza (1,3): 2 Podaj numer kolumny (1,3): 1 Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 30 15 2011-01-18 Kółko i krzyżyk – wersja I RUCH KOMPUTERA ... XOO X.. ... RUCH GRACZA: XOO X.. ... Podaj numer wiersza (1,3): 3 Podaj numer kolumny (1,3): 1 Koniec gry!!! XOO X.. X.. Wygrales z komputerem!!! Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 31 Wniosek Zastosowany sposób gry nie jest prawidłowy gdyż realizuje ruch tylko na podstawie oceny bieżącej sytuacji. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 32 16 2011-01-18 Algorytm minimax • Algorytm minimax służy do tworzenia gier dwuosobowych. • Wybiera optymalny ruch na podstawie analizy drzewa gry (opisującego wszystkie możliwe do zrealizowania ruchy). • Do oceny sytuacji stosowana jest funkcja płatności oceniająca sytuację z punktu widzenia komputera - im wyższa jest jej wartośd, tym lepsza jest pozycja komputera. • Podstawowa zasada algorytmu: przy wyborze ruchu komputer maksymalizuje wartośd funkcji płatności, zaś człowiek wykonuje ruch minimalizujący jej wartośd. Drzewo gry analizowane jest od dołu. Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 33 Schemat działania algorytmu minimax Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 34 17 2011-01-18 Kółko i krzyżyk – wersja II class KK02 extends KK01 { KK02(int n) { super(n); } Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 35 Kółko i krzyżyk – wersja II int ocenaSytuacji(int ktoWykonalRuch) { int wartoscProgowa = 0; switch(ktoWykonalRuch) { case KOMPUTER: if (czyWygral(KOMPUTER)) return 1000; if (czySaPuste()) { wartoscProgowa = 9999; for (int i = 0; i < n * n; i++) if (plansza[i/n][i%n] == NIKT) { plansza[i/n][i%n] = CZLOWIEK; wartoscProgowa = Math.min(wartoscProgowa, ocenaSytuacji(CZLOWIEK)); plansza[i/n][i%n] = NIKT; } } else return 0; break; Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 36 18 2011-01-18 Kółko i krzyżyk – wersja II case CZLOWIEK: if (czyWygral(CZLOWIEK)) return -1000; if (czySaPuste()) { wartoscProgowa = -9999; for (int i = 0; i < n * n; i++) if (plansza[i/n][i%n] == NIKT) { plansza[i/n][i%n] = KOMPUTER; wartoscProgowa = Math.max(wartoscProgowa, ocenaSytuacji(KOMPUTER)); plansza[i/n][i%n] = NIKT; } } else return 0; } // koniec switch return wartoscProgowa; } // koniec ocenaSytuacji } // koniec definicji klasy Paweł Lula, Katedra Systemów Obliczeniowych, Uniwersytet Ekonomiczny w Krakowie 37 19