Vier gewinnt, erkennen ob einer gewonnen hat

Paspirgilis

Weißer Powerranger
Hi
Mein title sagt wohl alles.
Ich hab ein HTML/CSS/Javascript/aJaX/PHP Vier Gewinnt programmiert.
Es Funktioniert vollständig und habe schon ein paar Testspiele gemacht.
Allerdings muss der Menshc sleber erkennen wann einer Verloren/Gewonnen hat und einfach neuladen. ich versuche einen Rhytmus oder etwas zufinden wie ich das überprüfen kann, da ich dieses Rad nicht neu erfinden möchte. Ich würde es sonst über etliche Schleifen "ertesten".
http://P-MyPage.de
allerdings muss man einen Email-Aktivierten Account haben, sich das Spiel geholt haben und dann kann man es Spielen. Für die tutorials-gemeinde mach ich schnell ne nachricht auf der landingpage.

MFG
Mark Paspirgilis
 
Naja, es gibt ja nur eine Siegbedingung bei 4-Gewinnt, nämlich 4 Steine in einer Reihe bzw. Diagonale.
Darauf musst du prüfen. Du kannst natürlich bereits vorher immer speichern, wo Steine in einer Reihe liegen (also sobald 2+ da sind) und diese ergänzen... Sind es 4, ununterbrochen, hat der Spieler gewonnen...

Übrigens, 4-Gewinnt ist langweilig, da es gelöst wurde ;)
 
Ja schon, aber ich brauchte für meine Page ein minispiel. da es diese funktion gibt und da musste ich irgendwas aus dem hut zaubern xD.
Also hatte ich innerhalb von 1-2 Tagen viergewinnt programmiert. Is auch ziemlich gut geworden.
Genau diesen algorhytmus suche ich den ich durchlaufen lasse. Ich Speichere den gesamten ablauf.

Ich geb ma n Beispiel:
Der Ablauf wird so gespeichert:
Code:
5_3,5_4,4_4,4_3,5_2,3_4,4_2,3_2,5_1,5_0,5_5,3_3,2_2,4_1,2_3,3_1,4_0,
Der Zweite Spieler hat übridens gewonnen.
Erläuterung zu dem Syntax des Spiel ablaufs:
Spieler eins setzt in die 4. spalte und der Stein fällt natürlich in die 6. Reihe, deswegen 5_3. Zähler beginnt bei 0.spieler Zwei: 5. Spalte auch ganz unten also reihe 6. usw.

Wie Überprüfe ich jetzt möglichst performant ob einer gewonnen hat?
 
Mir fällt für die Performance spontan ein, dass das über ein Binärsystem auch lösbar seien könnte.
Wenn man zum Beispiel für einen Spieler 4 aufeinander folgende Zeilen mit einfachem & Verknüpft und nicht 0 herauskommt hat dieser Spieler gewonnen (4 untereinander).
Oder Wählt man eine Zeile und ist diese mit gerader Anzahl durch 15 teilbar (2^4 - 1), bzw. durch 30 oder gleich 15, so gibt es sicherlich 4 nebeneinander.

Für das diagonale darfst dir selbst was ausdenken ;)
 
Zuletzt bearbeitet:
Ich weiß zwar nicht, wie schnell das ist (PHP ist meiner Erfahrung nach mehr als extrem langsam), aber du könntest es so machen, wie ich bei einen TBS die beziehbaren Felder getestet habe.

Zuerst lokalisierst du den letzten gelegten Stein. (Anderstwo zu gewinnen ist ja nicht möglich). Danach rufst du eine Methode auf, der die Position des Steins übergeben wird. Diese Addiert zu einer Variable (i) 1, und ruft sich selbst mit den Koordinaten der 8 Nachbarstein"slots" auf. Dabei wird jeweils eine von 8 +1 (j) Variablewerten mitübergeben. Die Methode testet dann ob es sich um einen Stein des selben Spielers handelt, addiert i um 1 und ruft je nach dem Wert von j den nächsten in der Reihe auf. Dieser testet wieder ob es der Stein des selben Spielers ist usw. Sobald i 4 ist, gibt es eine komplette Reihe. Der 9. Wert von j gibt an, dass es sich um den Aufruf des ersten Steins, also dem der zuletzt gelegt wurde handelt, und er in alle Richtungen testen soll.
 
