lehrkraefte:blc:informatik:ffprg1-2020:klassen

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
lehrkraefte:blc:informatik:ffprg1-2020:klassen [2020/03/02 08:01]
Ivo Blöchliger [Beispiel: Tic-Tac-Toe Feld]
lehrkraefte:blc:informatik:ffprg1-2020:klassen [2020/04/15 13:03] (current)
Ivo Blöchliger [Aufgaben]
Line 93: Line 93:
   * Implementieren Sie eine Methode ''draw'', die das Tic-Tac-Toe Feld in ein gpanel zeichnet. Siehe http://www.tigerjython.ch/index.php?inhalt_links=navigation.inc.php&inhalt_mitte=grafik/koordinaten.inc.php    * Implementieren Sie eine Methode ''draw'', die das Tic-Tac-Toe Feld in ein gpanel zeichnet. Siehe http://www.tigerjython.ch/index.php?inhalt_links=navigation.inc.php&inhalt_mitte=grafik/koordinaten.inc.php 
   * Fragen Sie die Maus ab, um Kreuze oder Kreise zu setzen. Siehe http://www.tigerjython.ch/index.php?inhalt_links=navigation.inc.php&inhalt_mitte=grafik/mausevents.inc.php   * Fragen Sie die Maus ab, um Kreuze oder Kreise zu setzen. Siehe http://www.tigerjython.ch/index.php?inhalt_links=navigation.inc.php&inhalt_mitte=grafik/mausevents.inc.php
 +
 +Damit die Maus-Abfrage innerhalb der Klasse erfolgen kann und keine globale Variable benötigt wird, kann eine Closure verwendet werden (das ist eine Funktion, die auf die Variablen Zugriff hat, die an der Stelle ihrer Erzeugung gültig waren):
 +<code python>
 +class TicTacToe:
 +    # Konstruktur, wird bei der Kreation der Instanz aufgerufen
 +    def __init__(self):
 +        # leeres Feld, bestehend aus 3 Arrays mit 3 Einträgen
 +        self.feld = [[0,0,0] for i in range(3)]
 +        # Closure: Lokale Funktion, die auch später noch Zugriff auf self hat:
 +        def handler(x,y):
 +            self.onKlick(x,y)
 +        # Die Closure registrieren
 +        makeGPanel(0, 3, 0, 3, mousePressed = handler)
 +
 +    def onKlick(self,x,y):
 +        # Tu wat sinnvolles damit...
 +        pass
 +
 +</code>
 +
 +<hidden Lösungsvorschlag>
 +<code python tictactoe.py>
 +from gpanel import *
 +
 +class TicTacToe:
 +    # Konstruktur, wird bei der Kreation der Instanz aufgerufen
 +    def __init__(self):
 +        # leeres Feld, bestehend aus 3 Arrays mit 3 Einträgen
 +        self.feld = [[0,0,0] for i in range(3)]
 +
 +        def handler(x,y):
 +            self.onKlick(x,y)
 +            
 +        makeGPanel(0, 2.99, 0, 2.99, mousePressed = handler)
 +        
 +
 +    def draw(self):
 +        clear()
 +        for i in range(1,3):
 +            line(i,0,i,3)
 +            line(0,i,3,i)
 +        for x in range(3):
 +            for y in range(3):
 +                if self.feld[x][y]==1:
 +                    move(x+0.5, y+0.5)
 +                    circle(0.4)
 +                elif self.feld[x][y]==2:
 +                    line(x+0.1, y+0.1, x+0.9, y+0.9)
 +                    line(x+0.1, y+0.9, x+0.9, y+0.1)
 +
 +    def onKlick(self,x,y):
 +        x = int(x)
 +        y = int(y)
 +        if (self.feld[x][y]==0):
 +            self.set(x,y,1)
 +            self.draw()
 + 
 +    # Setze alle Einträge auf 0
 +    def clear(self):
 +        for x in range(3):
 +            for y in range(3):
 +                self.feld[x][y] = 0
 + 
 +    # Standard-Methode zur Umwandlung in einen String, wird von print verwendet
 +    def __str__(self):
 +        symbols = [" ", "O", "X"]
 +        res = ""
 +        for y in range(3):
 +            for x in range(3):
 +                res += " "+symbols[self.feld[x][y]]+" "
 +                if (x<2):
 +                    res += "|"
 +            res += "\n"
 +            if (y<2):
 +                res += "---+---+---\n"
 +        return res
 +
 +
 +   
 +    
 +    # Setzt ein Feld, wenn es leer ist
 +    def set(self,x,y,what):
 +        if (self.feld[x][y]==0):
 +            self.feld[x][y] = what
 +        else:
 +            raise RuntimeError("Feld (%d, %d) ist schon mit %d belegt!" % (x,y,self.feld[x][y]))
 + 
 +    def isEmpty(self,x,y):
 +        return self.feld[x][y]==0
 + 
 + 
 +# Initialierung einer Instanz    
 +t = TicTacToe()
 +# Ruft automatisch __str__ auf, zur Umwandlung in einen String
 +print(t)
 +t.set(1,1,1);
 +print(t)
 +t.set(0,0,2);
 +print(t)
 +t.draw()
 +</code>
 +</hidden>
 +
 +  * Fügen Sie eine weitere Instanz-Variable hinzu, die speichert, wer gerade an der Reihe ist, damit mit der Maus abwechslungsweise ein Kreis und ein Kreuz gesetzt werden kann.
 +  * Fügen Sie eine Überprüfung hinzu, ob jemand schon gewonnen hat. Sie sollten dazu möglichst wenig Code kopieren. Idee: Eine Funktion, die Start-Koordinaten und einen Vektor bekommt, in welche Richtung 3 Felder überprüft werden sollen.
 +
 +<hidden minimal spielbare Version>
 +<code python tictactoe.py>
 +from gpanel import *
 +
 +
 +class TicTacToe:
 +    # Konstruktur, wird bei der Kreation der Instanz aufgerufen
 +    def __init__(self):
 +        # leeres Feld, bestehend aus 3 Arrays mit 3 Einträgen
 +        self.feld = [[0,0,0] for i in range(3)]
 +        self.clear()
 +        def handler(x,y):
 +            self.onKlick(x,y)
 +            
 +        makeGPanel(0, 2.99, 0, 2.99, mousePressed = handler)
 +        
 +
 +    def draw(self):
 +        clear()
 +        for i in range(1,3):
 +            line(i,0,i,3)
 +            line(0,i,3,i)
 +        for x in range(3):
 +            for y in range(3):
 +                if self.feld[x][y]==1:
 +                    move(x+0.5, y+0.5)
 +                    circle(0.4)
 +                elif self.feld[x][y]==2:
 +                    line(x+0.1, y+0.1, x+0.9, y+0.9)
 +                    line(x+0.1, y+0.9, x+0.9, y+0.1)
 +
 +    def onKlick(self,x,y):
 +        if self.winner()>0 or self.placed==9:
 +            # 1 Sekunde warten
 +            self.clear()
 +            self.draw()
 +            return
 +        x = int(x)
 +        y = int(y)
 +        if (self.feld[x][y]==0):
 +            self.placed += 1
 +            self.set(x,y,self.player)
 +            self.draw()
 +            self.player = 3-self.player
 + 
 +    # Setze alle Einträge auf 0
 +    def clear(self):
 +        self.player = 1
 +        self.placed = 0
 +        for x in range(3):
 +            for y in range(3):
 +                self.feld[x][y] = 0
 + 
 +    # Standard-Methode zur Umwandlung in einen String, wird von print verwendet
 +    def __str__(self):
 +        symbols = [" ", "O", "X"]
 +        res = ""
 +        for y in range(3):
 +            for x in range(3):
 +                res += " "+symbols[self.feld[x][y]]+" "
 +                if (x<2):
 +                    res += "|"
 +            res += "\n"
 +            if (y<2):
 +                res += "---+---+---\n"
 +        return res
 +
 +    def check(self,p,v):
 +        feld = self.feld[p[0]][p[1]]
 +        if feld==0:
 +            return 0
 +        # Liste/Array kopieren
 +        p = [p[i] for i in range(len(p))]
 +        for i in range(2):
 +            # Punkt vorruecken
 +            for j in range(2):
 +                p[j] += v[j]
 +            if self.feld[p[0]][p[1]]!=feld:
 +                return 0
 +        return feld
 +
 +    # Liefert 0 (kein Gewinner) oder die Nummer 1 oder 2, wenn jemand gewonnen hat
 +    def winner(self):
 +        for i in range(3):
 +            # Horizontal
 +            w = self.check((0,i),(1,0))
 +            if w>0:
 +                return w
 +            # Vertikal
 +            w = self.check((i,0),(0,1))
 +            if w>0:
 +                return w
 +        # erste Diagonale
 +        w = self.check((0,0),(1,1))
 +        if w>0:
 +            return w
 +        # zweite Diagonale
 +        w = self.check((0,2),(1,-1))
 +        if w>0:
 +            return w
 +        
 +   
 +    
 +    # Setzt ein Feld, wenn es leer ist
 +    def set(self,x,y,what):
 +        if (self.feld[x][y]==0):
 +            self.feld[x][y] = what
 +        else:
 +            raise RuntimeError("Feld (%d, %d) ist schon mit %d belegt!" % (x,y,self.feld[x][y]))
 + 
 +    def isEmpty(self,x,y):
 +        return self.feld[x][y]==0
 + 
 + 
 +# Initialierung einer Instanz    
 +t = TicTacToe()
 +# Ruft automatisch __str__ auf, zur Umwandlung in einen String
 +t.draw()
 +
 +</code>
 +</hidden>
  
  • lehrkraefte/blc/informatik/ffprg1-2020/klassen.1583132516.txt.gz
  • Last modified: 2020/03/02 08:01
  • by Ivo Blöchliger