Vier gewinnt, erkennen ob einer gewonnen hat

Hmm ich hatte mal folgende Idee dazu

Betrachte die Zeilen, Spalten und Diagonalen jeweils als Strings
Zeile1, Zeile2, ..Zeile6, Spalte1, ... Spalte7
DiagonaleLURO1 (von liks unten nach rechts oben) bis DiagonameLURO6 sowie DiagonaleLORU1 bis DiagonaleLORU6

Beim Setzen eines Steins füge ich in die entsprechenden Strings an der richtigen Stelle entweder ein A oder ein B ein.
Das Setzen der Steine ist etwas aufwändig.

Dann braucht man aber nur prüfen, ob in einer der oben genannten 25 Strings die Zeichenkette "AAAA" oder "BBBB" vorkommt. - Fertig
Das sind nur 25 String-Prüfungen und sollte daher recht schnell sein.

Noch mal zu den Strings:
Die Zeilen- und Spalten-String sind wohl klar:
Zeile1: enthält a1,b1,c1,d1,...g1
ZeileN analog an, bn,cn,dn....gn
Spalte1 enthält: a1,a2,a3,a4,a5,a6
Spalte7 enthält: g1,g2...g6

Die Diagonalen
DiagonaleLURO1 enthält a3,b4,c5,d6
DiagonaleLURO2 enthält a2,b3,c4,d5,e6
DiagonaleLURO3 enthält a1,b2,c3,d4,e5,f6
DiagonaleLURO4 enthält b1,c2,d3,e4,f5,g6
DiagonaleLURO5 enthält c1,de,e3,f4,g5
DiagonaleLURO6 enthält d1,e2,f3,g4

DiagonaleLORU1 enthält d6,e5,f4,g3
DiagonaleLORU2 enthält c6,d5,e4,f3,g2
DiagonaleLORU3 enthält b6,c5,d4,e3,f2,g1
DiagonaleLORU4 enthält a6,b5,c4,d3,e2,f1
DiagonaleLORU5 enthält a5,b4,c3,d2,e1
DiagonaleLORU6 enthält a4,b3,c2,d1

a b c d e f g
6 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
 
Irgendwie hat mich die AUfgaben gereitzt. also hab ich mich mal hingesetzt und etwas ausgedacht. Anschliessend hier mal gelesen was schon da ist. Meine Idee entspricht etwa der von vop

PS: Ich hab zum testen ein 3-Gewinnt gemacht, da es einfacher ist die Testfälle zu erstellen...
PHP:
<?php 
    // 3-Gewinnt mit 2 Spieler
    $rows[] = "__XXoX";
    $rows[] = "__XoX_";
    $rows[] = "__oXo_";
    $rows[] = "__ooX_";
    
    echo Tester::test($rows, 3)."<br />";
    
    // 3-Gewinnt mit 3 Spieler
    $rows = array();
    $rows[] = "__X/o/";
    $rows[] = "__/X/o";
    $rows[] = "__XXo/";
    echo Tester::test($rows, 3, array("X","O","/"))."<br />";
    
class Tester{    
    private $len;
    private $search = array();
    private $rows = array();
    
    /**
     * führt den Test statisch aus
     * @param $rows
     * @param int $len  länge des Prüfstrings (bei 4 Gewinnt -> bei 3 Gewinnt 3 etc)
     * @return String oder false
     */
    public static function test($rows, $len = 4, $userChars = array("X", "O")){
        $tester = new Tester($len, $userChars);
        return $tester->testNow($rows);
    }
    
    /**
     * Konstrukteur
     * @param int $len  länge des Prüfstrings (bei 4 Gewinnt -> bei 3 Gewinnt 3 etc)
     */
    public function __construct($len = 4, $userChars = array("X", "O")){
        $this->len = $len;
        $this->setUserChars($userChars); 
    }
    
    /**
     * set the charakter for the users
     * @param $userChars
     */
    public function setUserChars($userChars = array("X", "O")){
        //Array mit Search-Pattern erstellen. So muss dieser nur einmal 
        //erstellt werden und nicht bei jeder suche
        //->Array("X"=>"XXX", "O"=>"OOO")
        $this->search = array_combine($userChars, array_map("str_repeat", $userChars, array_fill(0, count($userChars), $this->len)));
    }
    
    /**
     * führt den Test aus
     * @param $rows
     * @return String oder false
     */
    public function testNow($rows){
        $this->rows = $rows;
        //testen ob eine Zeile ein treffer ergibt
        if ($winner = $this->testLines($this->getRows())) return $winner;
        //prüfen ob eine Spalte ein treffer ergibt
        if ($winner = $this->testLines($this->getCols())) return $winner;
        //prüfen ob eine Diagonale (obenlinks nach untenrechts) ein Treffer ergibt
        if ($winner = $this->testLines($this->getDia())) return $winner;
        //prüfen ob eine Diagonale (obenrechts nach untenlinks) ein Treffer ergibt
        //zuerst die Zeilen umderhen und dann die gleiche Prüfung durchlaufen
        if ($winner = $this->testLines($this->getDia(array_map("strrev", $this->rows)))) return $winner;
        //kein Treffer
        return false;
    }    

