Kurz2 - Kapitola7

17. června 2007 v 15:59 | http://www.sweb.cz/kurz_evt/ |  Programování pro WinCE

4.7 Náhodné promíchání hracího pole

V minulém díle nedokončená funkce Michani volá po dokončení. Doplňme do ní následující zdrojový kód:
// Funkce pro michani kostek - nKolik urcuje pocet pokusu o presun
void Michani(int nKolik)
{
int j, nVolne, nSmPos;
// Najdu prazdnou pozici
for (nVolne=0; nVolne<16; nVolne++)
if (!nCislo[nVolne]) break;
// Inicializuji generator nahody
srand((unsigned int)GetTickCount());
// Nahodne posunu tolikrat, kolik je pozadovano
for(j=0; j<nKolik; j++) {
// Nejprve vygeneruju nahodny smer posunu
nSmPos=(int)abs(rand()%4);
// Pak provedu (je-li mozno) presun ...
// ...nahoru
if((nSmPos==0)&&(nVolne<12)) {
nCislo[nVolne]=nCislo[nVolne+4];
nVolne=nVolne+4;
nCislo[nVolne]=0;
}
// ...dolu
if((nSmPos==1)&&(nVolne > 3)) {
nCislo[nVolne]=nCislo[nVolne-4];
nVolne=nVolne-4;
nCislo[nVolne]=0;
}
// ...vlevo
if((nSmPos==2)&&((nVolne%4)<3)) {
nCislo[nVolne]=nCislo[nVolne+1];
nVolne=nVolne+1;
nCislo[nVolne]=0;
}
// ...vpravo
if((nSmPos==3)&&((nVolne%4)>0)) {
nCislo[nVolne]=nCislo[nVolne-1];
nVolne=nVolne-1;
nCislo[nVolne]=0;
}
}
}
Aby byla funkce univerzální, je nejprve v poli nCislo nalezeno prázdné políčko. Druhým přípravným krokem je inicializace generátoru náhodného čísla.
Po dokončení příprav následuje vlastní smyčka, která provede tolik pokusů o přesun kostky, kolik je zadáno jako parametr. Protože některé pokusy nemusí být úspěšné (mimo okraj hracího pole nelze posunovat, někdy se dva po sobě jdoucí tahy ruší, vygenerovaný směr nemusí být volný), je vhodné zadávat jako hodnotu parametru vyšší číslo. V praxi se osvědčil počet pokusů kolem 1000.
Abychom měli hrací pole zamíchané hned při startu, doplňte do zprávy WM_CREATE za naplnění hracího pole hodnotami kostek příkaz na promíchání:
   // Inicializace hraciho pole
for(i=0;i<16;i++) nCislo[i]=(i+1)%16;
Michani(1000);
Jestliže program přeložíte a otestujete, měli byste mít první verzi, se kterou se dá již hrát...

4.8 Volba barvy pozadí

... my jsme však nároční a program ještě doplníme o několik drobností.
Do nabídkového menu vložte novou volbu Options, která bude mít dvě položky - viz obrázek:

obr. 44 Nové položky v nabídce
Jejich ID upravte na ID_BACKGROUNDCOLOR a ID_SOUND.
Nyní se pokusíme doplnit obsluhu těchto dvou položek v menu. První z nich bude měnit pozadí programu a druhá bude povolovat nebo zakazovat zvukové efekty.
Do obsluhy zprávy WM_COMMAND doplňte:
   case ID_BACKGROUNDCOLOR:
cc.lStructSize=sizeof(CHOOSECOLOR);
cc.hwndOwner=hWnd;
cc.hInstance=NULL;
cc.rgbResult=dwBarva;
cc.lpCustColors=crCustColors;
cc.Flags=CC_RGBINIT | CC_SOLIDCOLOR;
cc.lCustData=0;
cc.lpfnHook=NULL;
cc.lpTemplateName=NULL;
if (ChooseColor(&cc)) {
dwBarva=cc.rgbResult;
DeleteObject(hPozadi);
hPozadi=CreateSolidBrush(cc.rgbResult);
}
InvalidateRect(hWnd,NULL,TRUE);
break;
case ID_SOUND:
hMenu=CommandBar_GetMenu(hwndCB,0);
if(dwZvuk) {
dwZvuk=0;
CheckMenuItem(hMenu,ID_SOUND,MF_UNCHECKED);
}
else {
dwZvuk=1;
CheckMenuItem(hMenu,ID_SOUND,MF_CHECKED);
}
break;
Obsluha ID_SOUND nepotřebuje snad komentář, podobný zdrojový text můžete objevit v postupu tvorby předcházejícího programu - HexaView.
Poznamenejme, že je potřeba pouze doplnit globální proměnnou dwZvuk, která je připravena pro příští díl:
   DWORD   dwZvuk;         // Priznak pouzivani zvuku
...a lokální proměnnou ve funkci WndProc:
   HMENU hMenu;
Obsluha ID_BACKGROUNDCOLOR má za úkol vyvolat společný dialog ChooseColor. Před jeho voláním je třeba naplnit strukturu cc typu CHOOSECOLOR a připravit další proměnnou vyžadovanou funkcí ChooseColor.
Doplňte lokální proměnné funkce WndProc o:
   // Pomocne promenne pro volbu barvy pozadi
CHOOSECOLOR cc;
COLORREF crCustColors[16];
Pokud funkce ChooseColor vrátí nenulovou hodnotu, je zrušen starý štětec pozadí a vytvořen nový pro vybarvování pozadí. Pokud se nyní pokusíte program přeložit, asi vám překladač zahlásí, že funkci ChooseColor nezná. Ta je totiž součástí knihovny commdlg. Pro její použití je nutno vložit na úvod souboru Fifteen.cpp hlavičkový soubor
#include <commdlg.h>
a v Project->Settings... na kartě Link doplňte do kolonky Object/Library modules další knihovnu - commdlg.lib.
Program již přeložíte, ale nastavování pozadí ještě nepracuje správně. Protože překladač odmítal parametr GCL_HBRBACKGROUND u funkce SetClassLong, vyzkoušíme vykreslení pozadí vlastním - uživatelským způsobem.
Ve funkci MyRegisterClass programu zrušte zadání štětce pro pozadí okna:
   wc.hbrBackground = NULL;
Protože nyní okno nemá zadaný štětec pro vykreslení pozadí, musíme se o obnovu pozadí okna starat sami. Nezbývá tedy než doplnit obsluhu zprávy WM_ERASEBKGND, která je poslána vždy, když je potřeba překreslit pozadí okna:
case WM_ERASEBKGND:
GetUpdateRect(hWnd, &rt, FALSE);
hdc=GetDC(hWnd);
FillRect(hdc,&rt,hPozadi);
ReleaseDC(hWnd,hdc);
return 1;
Zde se pouze celý obdélník klientské vyplní štětcem pozadí. Zvláštností je, že obsluha zprávy by měla vracet nenulovou hodnotu, jako příznak provedení vymazání pozadí. Aby se nám překreslilo pozadí při zpracování zprávy WM_PAINT, doplňte na úvod zpracování zprávy WM_PAINT jeden řádek, kterým se pošle zpráva s žádostí o vymazání pozadí před vlastním kreslením:
   SendMessage(hWnd,WM_ERASEBKGND,0,0);
V tomto okamžiku již můžete možná hrát na takovém hezkém pozadí jako je např.:

obr. 45 Herní plocha se změněným pozadím
Bohužel, možná ano, ale pouze někteří ... :-(
Důvodem je fakt, na který v helpu k eVT není žádné upozornění. Některé kapesní přístroje bez klávesnice (PPC - jako např. Casio E-15) sice podporují částečně knihovnu společných dialogů, ale ne vše je implementováno. Tak např. dialog pro otevření souboru z knihovny commdlg.lib můžete použít, ale právě zvolená ChooseColor odmítá spolupracovat - přístroj vytrvale hlásí chybějící knihovnu. Dialogy Print a ChooseColor PPC nepodporují. Nezbude nám, než si jednoduchý dialog pro výběr barvy vytvořit sami.
Ale to ...viz příště :-)

Co bychom si měli z této lekce zapamatovat?

  • Generátor náhodného čísla vytvoříme např. pomocí funkcí srand a rand.
  • Pro volbu barvy se hodí společný dialog ChooseColor, nefunguje však vždy.
  • Pro obsluhu vykreslení pozadí stačí zpracovat zprávu WM_ERASEBKGND.
  • Je třeba testovat a zkoušet! Ne vše pracuje, jak bychom čekali :-)
 

Buď první, kdo ohodnotí tento článek.

Nový komentář

Přihlásit se
  Ještě nemáte vlastní web? Můžete si jej zdarma založit na Blog.cz.