PHPer,

Het is vakantie, hier en daar dus terug scriptneigingen.
Vandaag zijn de microben weer overgeslagen op mij en heb een project bedacht. Een Texas Hold'em script. Dit is eveneens een goede reden om te beginnen met OOP. Ik heb enkele tutorials gelezen, onderandere ook van deze site. Daarin staat duidelijk vermeld dat OOP een denkwijze is. Het verband tussen Classes zoals : maand extends dag, mastadizzy extends gebruiker, et cetera.
Nu zie ik deze logische verbanden niet echt terug in classes om kaarten te schudden en de kaarten te delen.

Even over de vraag waarmee ik zit. Hoe kan ik mijn geschudde kaarten ($kaarten) gebruiken in mijn volgend class? Zoals je wel kan zien schud ik de kaarten in mijn eerste class, en wil ik om te testen die geschudde kaartenarray oproepen in mijn volgende functie van een andere class (delen).

edit: Even vergeten bij te vermelden. Ik krijg netjes de array te zien die geprint wordt (dus de output van de eerste print_r van de functie schudden). daarna krijg ik 2 errors.

Notice: Use of undefined constant kaarten - assumed 'kaarten' in D:\wamp\www\class.inc.php on line 20

Notice: Object of class delen could not be converted to int in D:\wamp\www\class.inc.php on line 20
1


class.inc.php

<?PHP

class shuffle_kaarten
{
	var $kaarten = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52);

	function schudden()
	{
		shuffle($this->kaarten); //schud array met kaarten
		print_r($this->kaarten); //print array geschudde kaarten
	}
}

class delen
{
	var $aantal_spelers;
	
	function showkaarten()
	{
		print_r($this-kaarten); //om te testen array met geschudde kaarten weergeven	
	}
	
	function delen_speler1()
	{
		for($i=1;$i<=9;$i++)
		{
			echo $kaarten;
		}
	}
	function delen_computer()
	{
		
	}
}
?>



Het PHP bestand dat de classes oproept:

<?PHP
include 'class.inc.php';

$shuffle = new shuffle_kaarten;
$shuffle->schudden();

$kaartendelen = new delen;
$kaartendelen->showkaarten();


?>


Bij voorbaat dank!
Objecten zijn voorwerpen/mensen/dingen. Delen is een handeling en geen object dus geen class. shuffle_kaarten ook niet.

Verder hoor je geen echo/print etc in een class te doen maar netjes het resultaat terug te geven. (tenzij de class een view is, daar kan natuurlijk wel output)

pseudocode

<?php
    class TexasHoldEm
    {
        private $kaarten = array();
        private $spelers = array();
        private $aantalBijDelen = 9;
        
        public function __construct()
        {
            $this->refillKaarten();
        }
        
        public function schudden()
        {
            $this->kaarten = shuffle($this->kaarten);
        }
        
        public function delen()
        {
            $kaartenSpeler = array();
            for($i=0; $i< $this->aantalBijDelen; $i++)
            {
                $kaarten[] = array_shift($this->kaarten);
            }
        }
        
        public function addSpeler($speler)
        {
            $this->spelers[] = $speler;
        }
        
        public function refillKaarten()
        {
            $this->kaarten = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52);
        }
    }
?>


[edit]Vergeet bijna het gebruik.

<?php
    $casinoTafel = new TexasHoldEm();
    $casinoTafel->schudden();
    $kaartenSpelers = $casinoTafel->delen();
    $kaartenComputer = $casinoTafel->delen();
?>

[/edit]
Je kunt het opslaan van de kaarten ook netjes in de class doen.
Ok, hier kom ik al een heel eind mee verder!
Ik vond het persoonlijk raar om alles in 1 class te plaatsen.
Uiteindelijk, moet ik de validator ook in deze class schrijven? Of kan ik de denkpiste volgen: validator extends Texas hold'em ... omdat een validator een deel is van texas hold'em?

Bedankt alvast voor het bovenstaande!
"omdat een validator een deel is van texas hold'em"
Je zegt zelf al waarom "validator extends texas hold'em" niet kan. Validator is een ONDERDEEL van texas hold'em, het is niet "een texas hold'em"

Maar even terug op je originele post. Je moet bij poker denken aan objecten als:

Game
Player
Card
Deck
Dealer
Pot
Stack
Combination (bijv: Royal Flush of 3 of a kind)
Table

