Online piškvorky v PHP s MySQL 1.

21. května 2003

Pre čitateľov Interval.cz som si pripravil článok, popisujúci skript, ktorý umožňuje hrať dvom hráčom cez internet jednoduchú hru, piškvorky. A nechýba ani funkčná ukážka.

Tvorba SQL tabuľky

Údaje o hre si budeme ukladať do tabuľky „piskvorky“, každý záznam bude znamenať údaj o jednej hre, či už aktívnej (pripojení obaja hráči), alebo vytvorenej (druhý hráč ešte nie je pripojený). Pre lepšiu orientáciu medzi hráčmi si ich pomenujeme:

  • MASTER – hráč, ktorý hru vytvorí
  • SLAVE – hráč, ktorý sa na hru pripája

Viac tabuliek k piškvorkám nebudeme potrebovať. Databázu som pomenoval „hra“ a bude obsahovať len spomínanú tabuľku. Popis položiek tabuľky piskvorky:

  • pid – ID hry
  • begin – čas vytvorenia hry (počet sekúnd od 1. 1. 1970)
  • master – hodnoty súradníc obsadených buniek hráčom MASTER
  • master_sess – session ID hráča MASTER
  • slave – hodnoty súradníc obsadených buniek hráčom SLAVE
  • slave_sess – session ID hráča SLAVE
  • chat – texty správ hráčov
  • last – kto bol posledný na ťahu

Teraz si v našom obľúbenom správcovi databázy (napríklad phpMyAdmin) vytvoríme databázu „hra“, do ktorej z nižšie uvedeného SQL príkazu vložíme tabuľku „piskvorky“.

CREATE TABLE piskvorky (
    pid int(10) unsigned NOT NULL auto_increment,
    begin int(10) unsigned,
    master text,
    master_sess varchar(32),
    slave text,
    slave_sess varchar(32),
    chat text,
    last char(1),
    PRIMARY KEY (pid)
);

Úvod PHP skriptu a konštanty

V úvode skriptu naštartujeme session funkciou session_start, ktorá nám zabezpečí vytvorenie identifikátora. Tu musím upozorniť, že skript počíta s nastavenou nasledovnou direktívou v PHP.INI:

; use transient sid support if enabled by compiling with –enable-trans-sid.
session.use_trans_sid = 1

Toto nám zabezpečí automatické doplnenie session ID do odkazov a formulárov. Pri vypnutej direktíve však nie je problém doplniť tieto hodnoty ručne. Po štarte session ošetríme, aby stránka nebola cachovaná prehliadačom ani proxy servermi pomocou známej sady hlavičiek:

header („Pragma: no-cache“); // HTTP/1.0
header („Cache-Control: no-cache, must-revalidate“); // HTTP/1.1
header („Expires: „.GMDate(„D, d m Y H:i:s“).“ GMT“);
header („Last-Modified: “ .GMDate(„D, d M Y H:i:s“).“ GMT“);

Niektoré nastavenia hry je možné meniť nasledovnými konštantami:

