Przykład interakcji z myszą: WordSearch

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Ten przykład ilustruje interakcję z użytkownikiem realizowaną poprzez obsługę zdarzeń myszy. Zadaniem użytkownika jest zbudowanie jak największej liczby słów z liter rozmieszczonych losowo w tabeli. Kolejne litery wybiera się, wskazując sąsiednie litery w kierunku poziomym lub pionowym, jednak niedozwolone jest dwukrotne użycie tej samej litery. Przykład demonstruje następujące możliwości języka ActionScript 3.0:

  • Dynamiczne budowanie tablicy składników

  • Reagowanie na zdarzenia pochodzące z myszy

  • Aktualizowanie wyniku na podstawie interakcji z użytkownikiem

Aby pobrać pliki tej przykładowej aplikacji, należy przejść na stronę www.adobe.com/go/learn_programmingAS3samples_flash_pl . Pliki aplikacji WordSearch znajdują się w folderze Samples/WordSearch. Aplikacja składa się z następujących plików:

File

Opis

WordSearch.as

Klasa realizująca podstawowe funkcje aplikacji.

WordSearch.fla

lub

WordSearch.mxml

Główny plik aplikacji dla środowiska Flex (MXML) lub programu Flash (FLA).

dictionary.txt

Plik służący do określania, czy za ułożone słowa należą się punkty i czy słowa są prawidłowo ułożone.

Ładowanie słownika

W grze, której istotą jest układanie słów, niezbędny jest słownik. W przykładzie zastosowano plik tekstowy o nazwie dictionary.txt, który zawiera listę słów rozdzielonych znakami powrotu karetki. Po utworzeniu tablicy o nazwie words funkcja loadDictionary() ładuje ten plik. Po pomyślnym załadowaniu plik staje się długim ciągiem znaków. Ten ciąg jest następnie przekształcany w tablicę słów przy użyciu metody split() , która dzieli ciąg przy każdym wystąpieniu znaku powrotu karetki (kod znaku 10) lub nowego wiersza (kod znaku 13). Ta analiza ciągu odbywa się w funkcji dictionaryLoaded() :

words = dictionaryText.split(String.fromCharCode(13, 10));

Tworzenie interfejsu użytkownika

Po zapisaniu słów w tablicy możemy przygotować interfejs użytkownika. Tworzymy dwie instancje klasy Button: jeden przycisk służy do zgłaszania nowego słowa, a drugi do czyszczenia aktualnie układanego słowa. W każdym przypadku programu musi reagować na działania użytkownika, wykrywając zdarzenia MouseEvent.CLICK wysyłane przez przycisk, a następnie wywołując funkcję. W funkcji setupUI() zawarty jest poniższy kod tworzący detektory dla obu przycisków:

submitWordButton.addEventListener(MouseEvent.CLICK,submitWord); 
clearWordButton.addEventListener(MouseEvent.CLICK,clearWord);

Generowanie planszy gry

Plansza gry ma postać tabeli z losowymi literami. Funkcja generateBoard() tworzy tabelę dwuwymiarową w zagnieżdżonej pętli. Pierwsza pętla inkrementuje numer wiersza, a druga pętla inkrementuje numer kolumny w wierszu. Każda utworzona komórka zawiera przycisk reprezentujący literę na planszy.

private function generateBoard(startX:Number, startY:Number, totalRows:Number, totalCols:Number, buttonSize:Number):void 
{ 
    buttons = new Array(); 
    var colCounter:uint; 
    var rowCounter:uint; 
    for (rowCounter = 0; rowCounter < totalRows; rowCounter++) 
    { 
        for (colCounter = 0; colCounter < totalCols; colCounter++) 
        { 
            var b:Button = new Button(); 
            b.x = startX + (colCounter*buttonSize); 
            b.y = startY + (rowCounter*buttonSize); 
            b.addEventListener(MouseEvent.CLICK, letterClicked); 
            b.label = getRandomLetter().toUpperCase(); 
            b.setSize(buttonSize,buttonSize); 
            b.name = "buttonRow"+rowCounter+"Col"+colCounter; 
            addChild(b); 
             
            buttons.push(b); 
        } 
    } 
}