Je start een Game. Die deelt via je Dealer een aantal Cards aan een Player. De Cards haal je uit je Deck zodat er geen dubbele kaarten komen. Elke Player heeft een Stack (aantal fiches), bij inzetten gaat een deel van de Stack naar de Pot. Na inzetten komen er enkele Cards op de Table. Na nog een paar keer inzetten kijk je bij elke Player of zijn Cards met de Cards op de Table een Combination vormen. Als een Player een Combination heeft kun je een compare() uitvoeren tussen verschillende Players om te kijken wie de hoogste combinatie heeft. Vervolgens gaat de inhoud van de Pot naar een Player of wordt het gesplit. Een aantal van deze pokerregels zul je dus in Game (of in Dealer) programmeren, die gebruikt gewoon al die andere objecten.

Qua combinaties.Je maakt dus classes als "RoyalFlush extends Combination" om een combinatie te programmeren, met een functie als RoyalFlush::isHit($playerCards, $tableCards) die true returnt als de kaarten van een speler en de kaarten op tafel valideren tegen geldige pokercombinaties.

Heb ik je al op ideeën gebracht? Er zijn 1000 manieren om dit te doen, bovenstaand zou ook in minder classes kunnen (zo kun je een Stack ook zien als een eigenschap van een Player in plaats van een apart object, maar dat is een keuze).
Ik denk dat je hier echt stap voor stap moet gaan denken. Zeker als je het nog wil gaan leren. Begin eens makkelijk met een class Deck en een klas Cards.
Regel 5 kan je beter range gebruiken
Een paar grote wijzigingen gemaakt.

Allereerst heb ik schudden en delen in 1 class gestoken. Zoals TJVB meldde.

<?PHP
class TexasHoldEm
{
	private $deck = array(); //array maken voor 52 speelkaarten
	private $spelers = array();
	private $TeDelen = 9; //aantal te delen kaarten (2 voor speler, 2 voor computer, 5 voor de tafel)
	private $playerCards = array(); //array maken voor de kaarten van de speler
	private $computerCards = array(); //array maken voor de kaarten van de computer
	private $tableCards = array(); //array maken voor de kaarten die op tafel komen (flop, turn en river)
	
	public function __construct()
	{
		$this->BijVullen();
	}	
	public function BijVullen()
	{
		$this->deck = range(1,52); //plaats alle kaarten in het deck
	}
	public function schudden()
	{
		shuffle($this->deck); //schud het deck
	}
	
	public function delen()
	{
		for($i=0; $i < 2; $i++)
		{
			array_push($this->playerCards, array_shift($this->deck)); //geef eerst kaart aan speler
			array_push($this->computerCards, array_shift($this->deck)); //geef daarna kaart aan computer
		}
		for($i=0; $i <5; $i++)
		{
			array_push($this->tableCards, array_shift($this->deck)); //5 kaarten die later op tafel verschijnen
		}
	}
	
}
?>


Jacco schreef op 25.06.2009 11:14
Regel 5 kan je beter range gebruiken
Bedankt, dit zijn heel waarde volle tips :). Zeker omdat ik nog niet zo'n grote functie kennis heb.

Jurgen schreef op 25.06.2009 11:01
Ik denk dat je hier echt stap voor stap moet gaan denken. Zeker als je het nog wil gaan leren. Begin eens makkelijk met een class Deck en een klas Cards.
Idd, daarom wil ik er zeker van zijn dat mijn schudden en delen goed zit.
Wat bedoel je met class Deck en class Cards? Kan je even uitleggen wat je denkwijze is voor deze 2 klassen en wat ze doen?

Kaarten krijgen nu een waarde 1-52, maar hoe ga je later in het spel bepalen wat de eigenlijke waarde van die kaarten is? Met andere woorden, hoe ga je constateren dat iemand een flush of straight heeft of zelfs een paartje?

Zoals je ziet heeft een kaart meer eigenschappen dan enkel een nummer uit de reeks 1-52. Een kaart heeft een kleur en een waarde. Dat zou je heel mooi kunnen vastleggen in een object Card, een instantie van de klasse Card.

Vervolgens zou je kunnen kiezen om ook een Deck klasse te gebruiken. Een Deck object zou dan in eerste instantie 52 Card objecten bevatten. De method schudden() is dan een toepassing op een Deck en zou in die klasse thuis horen. Ook zou die klasse een method dealCard() kunnen hebben waarmee er 1 kaart uit het Deck gedeeld wordt. De delen() method uit je TexasHoldEm klasse roept dan een aantal keer die dealCard() method aan.

Een overzichtje:
<?php
class Card {
private $sSuit;
private $sValue;

public function __construct($sSuit, $sValue) {

}

// Aantal methods voor verkrijgen van de waarde en de kleur
}