Hab mir bissl gedanken drüber gemacht. Es soll in PHP sein und das mit dem 8 Felder drumherum überprüfen scheint mir ganz simpel zu sein.
Ich beginne damit das Feld zu "Stempeln" und danach zu gcuken ob 4 einsen oder zweien neben einander sind. erstma horizontal und vertikal dann schräg.
Bis jetzt hab ich grad das Stempeln fertig gemacht:
PHP:
function checkWin($comPro) {
    $counter = 1;
    for($i=0 ; $i < strlen($comPro) ; $i+=4){
        $cProPart = substr($comPro, $i, 3);
        $cProPartRow = substr($cProPart, 0, 1);
        $cProPartCol = substr($cProPart, 2, 1);
        $field[$cProPartRow][$cProPartCol] = $counter;
        $counter==1?$counter++:$counter--;
    }
    $field = array();
    for($i=0 ; $i < 6 ; $i++) {
        for($ii=0 ; $ii < 7 ; $ii++){
            $field[$i] = array();
            if(!$field[$i][$ii]==1 || !$field[$i][$ii]==2){
                $field[$i][$ii] = 0;
            }
        }
    }
    return false;
}
ignoriert das return fals, dass ist dazu da das der restliche code noch funktioniert.
 
jetzt mit Überprüfung auf horizontal und vertical:
PHP:
function checkWin($comPro) {
    $counter = 1;
    for($i=0 ; $i < strlen($comPro) ; $i+=4){
        $cProPart = substr($comPro, $i, 3);
        $cProPartRow = substr($cProPart, 0, 1);
        $cProPartCol = substr($cProPart, 2, 1);
        $field[$cProPartRow][$cProPartCol] = $counter;
        $counter==1?$counter++:$counter--;
    }
    $field = array();
    for($i=0 ; $i < 6 ; $i++) {
        for($ii=0 ; $ii < 7 ; $ii++){
            $field[$i] = array();
            if(!$field[$i][$ii]==1 || !$field[$i][$ii]==2){
                $field[$i][$ii] = 0;
            }
        }
    }
    $lastRow = substr($comPro, -4, 1);
    $lastCol = substr($comPro, -2, 1);
    $countHori = 0;
    $countVertical = 0;
    for($i=$lastCol+1 ; ($i < $lastCol+3 && $i < 7) ; $i++){
        if($field[$lastRow][$i] == $field[$lastRow][$lastCol])
            $countHori++;
        else
            $i += 7;
    }
    for($i=$lastCol-1 ; ($i > $lastCol-3 && $i >= 0) ; $i--){
        if($field[$lastRow][$i] == $field[$lastRow][$lastCol])
            $countHori++;
        else
            $i -= 7;
    }
    for($i=$lastRow+1 ; ($i < $lastRow+3 && $i < 6) ; $i++){
        if($field[$i][$lastCol] == $field[$lastRow][$lastCol])
            $countVertical++;
        else
            $i += 7;
    }
    for($i=$lastRow-1 ; ($i > $lastRow-3 && $i >= 0) ; $i--){
        if($field[$i][$lastCol] == $field[$lastRow][$lastCol])
            $countVertical++;
        else
            $i -= 7;
    }
    $resultWin = false;
    if($countVertical>3 || $countHori>3)
        $resultWin = true;
    return $resultWin;
}
 
Ich habe mal schnell was geschrieben. Ist eigendlich nur Psydocode, meine PHP-Zeit liegt 2 Jahre zurück und ich kann OOP nur aus der Theorie.
Kann nicht versprechen dass es so funktioniert.

PHP:
$northWest = 1;
$north = 2;
$northEast = 3;
$middleWest = 4;
$middleEast = 5;
$southWest = 6;
$south = 7;
$southEast = 8;

function checkWin($x, $y, $player)
{
	checkWin($x, $y, $player, 1, 0);
}
function checkWin($x, $y, $player, $rowCounter, $testDirectory)
{
	$stone = $stones[$x][$y];
	if((isset($stone)) && ($stone.getPlayer() == $player))
	{
		if($rowCounter == 4)
		{
			//TODO Gewonnen. =)
		}
		else if($testDirectory == 0)
		{
			checkWin($x - 1, $y - 1, $rowCounter + 1, $northWest);
			checkWin($x, $y - 1, $rowCounter + 1, $north);
			checkWin($x + 1, $y - 1, $rowCounter + 1, $northEast);

			checkWin($x - 1, $y, $rowCounter + 1, $middleWest);
			checkWin($x + 1, $y, $rowCounter + 1, $middleEast);

			checkWin($x - 1, $y + 1, $rowCounter + 1, $southWest);
			checkWin($x, $y - 1 + 1, $rowCounter + 1, $south);
			checkWin($x + 1, $y + 1, $rowCounter + 1, $southEast);
		}
		else
		{
			if($testDirectory == $northWest)
			{
				$x--;
				$y--;
			}
			else if($testDirectory == $north)
				$y--;
			else if($testDirectory == $northEast)
			{
				$x++;
				$y--;
			}
			else if($testDirectory == $middleWest)
				$x--;
			else if($testDirectory == $middleEast)
				$x++;
			else if($testDirectory == $southWest)
			{
				$x--;
				$y++;
			}
			else if($testDirectory == $south)
				$y--;
			else if($testDirectory == $southEast)
			{
				$x++;
				$y++;
			}
			checkWin($x, $y, $rowCounter + 1, $southEast);
		}
	}
}