    /**
     * gibt die Zeilen zurück
     * @return Array<String>
     */
    private function getRows(){
        return $this->rows;
    }

    /**
     * erstellt ein array mit den Spalten
     * @return Array<String>
     */
    private function getCols(){
        for ($colId=0; $colId<strlen($this->rows[0]); $colId++){
            foreach ($this->rows as $row){
                $columns[$colId] .= $row[$colId];
            }
        }
        return $columns;
    }    
    /**
     * erstellt ein Array mit den Diagonalen (obenlinks nach untenrechts)
     * @return Array<String>
     */
    private function getDia($rows = false){
        if (!$rows) $rows = $this->rows;
        //Anzahl startenden Diagonale per Zeile
        $countDiaStartPerRow = strlen($rows[0]) - $this->len + 1;
        //Anzahl startenden Diagonale per Spalte
        $countDiaStartPerCol = (count($rows)-$this->len+1);
        
        $diaId=0;   
        
        for ($r=0; $r<$countDiaStartPerCol; $r++){
            for ($colId=0; $colId<$countDiaStartPerRow; $colId++){
                for ($rowId=0; $rowId<count($rows); $rowId++){
                    $dias[$diaId] .= $rows[$r + $rowId][$colId + $rowId];
                }
                $diaId++;
            }
        }        
        return $dias;
    }    
        
    /**
     * prüft Array<String> aus treffer
     * @param Array<String> $rows
     * @return String oder false
     */
    private function testLines($lines){           
        foreach ($this->search as $char=>$search){
            foreach ($lines as $line){
                if (stristr($line, $search)) return $char;
            }
        }
        return false;
    }
}    
        
?>

Nachtrag:
Ich habe $chars hinzugefügt. So kann man auch mit mehr als 2 Leuten spielen....

Nachtrag2:
Hab das ganze noch ein wenig verbessert (Performance, array-Funktionen etc)
 
Zuletzt bearbeitet:
mein php code der zu funktionieren scheint:

PHP:
function checkWin($comPro) {
    $counter = 1;
    $field = array(0, 0, 0, 0, 0, 0);
    for($i=0 ; $i < 6 ; $i++)
        $field[$i] = array(0, 0, 0, 0, 0, 0, 0);
    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--;
    }
    for($i=0 ; $i < 6 ; $i++) {
        for($ii=0 ; $ii < 7 ; $ii++) {
            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+4 && $i < 7) ; $i++) {
        if($field[$lastRow][$i] == $field[$lastRow][$lastCol])
            $countHori++;
        else
            $i += 7;
    }
    for($i=$lastCol-1 ; ($i > $lastCol-4 && $i >= 0) ; $i--) {
        if($field[$lastRow][$i] == $field[$lastRow][$lastCol])
            $countHori++;
        else
            $i -= 7;
    }
    for($i=$lastRow+1 ; ($i < $lastRow+4 && $i < 6) ; $i++) {
        if($field[$i][$lastCol] == $field[$lastRow][$lastCol])
            $countVertical++;
        else
            $i += 7;
    }
    for($i=$lastRow-1 ; ($i > $lastRow-4 && $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($lastRow+$i<6 && $lastRow+$i>=0 && $lastCol+$i<7 && $lastCol+$i>=0) {
            if($field[$lastRow+$i][$lastCol+$i] == $field[$lastRow][$lastCol])
                $countLeBoToRi++;
            else
                $i += 7;
        }
    }
    for($i=-1 ; $i > -4 ; $i--) {
        if($lastRow+$i<6 && $lastRow+$i>=0 && $lastCol+$i<7 && $lastCol+$i>=0) {
            if($field[$lastRow+$i][$lastCol+$i] == $field[$lastRow][$lastCol])
                $countLeBoToRi++;
            else
                $i -= 7;
        }
    }
    for($i=1 ; $i < 4 ; $i++) {
        if($lastRow+$i<6 && $lastRow+$i>=0 && $lastCol+$i<7 && $lastCol+$i>=0) {
            if($field[$lastRow+$i][$lastCol+$i] == $field[$lastRow][$lastCol])
                $countRiBoToLe++;
            else
                $i += 7;
        }
    }
    for($i=-1 ; $i > -4 ; $i--) {
        if($lastRow+$i<6 && $lastRow+$i>=0 && $lastCol+$i<7 && $lastCol+$i>=0) {
            if($field[$lastRow+$i][$lastCol+$i] == $field[$lastRow][$lastCol])
                $countRiBoToLe++;
            else
                $i -= 7;
        }
    }

    $resultWin = 0;
    if($countVertical>2 || $countHori>2 || $countLeBoToRi>2 || $countRiBoToLe>2)
        $resultWin = $field[$lastRow][$lastCol];
    return $resultWin;
}

diese Funktion gibt mir nun 0 für noch kein win, 1 für spieler 1 hat gewonnen und 2 für spieler 2 hat gewonnen, wider.
Danke für eure Hilfe.
PS: ich liebe Funktions-orientiertes PHP :)
 
Zurück