class Deck {
private $aCards;

public function __construct() {
// Vul $this->aCards met 52 Card objecten
}

public function dealCard() {
return array_shift($this->aCards);
}
}

class TexasHoldEm {
// Hier de methods voor het spelen van het spel
}
?>

Mogelijk wil je dit ook nog uitbreiden met bijvoorbeeld een Player object waar je tijdens het spel kaarten aan toe kun wijzen. Er zijn heel veel mogelijkheden, maar dit geeft wel een beetje de basis.
Blanche schreef op 25.06.2009 12:41
Kaarten krijgen nu een waarde 1-52, maar hoe ga je later in het spel bepalen wat de eigenlijke waarde van die kaarten is? Met andere woorden, hoe ga je constateren dat iemand een flush of straight heeft of zelfs een paartje?

Mijn denkwijze was bijvoorbeeld:
klaveren [1-13] waarbij 1 ace, 11 jack, 12 queen en 13 king.
schoppen [14-26]
harten [27-39]
koeken [40-52]
dus, al je 1 en 14 vast hebt (2 aces dus) ... checken tussen welke waardes liggen. 14 ligt dus in de 2de categorie (schoppen) waardoor je 14-((2-1)*13) doet. (14=nummer-kaart; 2=2de categorie; 1=om de waarde te corrigeren. Zo wordt er geen verschil gemaakt van 26 wat resulteert in een negatief getal; 13=zoveel kaarten zijn er van 1 soort/zitten er in 1 range)
Wat dus waarde 1 terugstuurt. en als 2 waardes gelijk zijn aan elkaar. In dit geval heb je dus (1;1) vast wat dus een pair geeft :)
Inderdaad is dit niet de meest praktische methode, maar in andere poker-scripts(volgens een goede maat van mij) gebruikt men deze methode ook.

[edit] Hoe kan ik ervoor zorgen dat $aCards in de class Deck niet dezelfde kaarten afhaalt bij de Card-classe?
Want als ik het goed begrijp moet ik 52 keer de Card-classe oproepen in de constructor van class Deck?[/edit]
Het lijkt mij veel handiger om bijvoorbeeld een method isPair() te hebben die dat voor je doet.
<?php
public function isPair(Card $oCard1, Card $oCard2) {
if($oCard1->getValue() == $oCard2->getValue()) {
return true;
}
return false;
}
?>
En datzelfde zou je voor de andere combinaties van kaarten kunnen doen. Tenslotte zou je al deze controles met 1 method toe kunnen passen op de kaarten in de hand en de gemeenschappelijke kaarten...
Dit komt me bekent voor,
Ik ben er namelijk ook mee bezig :P

Dit is momenteel mijn opzet voor de deck class.
<?php

/**
* @author Nico Kaag
* @copyright 2009
*/
error_reporting(E_ALL);

class card
{
public $color;
public $value;
function __construct($color, $value)
{
$this->color = $color;
$this->value = $value;
}


}

class deck
{
//Player Variables
public $deck;
private $aSuits = array('H', 'D', 'S', 'C');
private $aValues = array('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A');

function __construct()
{
$this->deck = array();
foreach($this->aSuits as $sSuit)
{
foreach($this->aValues as $sValue)
{
array_push($this->deck, new card($sSuit, $sValue));
}
}
}
}

?>

en dit is mijn dealer class
<?php

/**
* @author Nico Kaag
* @copyright 2009
*/
error_reporting(E_ALL);

class dealer
{
public $deck;
public $playerCards;
private $shuffledDeck;
public function __construct()
{
$this->deck = new deck();
}

public function dealCards($nrOfPlayers, $nrOfCards)
{
$this->shuffleDeck();
for ($j = 0; $j < $nrOfCards; $j++)
{
for ($i = 0; $i < $nrOfPlayers; $i++)
{
$this->playerCards[$i][$j] = array_shift($this->shuffledDeck);
}
}
}

private function shuffleDeck()
{
$this->shuffledDeck = $this->deck->deck;
shuffle($this->shuffledDeck);
}
}

?>


zoals je wel ziet heb ik hier het schudden onder de dealer gezet.
Een deck schud zichzelf namelijk niet.
Dat word geschud door de dealer, dus dat is dan ook een functie die de dealer heeft.
Zo ook bij het delen.
De kaarten worden ook toegekend aan een object player/speler.
Dit gebeurt hier nog niet, omdat k nog niet zo ver ben :P

Reageren