// rozmery hracieho pola
define („AREA“, 4);
// pocet buniek potrebnych na vitazstvo
define („WINNER“, 4);
// po uplynuti tohto casu (sekundy) od vytvorenia hry bude hra vymazana
define („TIMEOUT“, 60*8);
// kolko sprav sa bude zobrazovat na obrazovke
define („MAXMSG“, 10);
// format ukladania suradnic do databazy
define („FORMAT“, „[%d|%d]“);
// pocet sekund pre znovunacitanie stranky pomocou META tagu
define („REFRESH“, 8);
// absolutna cesta
define („URL“, „http://localhost/hra/“);
// max pocet vytvorenych hier
define („MAXGAME“, 50);

Hracie pole je štvorec, ktorého rozmer je určený konštantou AREA. Počet buniek na víťazstvo určuje, koľko buniek v povolenom smere musí byť obsadených jedným hráčom, teda hodnota nemusí byť zhodná s rozmermi hracieho poľa – napríklad hracie pole 10×10 a pri WINNER=3 stačia 3 vyplnené bunky v povolenom smere na výhru. Po uplynutí hodnoty nastavenej v TIMEOUT od založenia hry bude hra vymazaná bez ohľadu na to, či hráči ešte hrajú. Možno by bolo vhodné nastaviť ju „automaticky“ podľa veľkosti AREA, napríklad define ("WINNER", 60*AREA*2).

MAXMSG nám určuje počet koľko správ sa bude uchovávať v databáze, respektíve zobrazovať na obrazovke. Súradnice sa zapisujú do položky typu TEXT (maximálne 65535 znakov) vo formáte určenom konštantou FORMAT. Takto budú súradnice každej bunky v položke zapísané jednoznačne, keď budeme súradnicu vyhľadávať funkciou StrStr (vyhľadanie podreťazca v reťazci).

Stránky budú refreshované pomocou metaelementu, konštanta REFRESH určuje periódu znovunačítania stránky. Znovunačítanie stránky prebehne aj vtedy, ak sa v zázname pre hru nezmení žiadna položka. Tu je možné využiť riešenie pomocou skrytého rámca (frame), tak ako som to ukázal v článku o jednoduchom online chate, ktoré zabezpečí znovunačítanie len v prípade zmeny v zázname hry. URL je absolútna čast parametra url pre metaelement. V prípade prekročenia počtu MAXGAME (aktívne aj vytvorené hry) nebude možné vytvoriť novú hru.

Pripojenie k databáze

K databáze sa budeme pripájať pomocou perzistentného spojenia, v tomto prípade na localhost. Pripomínam, že pre správne fungovanie perzistentného spojenia musí PHP bežať ako modul Apache, inak bude vytvorené len obyčajné pripojenie. Taktiež je potrebné mať v PHP.INI zapnutú direktívu mysql.allow_persistent = On.

// vytvorenie perzistentneho spojenia
mysql_pconnect () or die („Nepodarilo sa pripojiť k databáze !“);
// vyber db
mysql_select_db („hra“) or die („Nepodarilo sa vybrať databázu !“);

Hlavná časť PHP skriptu

Skript pre hru je napísaný v jednom súbore. Hlavná časť skriptu pozostáva z troch vlastných funkcií. Action slúži na spracovanie vstupov a na zápis údajov do databázy. Parametre $row, $s, $master, $slave sú volané odkazom, teda funkcia nám ich naplní potrebnými údajmi:

  • $row – objekt, ktorý nám vráti funkcia mysql_fetch_object (položky hry $pid)
  • $s – reťazec obsahujúci HTML obsah stránky
  • $master – bude True, ak hráč je MASTER, teda zakladateľ hry
  • $slave – bude True, ak hráč je SLAVE, teda hráč ktorý sa na hru pripojil

Pole $_GET je „superglobálna“ premenná, obsahujúca parametre predané metódou GET, hra teda pobeží aj s direktívou register_globals = Off. Podrobnejšie si funkciu rozoberieme neskôr, teraz je pre nás dôležitá jej návratová hodnota, a to True, ak sa má zobraziť sekcia hry (čiže samotná hra), alebo False, ak sa má zobraziť úvodná obrazovka.

Pri zobrazovaní sekcie hry voláme ďalšiu funkciu Area, ktorá zobrazí hracie pole a v prípade víťazstva, prehry, alebo remízy vráti kladnú hodnotu, inak nulu. Parametre funkcie Area nám naplnila funkcia Action. Premenná $s je volaná odkazom a funkcia Area nám ju naplní HTML obsahom hracieho poľa. Ak funkcia vráti kladnú hodnotu (vyhodnotenie hry), odstránime session hráča a ak hra ešte nebola označená na vymazanie, označíme ju. Hru na vymazanie označí hráč, ktorému sa ako prvému zobrazí vyhodnotenie.

Nakoniec ešte pridáme odkaz na úvodnú stránku hry. Jedine v prípade vyhodnotenia hry nebudeme stránku znovunačítavať cez metaelement – len zobrazíme výsledok a odkaz na úvodnú stránku. V ostatných prípadoch je potrebné stránku v pravidelných intervaloch načítávať. Ak sa hráči ešte hrajú, vytvoríme potrebný metaelement funkciou MetaRefresh, ktorej parametrom je názov skriptu (index.php) s potrebnými premennými:

  • pid=$row->pid – ID hry
  • SID – PHP konštanta v tvare PHPSESSID=session ID (vkladáme len ak sú vypnuté cookies, lebo len vtedy SID existuje)

function MetaRefresh ($c) {
    return „<meta http-equiv=\“Refresh\“ content=\““.REFRESH.“; URL=“.URL.“$c\“ />“;
    }

Kto obľubuje filtre v MSIE, môže si stránku obohatiť o ďalší metaelement, ktorý výtvára pri načítaní alebo opustení stránky nejaký efekt. Rýchlo si ho môžete vygenerovať a prezrieť na stránke asianouting.com, aby prechody pri refreshovaní stránky tak „nepreblikávali“.

Pri zobrazovaní úvodnej stránky hry nie sú potrebné žiadne premenné pre refresh stránky, teda funkciu voláme len s názvom skriptu. Samotný kód hlavnej časti PHP skriptu:

// spracovanie vstupov – vrati True, ak sa ma zobrazovat sekcia hry, inak False
$show = Action ($row, $s, $master, $slave);
// sekcia hry
if ($show){
    // zobrazi hracie pole – vrati 0 ak niet vitaza, nieco kladne ak je vitaz alebo remiza
    $win = Area ($s, $row, $master, $slave);
    if($win){
        // odstran session (najskor jedneho hraca, potom druheho..)
        session_destroy ();
        // oznac hru „pid“ na vymazanie
        if($row->last!=“d“)
            mysql_query („UPDATE piskvorky SET last=’d‘ WHERE pid=’$row->pid'“);
        $s .= „<a href=’index.php’>Hraj znova !</a><br/>“;
        } // if $win
    else
        // $row je naplnene z funkcie Action
        $meta = MetaRefresh („index.php?pid=$row->pid“.(SID ? „&amp;“.SID : SID));
    } // $show
// sekcia uvodnej stranky
else
    $meta = MetaRefresh („index.php“);

HTML obsah

PHP skript ďalej pokračuje definíciami spomínaných funkcií, ale o nich si povieme až v druhom článku. Pozrime sa ešte na samotný obsah HTML stránky:

<?xml version=“1.0″ encoding=“windows-1250″?>
<!DOCTYPE html PUBLIC „-//W3C//DTD XHTML 1.0 Transitional//EN“ „http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>
<html xmlns=“http://www.w3.org/1999/xhtml“ xml:lang=“sk“ lang=“sk“>
<head>
    <title>Online piškvorky v PHP s MySQL – ukážka skriptu zo serveru www.interval.cz</title>
    <meta http-equiv=“Content-Type“ content=“text/html; charset=windows-1250″ />
    <?php echo $meta?>
    <style media=“all“ type=“text/css“>@import url(‚piskvorky.css‘);</style>
    <script type=“text/javascript“>
        // JavaScript image preload
        var p = new Array („blank.gif“,“o.gif“, „o2.gif“, „o3.gif“, „x.gif“, „x2.gif“, „x3.gif“)
        var o = new Array (p.length)
        for (var i=0 ; i<p.length ; i++){
            o[i] = new Image ()
            o[i].src = p[i]
            }
    </script>
</head>
<body bgcolor=“#a0b0b0″>
<?php echo $s?>
</body>
</html>

V hlavičke pridávame metaelement pre refresh stránky a JavaScript na preload obrázkov. Do body vložíme obsah $s, ktorý obsahuje buď úvodnú stránku, alebo sekciu hry.

Prvú časť online piškvoriek si ukončíme ukážkou (AREA=5, WINNER=4), nezabudnite si však prečítať aj druhé pokračovanie, v ktorom si popíšeme funkcie využité v hlavnej časti PHP skriptu a kde bude tiež odkaz na zdrojový kód.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek Strategie přežití webu
Další článek skc
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *