Seite 1 von 2

Verzweifle an Tic Tac Toe

Verfasst: Montag 31. August 2009, 17:12
von Infrared
Liebe Member,
Ich hoffe ihr könnt mir da ein wenig weiter helfen.
Ich arbeite bereits seit längerem an einem Tic Tac Toe:

Code: Alles auswählen

#Standarteinstellungen - keine Veraenderungen noetig
#
#



from Tkinter import *
import time

global anzeige
global masterstring
masterstring = " "

def Rechner (master):
    global anzeige
    global B1
    global B2
    global B3
    global B4
    global B5
    global B6
    global B7
    global B8
    global B9




    frame = Frame(master)
    frame.pack()

    frame0 = Frame(frame)
    frame0.pack(side=TOP)

    frame1 = Frame(frame)
    frame1.pack(side=TOP)

    frame2 = Frame(frame)
    frame2.pack(side=TOP)

    frame3 = Frame(frame)
    frame3.pack(side=TOP)
    
    frame4 = Frame(frame)
    frame4.pack(side=TOP) 
    
    frame5 = Frame(frame) 
    frame5.pack(side=TOP)
    
    frame6 = Frame(frame)
    frame6.pack(side=TOP)
    
    frame7 = Frame(frame)
    frame7.pack(side=TOP)
    
    frame8 = Frame (frame)
    frame8.pack(side=RIGHT)
    
    frame9 = Frame (frame)
    frame9.pack(side=LEFT)
    
    frame10 = Frame (frame)
    frame10.pack(side=LEFT)
    
    
    





    B1 = Button(frame1, text="", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=eins)
    B1.pack(side=LEFT)
    
    B2 = Button(frame1, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=zwei)
    B2.pack(side=LEFT)

    B3 = Button(frame1, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=drei)
    B3.pack(side=LEFT)
    
    B4 = Button(frame2, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=vier)
    B4.pack(side=LEFT)
    
    B5 = Button(frame2, text=" ", bg="#F2FFFF", width=10, height=5, relief="sunken", borderwidth = 5, command=fuenf)
    B5.pack(side=LEFT)
    
    B6 = Button(frame2, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=sechs)
    B6.pack(side=LEFT)
    
    B7 = Button(frame3, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=sieben)
    B7.pack(side=LEFT)

    B8 = Button(frame3, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=acht)
    B8.pack(side=LEFT)

    B9 = Button(frame3, text=" ", bg="#F2FFFF", width=10, height=5, borderwidth = 5, command=neun)
    B9.pack(side=LEFT)
    
    B10 = Button(frame4, text="Spieler 1", width=10, height=5, borderwidth = 5, command=player1)
    B10.pack(side=LEFT)
    
    B11 = Button(frame4, text="Spieler 2", width=10, height=5, borderwidth = 5, command=player2)
    B11.pack(side=LEFT)



def player1():
    player = "X"

def player2():
    player = "O"


global player
player = " "




def eins():
    global B5
    global B6
    B1.configure(text=player, bg="#FF9999")
    
def zwei():
    global B5
    global B6
    B2.configure(text=player, bg="#FF9999")
    
def drei():
    global B5
    global B6
    B3.configure(text=player, bg="#FF9999")
    
def vier():
    global B5
    global B6
    B4.configure(text=player, bg="#FF9999")
    
def fuenf():
    global B5
    global B6
    B5.configure(text=player, bg="#FF9999")

def sechs():
    global B5
    global B6
    B6.configure(text=player, bg="#FF9999")
    
def sieben():
    global B5
    global B6
    B7.configure(text=player, bg="#FF9999")
    
def acht():
    global B5
    global B6
    B8.configure(text=player, bg="#FF9999")
    
def neun():
    global B5
    global B6
    B9.configure(text=player, bg="#FF9999")

#Sonstige Definitionen und Anpassungen
#
#
    
def add_to_string(pWert):
    global masterstring
    global anzeige

    masterstring = masterstring + str(pWert)
    anzeige.configure(text = masterstring)
    print masterstring


root = Tk()
Rechner(root)
root.geometry( '240x300+250+250')
root.mainloop()
So. Ich war in der Hoffnung das durch den Klick auf einen Button er automatisch erkennt, dadurch das man vorher auf Spieler 1 oder 2 klickt ein X bzw. ein O in den Button zu setzen. Das ist mir erst einmal wichtig.
Er brauch erst garnicht erkennen ob man gewonnen oder verloren hat. (Falls es jemand weiß, kann er es natürlich dazuposten :D )
Das Grundgerüst wie es dort ist möchte ich auf jeden Fall beibehalten.
Ich wüsste nur gern was ich falsch gemacht habe oder was ich dafür noch ergänzen muss.

Außerdem wäre es ganz hilfreich nicht dauernt auf Spieler 1 und 2 zu klicken, sondern das der Computer von alleine zwischen X und O wechselt.

Aber wie gesagt: Am wichtigsten ist das die X und O's ersteinmal erscheinen. :)

Schon einmal vielen Dank fürs durchlesen.

Mfg
Infrared

Verfasst: Montag 31. August 2009, 17:35
von EyDu
Nur fürs Zeitmanagement: Bedeutet "seit längerem" seit dem Informatikunterricht letzte Woche und ist die Hausaufgabe wieder bis Freitag zu erledigen? :P

Verfasst: Montag 31. August 2009, 17:59
von Infrared
was? :?

Verfasst: Montag 31. August 2009, 21:41
von Infrared
kann mir wirklich keiner helfen
oder kommt "das beste zum schluss" ?

Verfasst: Montag 31. August 2009, 22:28
von BlackJack
Ich denke der Knackpunkt dürfte folgender Satz sein: "Das Grundgerüst wie es dort ist möchte ich auf jeden Fall beibehalten."

Da kann Dir wirklich keiner helfen. ;-)

Verfasst: Montag 31. August 2009, 22:47
von cofi
Um das mal auf den Punkt zu bringen:

Code: Alles auswählen

In [2]: code.count("global")
Out[2]: 33
Daneben ist der Code fuerchterlich redundant.

Das ``global`` in Zeile 114 sollte vor Zeile 111 und 108 stehen. Daneben fehlt die Logik in den "Klick"-Funktionen, um zu erkennen, welcher Spieler aktiv ist.

Sag mal gehoerst du zu http://www.python-forum.de/topic-20047.html und http://www.python-forum.de/topic-20035.html ? Wenn ja schick doch bitte mal deinen Lehrer vorbei. Dieser Programmierstil ist unter aller Sau.

Verfasst: Dienstag 1. September 2009, 00:43
von EyDu
Der Code sollte weiterhelfen ^^

Code: Alles auswählen

import Tkinter as tk
import itertools
import functools

class MTTT(type):
    def __init__(cls, *args, **kwds):
        def fk(b, a, r):
            bt = getattr(b, MTTT.btnmmkr(a, r))
            if b.fld[a,r] not in TTT.PLYS:
                p = b.gplyr()
                bt.configure(text=p)
                b.ntplyr()
                b.fld[a,r] = p
        
        flds = dict(zip(itertools.product(range(cls.SZ), repeat=2),
                    itertools.repeat(" ")))
        [setattr(cls, MTTT.nmmkr(x,y), fk) for x,y in flds]
         
        type.__init__(cls, *args, **kwds)
    
    def __call__(cls, rt, *args, **kwds):
        inst = type.__call__(cls, *args, **kwds)
        
        inst.fld = dict(zip(itertools.product(range(TTT.SZ), repeat=2),
                            itertools.repeat(" ")))
        for (d,o), of in inst.fld.iteritems():
            nm = MTTT.btnmmkr(d, o)
            
            setattr(inst, nm, tk.Button(rt,
                                        text=of,
                                        bg="#F2FFFF",
                                        width=10,
                                        height=5,
                                        borderwidth=5,
                                        command=functools.partial(getattr(inst, MTTT.nmmkr(d, o)), d, o)))
            getattr(inst, nm).grid(row=d,column=o)
            
        inst.plyr = 0
        
        return inst

    @staticmethod
    def nmmkr(a, b):
        nm = ["null", "one", "deux"]
        return "on_%s_%s" % (nm[a], nm[b])
    
    @staticmethod
    def btnmmkr(a, b):
        return "btn_%s" % MTTT.nmmkr(a, b)

class TTT(object):
    __metaclass__ = MTTT
    SZ = 3
    PLYS = ["x", "o"]
    
    def gplyr(self):
        return TTT.PLYS[self.plyr]
    
    def ntplyr(self):
        self.plyr = (self.plyr + 1) % len(TTT.PLYS)


def main():
    root = tk.Tk()
    t = TTT(root)
    root.geometry('350x300+250+250')
    root.mainloop() 

if __name__ == "__main__":
    main()

Verfasst: Dienstag 1. September 2009, 05:00
von gkuhl
Die Verwendung von ´´global´´ wird von der Python Community strafrechtlich verfolgt. Auch dein Lehrer muss sich vermutlich auf eine Anzeige wegen Anstiftung zur Verwendung von ´´global´´ einstellen. In der Vergangenheit sind ähnliche Klagen der Community schon sehr erfolgreich gewesen und mit hohen Schadensersatzzahlungen pro ´´global´´-Statement belohnt worden.

Verfasst: Dienstag 1. September 2009, 10:00
von cofi
Hmm gkuhl bring mich nicht auf dumme Ideen :twisted:

Das Problem ist ganz einfach, dass man gegen Python kaempft, wenn man _so_ ausufernd ``global`` verwendet.

Man schiesst sich damit ziemlich schnell selbst in den Fuss und wenn etwas nicht klappt, werden einfach noch ein paar ``global`` verteilt bis es endlich klappt, statt nach der Loesung zu suchen. Und das sieht man auch im Code vom OP.

@EyDu: Hattest du einen Scherzkeks zum Abendessen? :twisted:

Verfasst: Dienstag 1. September 2009, 10:42
von EyDu
cofi hat geschrieben:@EyDu: Hattest du einen Scherzkeks zum Abendessen? :twisted:
Ich musste mich für eine halbe Stunde mal ablenken. Ganz zufrieden bin ich mit meiner Lösung allerdings noch nicht. Anstatt in Zeile 35 die Koordinaten zu übergeben, könnte man auch (natürlich mit REs) aus den Funktionsnamen die Werte schließen.

Verfasst: Dienstag 1. September 2009, 13:20
von Infrared
gkuhl hat geschrieben:Die Verwendung von ´´global´´ wird von der Python Community strafrechtlich verfolgt. Auch dein Lehrer muss sich vermutlich auf eine Anzeige wegen Anstiftung zur Verwendung von ´´global´´ einstellen. In der Vergangenheit sind ähnliche Klagen der Community schon sehr erfolgreich gewesen und mit hohen Schadensersatzzahlungen pro ´´global´´-Statement belohnt worden.
achso. :roll: Bestimmt irgegndwann mal.


Aber wirklich weiter bin ich mit dem code auf nicht EyDu.
Von mir aus ändert auch das Grundgerüst :D
aber ich komm nicht weiter

Verfasst: Dienstag 1. September 2009, 13:32
von /me
Infrared hat geschrieben:Von mir aus ändert auch das Grundgerüst :D
aber ich komm nicht weiter
Damit wir qualifiziert weiterhelfen können solltest du uns mitteilen, wie denn überhaupt dein Wissensstand in Bezug auf Programmierung allgemein und Python speziell ist. Bei dem bisherigen Aufbau deines Programms sieht man sehr schnell, dass dir wohl elementare Grundlagen fehlen die du erst einmal verstehen musst.

Gruß,
Matthias

Verfasst: Dienstag 1. September 2009, 16:05
von EyDu
Schon besser: http://paste.pocoo.org/show/137466/

An der PEP8-Konformität sollte ich noch arbeiten ... :lol:

Verfasst: Dienstag 1. September 2009, 23:01
von wuf
Hallo Infrared

Willkommen in unserm Forum!

Das folgende Skript ist meine Variante des Tic-Tac-Toe's:
http://paste.pocoo.org/show/137516/

Die Spielauswertung muss aber noch programmiert werden!

Viel Spass beim Programmieren mit Python & Tkinter :D

Gruss wuf :wink:

Verfasst: Donnerstag 3. September 2009, 22:15
von yipyip
Und noch eine Variante. :)
http://paste.pocoo.org/show/137864/

Es fehlen natuerlich Auswertung, KI, Netzwerk...
Laeuft bei mir unter Python 2.6 und 3.1 .

:wink:
yipyip

Verfasst: Sonntag 6. September 2009, 17:07
von Infrared
schuldigung das ich erst einmal nicht zurück schreiben konnte.
Aber die fertigen scripts und antworten haben mich ein ganzes stück weiter gebracht. danke

:D

Verfasst: Montag 7. September 2009, 14:12
von Infrared
habe da doch noch eine frage:
wie erkennt python, ob jemand gewonnen hat oder nicht? sprich, wie kann man den inhalt eines buttons auslesen?? :shock:

Verfasst: Montag 7. September 2009, 20:06
von wuf
Hallo Infrared

Den Inhalt eines Button-Widgets kannst du auf zwei Arten auslesen:

Code: Alles auswählen

inhalt = button_obj.cget("text")
oder

Code: Alles auswählen

inhalt = button_obj["text"]
Gruss wuf :wink:

Verfasst: Montag 7. September 2009, 20:30
von BlackJack
Sollte man aber nicht machen. Die GUI ist nicht dazu da sich Daten zu merken, das sollte man besser in der Programmlogik unabhängig von der GUI machen.

Verfasst: Montag 7. September 2009, 20:41
von yipyip
Wollte eigentlich das Gleiche wie BlackJack sagen...

Hier meine erweiterte Version mit Auswertung:
http://paste.pocoo.org/show/138580/

Fehlen nur noch KI und Netzwerk...

:wink:
yipyip