Online piškvorky v PHP s MySQL 2.
V druhom pokračovaní online piškvoriek si prezrieme funkcie, ktoré sme si predstavili v predchádzajúcom článku – funkciu na spracovanie vstupov, funkciu na zobrazenie hracieho poľa a funkciu na zistenie víťaza hry. Nájdete tu aj zdrojové kódy skriptu.
function Action(&$row, &$s, &$master, &$slave)
V úvode funkcie si pretransformujeme pole $_GET na premenné a prekonvertujeme $pid na číselnú hodnotu:
if (isset($_GET)){
reset ($_GET);
while (list ($key, $val) = each ($_GET))
$$key = $val;
}
$pid *= 1;
Ďalej sa pustíme do postupného spracovania týchto premenných. Každá podmienka bude ukončená príkazom return True
alebo False
, podľa toho, či budeme zobrazovať sekciu hry, alebo nie, preto je dôležité zachovať poradie jednotlivých podmienok vo funkcii Action tak, ako si teraz ukážeme. Najskôr vytvorenie novej hry:
if ($m==“create“){
// osetri maximalny pocet hier
$p = mysql_fetch_array ( mysql_query („SELECT count(*) FROM piskvorky“) );
if ($p[0] >= MAXGAME){
$s .= „Prekročený maximálny počet vytvorených hier. Počkajte prosím, kým sa niektorá z hier ukončí.“;
return False;
}
// zaloz novu hru (zaznam),
// do db zapisujem: cas vytvorenia, master session, znacku „*“ pre prave vytvorenu hru
mysql_query („INSERT INTO piskvorky (begin, master_sess, last) VALUES (UNIX_TIMESTAMP(NOW()), ‚“.session_id ().“‚, ‚*‘)“);
// zisti „pid“ tejto hry
// mysql_insert_id vrati ID (AUTO_INCREMENT stlpec) posledneho INSERT prikazu
$row->pid = mysql_insert_id ();
$master = True;
// zobraz sekciu hry
return True;
} // vytvorenie hry
Hra bude vytvorená len ak nebol prekročený počet MAXGAME – počet záznamov v tabuľke „piskvorky“. Inak zobrazíme správu o tom, že hra nebola vytvorená a vyskočíme z funkcie s návratovou hodnotou False
. Metaelement v tomto prípade zabezpečí návrat na úvodnú stránku. Nastavenie premennej $master
na True
je potrebný z dôvodu volania funkcie pre zobrazenie hry, aby sa zobrazovali obrázky pre hráča MASTER. Funkciu opustíme príkazom return
s hodnotou True
, čo znamená, že sa bude zobrazovať sekcia hry. V prípade, že sa nevytvára nová hra, ale premenná pid (ID hry) nie je definovaná zobrazíme úvodnú obrazovku:
if (!$pid){
$s .= „ONLINE PIŠKVORKY“;
// vymaz stare hry
mysql_query („DELETE FROM piskvorky WHERE begin < (UNIX_TIMESTAMP(NOW())-„.TIMEOUT.“)“);
// vypis vytvorenych hier
$s .= „Vytvorené hry:<br/>“;
// najnovsie hry navrchu
$result = mysql_query („SELECT * FROM piskvorky WHERE last=’*‘ ORDER BY begin DESC“);
while ($row = mysql_fetch_object ($result)) {
// nacitaj odkaz z chatu
$row->chat = substr ($row->chat, 0, strpos ($row->chat, „<br/>“));
// odkaz na hru
$s .= „<a href=’index.php?pid=$row->pid&m=connect’>Hraj hru č. $row->pid založenú „.date(„j.n.Y G:i:s“, row->begin).“</a>“;
// zobraz k odkazu spravu z chatu (napr. nejaka vyzva pre pripajajucich sa…)
if ($row->chat)
$s .= “ – <span class=’info’>$row->chat</span>“;
$s .= „<br/>“;
}
// vypis aktivnych hier (obsadene hry)
$s .= „<hr/>Aktívne hry:<br/>“;
$result = mysql_query („SELECT * FROM piskvorky WHERE last!=’*‘ ORDER BY begin DESC“);
while ($row = mysql_fetch_object ($result)) {
$s .= „Hra č. $row->pid založená „.date(„j.n.Y G:i:s“, $row->begin).“ je aktívna.<br/>“;
}
// odkaz pre vytvorenie hry
$s .= „<hr/><a href=’index.php?m=create’>Vytvor hru</a>“;
// nezobraz sekciu hry
return False;
} // uvodna obrazovka
O čo sa stará úvodná stránka:
- vymazanie starých hier
- odkaz (
href='index.php?pid=$row->pid&m=connect
) na vytvorené hry (last='*'
) plus prvý odkaz z MAXMSG správ – napr. nejaká výzva pre pripájajúcich sa - zobrazenie aktívnych hier (
last!='*'
) - odkaz na vytvorenie novej hry (
href='index.php?m=create'
)
Ak pid nebude prázdne, načítame z tabuľky tento záznam. Ak záznam neexistuje, hra bola vymazaná a zobrazíme o tom správu:
// nacitaj zaznam o hre
$result = mysql_query („SELECT * FROM piskvorky WHERE pid=’$pid'“);
// hra bola vymazana
if (!mysql_num_rows ($result)){
$s .= „Hra bola vymazaná<br/><a href=’index.php’>Hraj znova !</a><br/>“;
// nezobraz sekciu hry
return False;
}
// hra existuje
$row = mysql_fetch_object ($result);
Odteraz máme vo vlastnostiach objektu $row
k dispozícii hodnoty položiek hry $pid
. Nasledujúca časť kódu zabezpečí pripojenie hráča na už vytvorenú hru a ošetruje pripojenie viacerých hráčov na tú istú hru. Takýto prípad môže nastať ak by v približne rovnakom čase klikli viacerí SLAVE hráči na odkaz vytvorenej hry, ktorý by sa nestihol refreshnut a zaradiť medzi aktívne hry (teda, že by to už nebol odkaz). Hráč bude ku hre pripojený vtedy, ak bude prázdna položka slave_sess
, kam zapíšeme session ID SLAVE hráča:
// niekto sa pripaja na hru
if($m==“connect“){
// vytvor SLAVE hraca
if (!$row->slave_sess){
mysql_query („UPDATE piskvorky SET slave_sess='“.session_id ().“‚, last=’m‘ WHERE pid=’$pid'“);
// zobraz sekciu hry
return True;
}
// SLAVE hrac uz existuje
else {
$s .=“Ľutujem, niekto sa na hru pripojil skôr.<br/>“;
// nezobraz sekciu hry
return False;
}
} // $m=connect
Dostávame sa k časti funkcie Action, v ktorej už máme istotu, že pripojený ku hre je niekto z aktívnych hráčov (SLAVE, alebo MASTER). Určíme si kto je kto:
// som MASTER ?
$master = ($row->master_sess == session_id ());
// som SLAVE ?
$slave = ($row->slave_sess == session_id ());
// formatuj suradnice, ak existuju
$coo = ($x!=““ && $y!=““) ? sprintf (FORMAT, $x, $y) : False;
Tiež naplníme $coo
formátovanou hodnotou súradníc, ak boli nejaké zadané (pri kliknutí na nejakú bunku hracieho poľa). Môže sa však stať, že niekto by do URL zadal ručne hodnotu existujúcej hry, čo musíme ošetriť, ak nechceme mať v hre divákov (naviac by to spôsobovalo chyby pri vyhodnocovaní víťaza):
// ani MASTER ani SLAVE
if(!$master && !$slave){
$s .= „Nepovolený vstup do hry č. $row->pid !“;
return False;
}
Zápis posledných MAXMSG správičiek z chatu do databázy urobíme v týchto krokoch:
// chat
if($txt){ // zadana sprava
// osetrenie vstupu a pridanie novej spravy (s IP adresou hraca)
$row->chat .= „[„.$REMOTE_ADDR.“] – „.stripslashes( strtr ( sprintf („%.80s“,$txt), „<>&“,“***“) );
// uloz spravy ako prvky pola
$row->chat = explode („<br/>“, $row->chat);
// vyber len poslednych MAXMSG sprav
// zaporna hodnota parametra „offset“ pre array_slice vybere pocet „offset“ prvkov od konca pola
$row->chat = array_slice ($row->chat, -MAXMSG);
// zlep prvky pola
$row->chat = implode („<br/>“, $row->chat);
// a uloz ich do db
mysql_query („UPDATE piskvorky SET chat=’$row->chat<br/>‘ WHERE pid=’$pid'“);
// zobraz sekciu hry
return True;
}
V prvej časti článku sme si povedali, že hru budeme označovať na vymazanie, ak sa hráčovi zobrazí vyhodnotenie. Teraz môžeme skontrolovať túto položku a hru vymazať:
// zmaze ukoncenu hru (znacka „d“)
if($row->last == „d“){
mysql_query („DELETE FROM piskvorky WHERE last=’d‘ AND pid=’$pid'“);
// zobraz sekciu hry
return True;
}
Nakoniec nám ostáva zapísať súradnice bunky príslušného hráča, najskôr MASTER:
if ($master && $coo){
// naposledy tahal (alebo vytvoril hru) MASTER – na rade je druhy hrac
if($row->last==“m“ || $row->last==“*“){
$s .= „Na rade je druhý hráč SLAVE<br/>“;
// zobraz sekciu hry
return True;
}
// kontrola buniek
if ( strstr($row->slave, $coo) ){
$s .= „Obsadené políčko hráčom SLAVE<br/>“;
// zobraz sekciu hry
return True;
}
// zapis MASTER suradnice do db
$row->master .= $coo;
mysql_query („UPDATE piskvorky SET master=’$row->master‘, last=’m‘ WHERE pid=’$pid'“);
// zobraz sekciu hry
return True;
} // $master && $coo
Podmienka if ($master && $coo)
bude pravdivá, len ak je hráč MASTER a máme nastavené súradnice – inak povedané, hráč MASTER klikol na bunku hracieho poľa. Ďalšími podmienkami ošetríme udalosti:
- na ťahu je druhý hráč (zistíme podľa položky last – „*“ určuje práve vytvorenú hru, teda prvý na ťahu bude vždy hráč, ktorý sa na hru pripája = SLAVE)
- políčka obsadené druhým hráčom (prehľadanie súradníc protihráča SLAVE)
Ak nebudú tieto podmienky pravdivé zapíšeme súradnice do databázy a položku last nastavíme na „m“ – posledný na ťahu bol MASTER. Rovnaký postup použijeme aj pre hráča SLAVE, okrem kontroly last="*"
, pretože tento hráč má právo ťahať prvý.
if ($slave && $coo){
// naposledy tahal SLAVE – na rade je druhy hrac
if ($row->last==“s“){
$s .=“Na rade je druhý hráč MASTER<br/>“;
// zobraz sekciu hry
return True;
}
// kontrola buniek
if ( strstr($row->master, $coo) ){
$s .=“Obsadené políčko hráčom MASTER<br/>“;
// zobraz sekciu hry
return True;
}
// zapis SLAVE suradnice do db
$row->slave .= $coo;
mysql_query („UPDATE piskvorky SET slave=’$row->slave‘, last=’s‘ WHERE pid=’$pid'“);
// zobraz sekciu hry
return True;
} // $slave && $coo
Dostávame sa k ukončeniu funkcie Action. Ak nenastala ani jedna zo spomínaných podmienok, znamená to, že je potrebný len refresh stránky, respektíve refresh sekcie hry, pretože si môžeme byť istý, že hráč je MASTER, alebo SLAVE, teda už sa nachádzame v sekcii hry. Ukončenie funkcie Action:
// zobraz sekciu hry – iba refresh – ziadna udalost
return True;
function Area (&$s, $row, $master, $slave)
Area napĺňa premennú $s
HTML kódom, ktorý zabezpečí zobrazenie hracieho poľa. Dáta pre hracie pole si uložíme do dvojrozmerného poľa $matrix
:
// dvojrozmerne pole $matrix naplnime hodnotami: „x“=SLAVE bunka, „o“=MASTER bunka, „*“=prazdna bunka
for ($y=0 ; $y<AREA; $y++){
for($x=0 ; $x<AREA; $x++){
$coo = sprintf (FORMAT, $x, $y);
if ( strstr($row->master, $coo) )
$matrix[$y][$x] = „x“;
else if ( strstr($row->slave, $coo) )
$matrix[$y][$x] = „o“;
else
$matrix[$y][$x] = „*“;
}
}
V ďalšom kroku zavoláme funkciu WinTest s parametrom $matrix
(predaným odkazom), ktorá vyhodnotí víťaza hry a vráti 0 (ak nie je víťaz), 1 (ak je víťaz MASTER), 2 (víťaz je SLAVE) alebo 3 (ak nastala remíza – obsadené všetky bunky, ale niet víťaza). Na základe tejto návratovej hodnoty zobrazíme odpovedajúcim hráčom výsledok hry:
// funkcia na zistenie vitaza: 0=neni, 1=MASTER, 2=SLAVE, 3=remiza
// taktiez oznaci vitazny tah
$win = WinTest ($matrix);
// zobraz info o vitazstve, prehre..
if (($win == 1 && $master) || ($win == 2 && $slave))
$s .= „<b>Gratulujem, si víťaz !</b><br/>“;
else if (($win == 1 && $slave) || ($win == 2 && $master))
$s .= „<b>Ľutujem, prehral si !</b><br/>“;
else if ($win == 3)
$s .= „<b>Remíza.</b><br/>“;
Hracie pole bude vytvorené elementom table
a bunky tabuľky budú reprezentovať bunky hracieho poľa. Kliknúť na bunku sa bude dať len vtedy, ak hra ešte neskončila ($win==0
) a bunka je prázdna ($matrix[$y][$x] == "*"
). Tam, kde sa bude dať kliknúť, budeme zobrazovať odkaz s pid hry a súradnicami bunky (href='index.php?pid=$row->pid&x=$x&y=$y'
). Odkaz je obohatený o udalosti onmouseover a onmouseout, pomocou ktorých zobrazujeme na prázdnych bunkách pri prechode kurzora príslušné obrázky. Ďalej v cykle cez príkaz „switch“ priradíme bunkám obrázky:
// generuje hracie pole
$s .= „<table cellspacing=’0′ cellpadding=’1′ border=’0’>“;
for ($y=0 ; $y<AREA ; $y++){
$s .= „<tr>“;
for($x=0 ; $x<AREA ; $x++){
// odkaz pridavaj len ak sa este hra
if ( !$win && $matrix[$y][$x] == „*“){
$over = $master ? „x3.gif“ : „o3.gif“;
$a_start = „<a href=’index.php?pid=$row->pid&x=$x&y=$y‘
onmouseover = ‚document.images.x$x“.“y$y.src=\“$over\“‚
onmouseout = ‚document.images.x$x“.“y$y.src=\“blank.gif\“‚>“;
$a_end = „</a>“;
}
else {
$a_start = $a_end = „“;
}
// podla znacky zobraz obrazok
switch ($matrix[$y][$x]){
case „x“:
$src = „x.gif“;
break;
case „[x]“:
$src = „x2.gif“;
break;
case „o“:
$src = „o.gif“;
break;
case „[o]“:
$src = „o2.gif“;
break;
default:
$src = „blank“;
break;
}
$s .= „<td width=’39‘ height=’39’>$a_start<img src=’$src‘ width=’39‘ height=’39‘ border=’0′ name=’x$x“.“y$y‘ />$a_end</td>“;
}
$s .= „</tr>“;
}
$s .= „</table>“;
Na záver zobrazíme správy chatu a, ak sa ešte hrá, aj formulár na vpisovanie správ s focusom na tento prvok:
// chat text
$s .= „<hr/>$row->chat“;
// ak sa este hrá zobraz formular na chat a nasmeruj nan kurzor
if ( !$win ){
$s .= „<form action=’index.php‘ method=’get‘ name=’f’><input type=’hidden‘ name=’pid‘ value=’$row->pid‘ /><input type=’text‘ name=’txt‘ size=’40‘ /> <input type=’submit‘ value=’Odošli správičku‘ /></form>“;
$s .= „<script type=’text/javascript’>document.f.txt.focus ()</script>“;
}
return $win;
function WinTest (&$matrix)
Funkcia WinTest kontroluje dvojrozmerné pole $matrix
a vráti víťaza – 0 (neni), 1 (MASTER), 2 (SLAVE) alebo 3 (remíza). Naviac nám toto pole doplní ($matrix
je volaný odkazom) o víťazný ťah tak, že hodnoty víťazných prvkov uzavrie do hranatých zátvoriek. Takto budeme pri vykresľovaní vedieť, do ktorých buniek vkladať obrázok pre víťazný ťah. Víťazný ťah kontrolujeme vo štyroch smeroch – horizontálny, vertikálny a dve diagonály. Kontrola každého smeru je urobená cez cykly, ukážeme si len horizontálny smer:
for ($y=0 ; $y<AREA; $y++){
$win[0]=$win[1]=0;
for($x=0 ; $x<AREA ; $x++){
if ($matrix[$y][$x] == „x“){
$win[0]++;
$win[1]=0;
}
else if ($matrix[$y][$x] == „o“){
$win[1]++;
$win[0]=0;
}
else
$win[0]=$win[1]=0;
if ($win[0] == WINNER){
for($x=0 ; $x<AREA; $x++)
$matrix[$y][$x] = ($matrix[$y][$x]==“x“) ? „[x]“ : $matrix[$y][$x];
return 1;
}
if ($win[1] == WINNER){
for($x=0 ; $x<AREA; $x++)
$matrix[$y][$x] = ($matrix[$y][$x]==“o“) ? „[o]“ : $matrix[$y][$x];
return 2;
}
}
}
Premenná $win[0]
určuje počet buniek hráča MASTER idúcich za sebou, $win[1]
to isté pre hráča SLAVE. Ak bude tento počet zhodný s počtom WINNER, označíme víťazný ťah (hranaté zátvorky) a príkazom return vrátime hodnotu pre daného víťaza. Ak viete o lepšom algoritme na kontrolu víťazného ťahu, neváhajte mi napísať.
Dúfam, že skript sa vám páčil. Samotná hra nie je asi veľmi zábavná, ale ako ukážka vytvorenia online hry v PHP to myslím postačí, naviac zopakujem, že sme použili len jednu databázovú tabuľku a session využívame len na identifikáciu užívateľa. Opäť uvádzam odkaz na ukážku (AREA=5, WINNER=4) a dnes aj na samotný skript.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
AI v programování: Jak používat GitHub Copilot (část 2)
19. února 2024 -
Thunderbolt 4 vs. OCuLink: Přišel čas na upgrade?
27. května 2024 -
ZONER Webmail jako první v Česku přináší BIMI s VMC
11. července 2024
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024
MEN-X
Říj 13, 2009 v 22:36Složitěji by to snad ani nešlo. Sry tohle neni tutorial, ale návod jak co nejvíce skrátit kód..