Mimo że detektor zdarzenia MouseEvent.CLICK został dodany tylko w jednym wierszu, zostanie przypisany do wszystkich instancji klasy Button, ponieważ jest dodawany w pętli for . Ponadto każdemu przyciskowi przypisywana jest nazwa wynikająca z jego numeru wiersza i kolumny, co pozwala w prosty sposób odwoływać się w kodzie do numeru wiersza i kolumny każdego z przycisków.

Układanie słów na podstawie interakcji z użytkownikiem

Kolejne słowa układa się, wybierając litery sąsiadujące ze sobą w pionie lub poziomie, jednak niedozwolone jest dwukrotne użycie tej samej litery. Każde kliknięcie wywołuje zdarzenie myszy. Wówczas konieczne jest sprawdzenie aktualnie ułożonego słowa w celu potwierdzenia, że wybrano literę sąsiednią względem poprzednio klikniętej. Jeśli ten warunek nie jest spełniony, słowo jest usuwane i rozpoczyna się układanie nowego słowa. Sprawdzenie to odbywa się w metodzie isLegalContinuation() .

private function isLegalContinuation(prevButton:Button, currButton:Button):Boolean 
{ 
    var currButtonRow:Number = Number(currButton.name.charAt(currButton.name. indexOf("Row") + 3)); 
    var currButtonCol:Number = Number(currButton.name.charAt(currButton.name.indexOf("Col") + 3)); 
    var prevButtonRow:Number = Number(prevButton.name.charAt(prevButton.name.indexOf("Row") + 3)); 
    var prevButtonCol:Number = Number(prevButton.name.charAt(prevButton.name.indexOf("Col") + 3)); 
     
    return ((prevButtonCol == currButtonCol && Math.abs(prevButtonRow - currButtonRow) <= 1) || 
             (prevButtonRow == currButtonRow && Math.abs(prevButtonCol - currButtonCol) <= 1)); 
}

Metody charAt() i indexOf() klasy String odczytują odpowiedni wiersz i kolumnę aktualnie i poprzednio klikniętego przycisku. Metoda isLegalContinuation() zwraca wartość true , jeśli nie zmienił się numer wiersza lub numer kolumny i jeśli zmieniony numer wiersza lub kolumny jest o jeden większy lub mniejszy od poprzedniego. Aby zmienić reguły gry i zezwolić na wybór liter po przekątnej, można usunąć sprawdzenie, czy co najmniej jeden numer pozostał niezmieniony. Wówczas ostatni wiersz wyglądałby tak:

return (Math.abs(prevButtonRow - currButtonRow) <= 1) && Math.abs(prevButtonCol - currButtonCol) <= 1));

Sprawdzanie zgłoszonych słów

Ostatnim elementem kodu gry są mechanizmy sprawdzające zgłoszone słowa i aktualizujące wynik. Metoda searchForWord() zawiera oba te mechanizmy:

private function searchForWord(str:String):Number 
{ 
    if (words && str) 
    { 
        var i:uint = 0 
        for (i = 0; i < words.length; i++) 
        { 
            var thisWord:String = words[i]; 
            if (str == words[i]) 
            { 
                return i;     
            } 
        } 
        return -1; 
    } 
    else 
    { 
        trace("WARNING: cannot find words, or string supplied is null"); 
    } 
    return -1; 
}

Funkcja ta w pętli przegląda wszystkie słowa występujące w słowniku. Jeśli słowo użytkownika pasuje do słowa w słowniku, zwracana jest pozycja w słowniku. Następnie metoda submitWord() sprawdza odpowiedź i aktualizuje wynik, jeśli pozycja jest poprawna.

Dostosowywanie przykładu

Na początku definicji klasy umieszczono kilka stałych. Modyfikując je, można zmienić parametry gry. Na przykład zwiększenie wartości TOTAL_TIME spowoduje wydłużenie czasu przeznaczonego na grę. Można także nieznacznie zwiększyć wartość PERCENT_VOWELS , aby zwiększyć prawdopodobieństwo znajdowania słów.