Archive for the ‘Nezařazené’ Category

Android Sudoku Solver

Napsal jsem jednoduchou aplikaci pro OS Android, která umí vyřešit zadané sudoku. Tento sudoku řešič jsem psal z nudy a dlouhého čekání na můj Samsung Galaxy S, který je stále na reklamaci. V tomto příspěvku nebudu rozvádět celý zdrojový kód, jen rozvedu pár drobností. Zdrojový kód a samotnou aplikaci (pokud si ji chcete vyzkoušet na svém Android zařízení) si můžete stáhnout na konci tohoto příspěvku.

Ukázka programu

Použitý algoritmus

Algoritmus pro řešení sudoku zde nebudu vůbec rozebírat. Lze použít jakýkoliv jiný algoritmus pro řešení sudoku. Já použil tento, protože jsem jeho zdrojový kód měl na svém disku. Tento algoritmus jsme napsali s mými spolužáky (Martinem Paroubkem a Lukášem Matějů) jako semestrální práci na předmět Teorie grafů a her. Algoritmus původně hledal všechna možná řešení, ale pro tuto aplikaci jsem ho upravil tak, aby vracel pouze první korektní nalezené řešení. Použitý algoritmus využívá metody hladového barvení, přičemž pořadí vrcholů v cyklu volí podle stupně nasycení. Při implementaci algoritmu jsem nejspíše přišel na chybnost algoritmu, která zpomaluje výpočet, ale zatím jsem se chybu nepokoušel nalézt.

Mřížka sudoku

Na mřížku sudoku jsem si napsal vlastní widget. Tento widget vykresluje kromě mřížky také vyplněná čísla a obstarává reakci na dotek displeje. Po vyvolání události onTouchEvent této komponenty se otevře dialog, který umožní výběr čísla na danou pozici.

Dialogy a čekání na návratovou hodnotu

Že zavoláme u dialogu metodu show(), počkáme až skončí a načteme poté data z dialogu? Ale kdepak. Každý si u vývoje GUI v operačním systému Android uvědomit, že se vše děje asynchronně. Na zmíněný problém nám ale postačí OnDismissListener(). Jak jej použít je znázorněnu na následujícím útržku kódu.

numberSelectDialog.setOnDismissListener(new OnDismissListener() {
   public void onDismiss(DialogInterface dialInterface) {
      //reaguj na to, ze byl dialog zavren
   }
});

Tato událost je vyvolána v případě, že je dialog ukončen metodou dismiss(). V případě, že je dialog ukončován metodou cancel(), můžeme použít OnCancelListener.

Menu

Jak vytvořit menu v Android aplikaci je snadné. Jako demonstrace skvěle poslouží Creating Menus.

Soubory ke stažení

Zdrojové kódy programu Sudoku Solver – SudokuSolverSource.zip
Instalační soubor Sudoku Solver – SudokuSolverApk.zip


Java pong

Napsat hru Pong v Javě by mě nyní ani nenapadlo. Chtěl jsem původně napsat Pong pro OS Android, ale asi v půlce vývoje mi odešel telefon, takže je nyní na reklamaci. Jen mimo řeč bych rád zmínil, že program Kies od Samsungu opravdu stojí za to. Je tak dobře napsaný, že mu nedělá problémy spadnout při aktivitě, jako je například upgrade firmwaru telefonu. Ano, přesně z tohoto důvodu putuje můj telefon po servisním oddělení společnosti Samsung. Samozřejmě existovala možnost nahrát nějakou neoficiální ROM, ale pomyšlení na ztrátu záruky v případě poruchy telefonu mi to nedovolilo. Nyní zase k věci. Telefon není doma, provádět všechny testy v AVD se mi nechtělo, tak jsem se rozhodl, že dopíši Pong prozatím v Java SE. Hra není úplně dolazena a má nedostatky, víceméně jsem její tvorbou jen zabíjel čas.

Nebudu v tomto příspěvku rozvádět každý kousek kódu. Celý zdrojový kód včetně výsledné aplikace si můžete stahnout z odkazů umístěných na konci příspěvku. Hlavní logika hry, vykreslování, ovládání klávesnicí se nachází ve třídě Pong.java, která obsahuje asi 150 řádků kódu. Nejedná se tedy o nic složitého. Dále se pokusím poukázat na pár detailů, které by se mohli programátorům začátečníkům hodit – aby měl tento příspěvěk alespoň nějaký význam :) .

Double buffering

Předpokládám, že není třeba termín vysvětlovat. Pokud někdo přeci jen neví oč jde, může se podívat například sem. Jak v Javě řešit tento problém existuje více způsobů. Jeden způsob je zmíněn v odkazu, který je umístěn  na začátku odstavce. Já použil trošku jiný styl řešení. Kreslím vše do obrázku. Pokud je vše vykresleno, tak tento obrázek vykreslím na obrazovku. To bohatě stačí k zamezení protivného problikávání obrazu způsobeného neustálým překreslováním při kreslení dalších a dalších tvarů.

Image bufferImage = createImage(getWidth(), getHeight());
Graphics buffer = bufferImage.getGraphics();

