lehrkraefte:blc:informatik:ffprg1-2024:raster-tictactoe

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
lehrkraefte:blc:informatik:ffprg1-2024:raster-tictactoe [2024/04/09 15:11]
Ivo Blöchliger created
lehrkraefte:blc:informatik:ffprg1-2024:raster-tictactoe [2024/05/17 13:10] (current)
Ivo Blöchliger [Gewinn überprüfen]
Line 1: Line 1:
 ====== Tic Tac Toe ====== ====== Tic Tac Toe ======
 +<WRAP todo>
 +  * Legen Sie einen neuen Ordner 'tictactoe' and und speichern Sie darin die Dateien [[.:raster-basics|der Basis]] für ein Raster Spiel.
 +  * Speichern Sie im gleichen Ordner auch folgende beiden Bilder (gemacht mit dem sehr zu empfehlenden OpenSource-Programm [[https://inkscape.org/|Inkscape]]:
 +    * {{lehrkraefte:blc:informatik:ffprg1-2024:cross.svg?linkonly}} und {{lehrkraefte:blc:informatik:ffprg1-2024:dot.svg?linkonly}}
 +  * Fügen Sie in der Datei ''raster.css'' folgenden CSS-Code hinzu:
 +<code css>
 +.wert1 {
 +    background-image: url("cross.svg");
 +    background-size: cover;
 +}
 +.wert2 {
 +    background-image: url("dot.svg");
 +    background-size: cover;
 +}
 +</code>
 +  * In der Datei ''mygame.js'' 
 +    * entfernen Sie den Aufruf von ''Raster.addColorRules'',
 +    * passen Sie die Grösse auf 3 mal 3 an,
 +    * fügen Sie eine Variable ''currentPlayer'' hinzu, die angibt, welcher Spieler (1 oder 2) gerade am Zug ist.
 +    * Beginnen Sie das Spiel im ''clickCallback'' zu programmieren (mit den Variablen ''meinRaster'' und ''currentPlayer''). Dabei soll einfach abwechselnd auf leeren Feldern gezogen werden können.
 +    * Fügen Sie eine weitere Variable ''cellsPlayed'' hinzu, die zählt, wie viele Zellen schon belegt sind.
 +    * Programmieren Sie eine Unterfunktion ''reset'', die das Spiel und alle nötigen Variablen zurücksetzt.
 +    * Wenn geklickt wird und alle Zellen schon voll sind, soll das Spiel neu starten.
  
 +<hidden Lösungsvorschlag>
 +<code javascript>
 +window.addEventListener('load', function() {
 +
 +    let meinRaster = new Raster(3,3);
 +    let currentPlayer = 1;
 +    let cellsPlayed = 0;
 +
 +    function reset() {
 +        currentPlayer = 1;
 +        cellsPlayed = 0;
 +        for (let x=0; x<3; x++) {
 +            for (let y=0; y<3; y++) {
 +                meinRaster.setValue(x,y,0);
 +            }
 +        }
 +    }
 +
 +    // Callback für einen Klick definieren
 +    meinRaster.clickCallback = function(x, y) {
 +        if (cellsPlayed==9) {
 +            reset();
 +            return;
 +        }
 +        let v = meinRaster.getValue(x,y);
 +        if (v!=0) {
 +            return;
 +        }
 +        meinRaster.setValue(x,y,currentPlayer);
 +        currentPlayer = 3-currentPlayer;
 +        cellsPlayed++;
 +    }
 +});
 +</code>
 +</hidden>
 +</WRAP>
 +
 +
 +===== Gewinn überprüfen =====
 +<WRAP todo>
 +In der Datei ''mygame.js'', fügen Sie eine weitere Unterfunktion ''winner'' hinzu, die folgende Werte zurückgibt:
 +  * 0, wenn niemand 3 in einer Reihe hat
 +  * 1 oder 2, wenn Spieler 1 oder Spieler 2 gewonnen hat.
 +
 +Hinweise:
 +  * Schreiben Sie zusätzlich eine Funktion ''sindsDrei(x,y,vx,vy)'', die ''true'' ergibt, wenn drei gleiche Werte >=1 vom Startpunkt x,y, in Richtung des Vektors (vx,vy) anzutreffen sind. Sonst ''false''.
 +  * Rufen Sie die Funktion ''sindsDrei'' in der Funktion ''winner'' unter anderem in einer for-schlaufe auf.
 +
 +<hidden Teillösungsvorschlag>
 +<code javascript>
 +    function sindsDrei(x,y,vx,vy) {
 +        let w = meinRaster.getValue(x,y);
 +        if (w==0) return false;
 +        for (let i=0; i<3; i++) {
 +            if (meinRaster.getValue(x,y)!=w) return false;
 +            x+=vx;
 +            y+=vy;
 +        }
 +        return true;
 +    }
 +
 +    function winner() {
 +        for (let i=0; i<3; i++) {
 +            if (sindsDrei(i,0,0,1)) return meinRaster.getValue(i,0);  // Vertikal
 +            if (sindsDrei(0,i,1,0)) return meinRaster.getValue(0,i);  // Horizontal
 +        }
 +        if (sindsDrei(0,0,1,1)) return meinRaster.getValue(0,0);  // Diagonale in Richtung (1,1)
 +        if (sindsDrei(2,0,-1,1)) return meinRaster.getValue(2,0);  // Diagonale in Richtung (-1,1)
 +        return 0;
 +    }
 +
 +</code>
 +</hidden>
 +</WRAP>
 +
 +
 +<hidden Lösungsvorschlag aus der Stunde>
 +<code mygame.js>
 +// Erst mal alles Laden, erst dann an der Webseite
 +// Dinge ändern (die sonst noch gar nicht existieren würden)
 +window.addEventListener('load', function() {
 +
 +
 +    // Raster anlegen
 +    // Diese Variable ist ab hier auch in Unterfunktionen
 +    // definiert und verwendbar
 +    let meinRaster = new Raster(13,13);
 +    let currentPlayer = 1;
 +
 +    function reset() {
 +        meinRaster.fill(0);
 +        currentPlayer = 1;
 +    }
 +    function zaehlen(x,y,vx,vy, markieren=false) {
 +        let count = function(x,y,vx,vy) {
 +            let anzahl = 1;
 +            let wert = meinRaster.getValue(x,y);
 +            let [a,b] = [x+vx,y+vy];
 +            while (meinRaster.isOn(a,b) && meinRaster.getValue(a,b)==wert) {
 +                if (markieren) {
 +                    meinRaster.setValue(a,b,wert+2);
 +                }
 +                anzahl++;
 +                [a,b] = [a+vx, b+vy];
 +            }
 +            return anzahl;
 +        }
 +        let anzahl = count(x,y,vx,vy, markieren)+count(x,y,-vx,-vy, markieren)-1;
 +        if (markieren) {
 +            meinRaster.setValue(x,y,meinRaster.getValue(x,y)+2);
 +        }
 +
 +        return anzahl;
 +    }
 +    
 +    function hasWon(x,y) {
 +        for (let v of [[1,0],[1,1],[0,1],[-1,1]]) {
 +            if (zaehlen(x,y,v[0],v[1])>=5) {
 +                zaehlen(x,y,v[0],v[1],true);
 +                return true;
 +            }
 +        }
 +    }
 +    // Callback für einen Klick definieren
 +    meinRaster.clickCallback = function(x, y) {
 +        let v = meinRaster.getValue(x,y);
 +        if (v==0) {
 +            meinRaster.setValue(x,y,currentPlayer);
 +            if (hasWon(x,y)) {
 +                console.log(`Player ${currentPlayer} hat gewonnen!`);
 +            }
 +            currentPlayer = 3-currentPlayer;
 +        }
 +    };
 +
 +    this.document.getElementById('resetknopf').addEventListener('click', reset);
 +
 +});
 +</code>
 +</hidden>
 +===== Zellen markieren =====
 +<WRAP todo>
 +Ziel ist es, die gewinnende Dreierreihe zu markieren.
 +  * Fügen Sie dazu in der Datei ''raster.css'' zwei weitere Klassen ''wert3'' und ''wert4'' hinzu, um das Aussehen der gewinnenden Zellen für Spieler 1 und 2 festzulegen.
 +  * In der Funktion ''sindsDrei'', fügen Sie unmittelbar vor dem ''return true'' noch eine Schlaufe hinzu, die den Wert der gewinndenden Zellen um 2 erhöht.
 +
 +<hidden Lösungsvorschlag>
 +<code css>
 +.wert3 {
 +    background-image: url("cross.svg");
 +    background-color: lightcoral;
 +    background-size: cover;
 +}
 +.wert4 {
 +    background-image: url("dot.svg");
 +    background-color: skyblue;
 +    background-size: cover;
 +}
 +</code>
 +<code javascript>
 +        for (let i=0; i<3; i++) {
 +            x-=vx;
 +            y-=vy;
 +            meinRaster.setValue(x,y,w+2);
 +        }
 +</code>
 +</hidden>
 +</WRAP>
  
  • lehrkraefte/blc/informatik/ffprg1-2024/raster-tictactoe.1712668279.txt.gz
  • Last modified: 2024/04/09 15:11
  • by Ivo Blöchliger