Musst auf jeden Fall noch den booleanischen return-Wert zum ersten call "routen".
 
OK.
Final Version:
PHP:
function checkWin($comPro) {
    $counter = 1;
    for($i=0 ; $i < strlen($comPro) ; $i+=4){
        $cProPart = substr($comPro, $i, 3);
        $cProPartRow = substr($cProPart, 0, 1);
        $cProPartCol = substr($cProPart, 2, 1);
        $field[$cProPartRow][$cProPartCol] = $counter;
        $counter==1?$counter++:$counter--;
    }
    $field = array();
    for($i=0 ; $i < 6 ; $i++) {
        for($ii=0 ; $ii < 7 ; $ii++){
            $field[$i] = array();
            if(!$field[$i][$ii]==1 || !$field[$i][$ii]==2){
                $field[$i][$ii] = 0;
            }
        }
    }
    $lastRow = substr($comPro, -4, 1);
    $lastCol = substr($comPro, -2, 1);
    $countHori = 0;
    $countVertical = 0;
    $countLeBoToRi = 0;
    $countRiBoToLe = 0;
    for($i=$lastCol+1 ; ($i < $lastCol+3 && $i < 7) ; $i++){
        if($field[$lastRow][$i] == $field[$lastRow][$lastCol])
            $countHori++;
        else
            $i += 7;
    }
    for($i=$lastCol-1 ; ($i > $lastCol-3 && $i >= 0) ; $i--){
        if($field[$lastRow][$i] == $field[$lastRow][$lastCol])
            $countHori++;
        else
            $i -= 7;
    }
    for($i=$lastRow+1 ; ($i < $lastRow+3 && $i < 6) ; $i++){
        if($field[$i][$lastCol] == $field[$lastRow][$lastCol])
            $countVertical++;
        else
            $i += 7;
    }
    for($i=$lastRow-1 ; ($i > $lastRow-3 && $i >= 0) ; $i--){
        if($field[$i][$lastCol] == $field[$lastRow][$lastCol])
            $countVertical++;
        else
            $i -= 7;
    }
    //Diagonal
    $horiPosi = $lastCol;
    $vertPosi = $lastRow;
    for($i=1 ; $i < 4 ; $i++){
        if($vertPosi+$i<6 && $vertPosi+$i>=0 && $horiPosi+$i<7 && $horiPosi+$i>=0){
            if($field[$vertPosi+$i][$lastCol+$i] == $field[$lastRow][$lastCol])
                $countLeBoToRi++;
            else
                $i += 7;
        }
    }
    for($i=-1 ; $i > -4 ; $i--){
        if($vertPosi+$i<6 && $vertPosi+$i>=0 && $horiPosi+$i<7 && $horiPosi+$i>=0){
            if($field[$vertPosi+$i][$lastCol+$i] == $field[$lastRow][$lastCol])
                $countLeBoToRi++;
            else
                $i -= 7;
        }
    }
    for($i=1 ; $i < 4 ; $i++){
        if($vertPosi+$i<6 && $vertPosi+$i>=0 && $horiPosi-$i<7 && $horiPosi-$i>=0){
            if($field[$vertPosi+$i][$lastCol-$i] == $field[$lastRow][$lastCol])
                $countRiBoToLe++;
            else
                $i += 7;
        }
    }
    for($i=1 ; $i > -4 ; $i--){
        if($vertPosi+$i<6 && $vertPosi+$i>=0 && $horiPosi-$i<7 && $horiPosi-$i>=0){
            if($field[$vertPosi+$i][$lastCol-$i] == $field[$lastRow][$lastCol])
                $countRiBoToLe++;
            else
                $i -= 7;
        }
    }
    
    $resultWin = false;
    if($countVertical>3 || $countHori>3 || $countLeBoToRi>3 || $countRiBoToLe>3)
        $resultWin = true;
    return $resultWin;
}

Wäre Jemand so nett und überblickt das mal einer. Ich Glaube es ist Fehlerfrei.
 
Zurück