Tímto kódem se vytvoří obrázek – instance třídy Image, který poté bude vykreslován na obrazovku (v tomto případě do panelu JPanel) a instance třídy Graphics, pomocí níž jsme schopni do obrázku kreslit základní tvary atd.

@Override
public void paint(Graphics g) {
    buffer.drawString("Ahoj :]", 20, 20);
    g.drawImage(bufferImage, 0, 0, this);
}

Zde je už jen příklad přetížené metody paint, ve které do „bufferovaného“ obrázku zakreslíme řetězec a následně je vykreslen „bufferovaný“ obrázek.

Stisk více klávec najednou

Tento problém jsem vyřešil tak, že jsem ho vlastně moc neřešil. Na nějakém fóru jsem zahlédl jedno řešení a to použil. Nejedná se ovšem o moc použitelnou variantu, což si každý může v aplikaci vyzkoušet. Nicméně to funguje o level lépe, než kdyby se to neřešilo vůbec.

private Set pressedKeys = new HashSet();
@Override
public void keyPressed(KeyEvent e) {
    pressedKeys.add(e.getKeyCode());
    if (pressedKeys.size() > 0) {
            for (int i : pressedKeys) {
                switch (i) {
                    case KeyEvent.VK_UP:
                    //do something
                    .
                    .
                    .
                }
            }
     }
}

@Override
public void keyReleased(KeyEvent e) {
    pressedKeys.remove(e.getKeyCode());
}

Jde jen o registraci instance třídy HashSet, přičemž se do ní ukládá kód stishnuté klávesy. Jestliže je vyvolána událost keyReleased, která nastane pokud pustíme stiknutou klávesu, tak se z kolekce její kód odebere. Pokud jsou nějaké klávesy stishnuny, je volána obslužná metoda keyPressed a v ní je možno iterovat stisknuté klávesy, které jsou uloženy v kolekci typu HashSet.

Náhodná hodnota z výčtu (enum)

Pro směr míčku jsem si udělal výčet směrů. Když jsem poté řešil, jak elegantně vyřešit návrat náhodného směru, tak jsem došel k následujícímu řešení.

public enum Direction {

    RIGHT_DOWN,
    RIGHT_UP,
    LEFT_DOWN,
    LEFT_UP;

    private static final List VALUES = Arrays.asList(values());
    private static final int SIZE = VALUES.size();
    private static final Random RANDOM = new Random();

    public static Direction randomDirection() {
        return VALUES.get(RANDOM.nextInt(SIZE));
    }
}

Zdrojové kódy hry Pong – PongSE.zip
Hra Pong – PongSE-jar.zip


Kreslení v Androidu

Kreslení v Androidu není žádná složitost. Stačí vytvořit třídu, která bude dědit od třídy View. To je třída, která je předkem všech grafických komponent systému Android – tzv. widgetů. V naší třídě poté stačí přetížit metodu onDraw, která má vstupní parametr instanci třídy Canvas. Na tomto objektu již můžeme provádět kreslící „kousky“ :) . Takováto ukázková třída může vypadat takto:

public class Platno extends View {

    Paint paint = new Paint();

    public Platno(Context context) {
        super(context);
    }

    @Override
    public void onDraw(Canvas canvas) {
        paint.setColor(Color.BLUE);
        canvas.drawRect(new Rect(0, 0, 50, 100), paint);
        paint.setColor(Color.RED);
        canvas.drawCircle(100, 100, 50, paint);
    }
}

Poté stačí vytvořit instanci této třídy, například v základní třídě projektu a nastavit ContentView na vytvořenou instanci.

public class CanvasTest extends Activity
{
    Platno platno;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        platno = new Platno(this);
        platno.setBackgroundColor(Color.GRAY);
        setContentView(platno);
    }
}

Výsledek v tomto případě vypadá takto:

ukázka výstupu


Změna stránek

Se svými starými, již 2 roky neaktualizovanými, stránkami jsem již nebyl spokojen. Rozhodl jsem se tedy, že stránky potřebují velkou úpravu. Z lennosti jsem využil redakční systém WordPress. Staré stránky jsou stále aktivní, ale nyní pod jinou doménou. Odkaz můžete nalézt v pravém postraním panelu v sekci odkazy. Na starých stránkách je mnoho návodů, které mohou pomoci začínajícím programátorům, kteří upřednostňují jazyk Java. Musím ale zdůraznit, že na mnoho stránkách se nachází ne úplně pravdivý obsah – přece jen jsem stránky psal na střední škole se znalostmi, které nebyly moc slavné.

Tím, že jsem tyto stránky „renovoval“ bych nerad skončil. Čas od času mám v plánu nějaký ten příspěvek přidal. Většinou by se jednalo o příspěvky z oboru programování, momentálně i z programování aplikací pro OS Android.

Také bych tímto příspěvkem rád poděkoval „stálým návštěvníkům“, kteří i na přes 2 roky neaktualizovaném webu odebírají RSS kanál. Díky :)


Hledat


Menu

Archiv

Odkazy