verdammt, ich kapier es einfach nicht

Fragen zu Tkinter.
Benutzeravatar
wuf
User
Beiträge: 1483
Registriert: Sonntag 8. Juni 2003, 09:50

Dienstag 22. Juli 2008, 11:31

Hallo BlackJack

Wie es so ist für solche die den OOP-Mechanismus noch nicht ganz inne haben können beim durchlesen des Codes bestimmet Zusammenhänge noch nicht so klar überblickt werden. Ich muss gestehen, dass ich meinen Vorschlag mit der Konsole (übrigens eine hilfreiche Mini-GUI) nicht vollumfänglich getestet habe. Ich wollte diesen Test 'derkai' überlassen.

Ich habe das CodeSchnipsel nun so abgeändert, dass es sich so verhält wie ich mir dies vorgestellt habe. Mit anschliessender Konsolen-Ausgabe:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#~ Skriptname programm_logic_03_01.py (22.07.2008)

class Tile(object):
    """Klasse:Spielfeld"""

    def __init__(self, name):
        """Konstruktor für die Klasse-Tile"""
        self.name = name
        self.panzer = "."

#~~ Konstanten für Spielfeld-Typen
DESERT = 'Desert'
WOODS = 'Wood'

class Map(object):
    """Klasse:Spielkarte"""

    #~~ Konstante für die Abfrage der Nachbarfelder
    DIRECTION_DELTAS = [(0, -1), (1, 0), (0, 1), (-1, 0)]

    #~~ Gibt die Anzahl x-Felder (Spalten) zurück
    @property
    def width(self):
        return len(self.tiles[0])

    #~~ Gibt die Anzahl y-Felder (Reihen) zurück
    @property
    def height(self):
        return len(self.tiles)

    def __init__(self, width, height, tile_type=DESERT):
        """Konstruktor für die Klasse Map"""

        #~~ Erzeugt eine Feldobjekt-Liste mit der
        #   Anzahl 'width' * 'height' Feldobjekten
        self.tiles = []
        self.row_list = []
        for  y in xrange(height):
            for x in xrange(width):
                self.row_list.append(Tile(tile_type))
            self.tiles.append(self.row_list)
            self.row_list = []

    def __getitem__(self, coordinates):
        """Adressiert das Feldobjekt"""
        x, y = coordinates
        return self.tiles[y][x]

    def __setitem__(self, coordinates, tile):
        """Setzt den Feldtyp"""
        x, y = coordinates
        self.tiles[y][x] = tile

    def neighbour_coordinates(self, coordinates):
        """Ermittelt die Koordinaten der Nachbarfelder"""
        x, y = coordinates
        for delta_x, delta_y in self.DIRECTION_DELTAS:
            new_x = x + delta_x
            new_y = y + delta_y
            if 0 <= new_x < self.width and 0 <= new_y < self.height:
                yield new_x, new_y


def main():
    #~~ Erstellt ein Spielfeld mit 10 * 10 Feldobjekten (default-Feldyp = 'Desert'

    SPALTEN = COLUMNS = 10
    REIHEN = ROWS = 10

    #~~Erstellt eine Instanz der Spielfeld-Klasse (Map)
    game_map = Map(SPALTEN, REIHEN)

    print 'Anzahl Spalten',game_map.width
    print 'Anzahl Reihen',game_map.height

    #~~ Ändert den Feldtyp des Feld auf Koordinate x=2,y=4
    #   in ein Feldtyp 'Wood' um
#    game_map[2, 4] = WOODS
    game_map[2, 4].name = WOODS

    #~~ Test: Abfrage des Feldtyp-Namens der Felder auf Koordinate:
    #         a) x=2,y=4 ('Wood')
    #         b) x=3,y=2 ('Desert')
    for x, y in [(2, 4), (3, 2)]:
        print game_map[x, y].name

    print 'Nachbar-Koordinate',list(game_map.neighbour_coordinates((1, 1)))
    #~~ Gibt die Koordinaten der Nachbarfelder des
    #   Testfeldes auf Koordinate x=1,y=1 zurück.
    #
    #   Testfeld     X  x=1,y=1
    #   Nachbarfeld  a  x=1,y=0
    #   Nachbarfeld  b  x=0,y=1
    #   Nachbarfeld  c  x=1,y=2
    #   Nachbarfeld  d  x=2,y=1
    #
    #         0   1   2   3 - x
    #         ------------------
    #     0 |   | a |   |   |
    #         ------------------
    #     1 | b | X | d |   |
    #         ------------------
    #     2 |   | c |   |   |
    #         ------------------
    #     3 |   |   |   |   |
    #         ------------------
    #     x |   |   |   |   |


    #*** DER PANZER BELEGUNGS-TEST ***

    #~~ Setze drei unterschiedliche Panzertypen auf verschiedene
    #   Spielfelder auf der Spielkarte
    game_map[2, 5].panzer = 'O' # Panzer-O
    game_map[8, 8].panzer = 'X' # Panzer-X
    game_map[9, 3].panzer = 'Z' # Panzer-Z

    #~~ Zeige die Spielkarte-Panzerbelegung auf der Konsole
    print
    for y in xrange(game_map.height):
        for x in xrange(game_map.width):
            print game_map[x, y].panzer,
        print

main()
@BlackJack Was meinst du zu dieser Variante?

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
wuf
User
Beiträge: 1483
Registriert: Sonntag 8. Juni 2003, 09:50

Dienstag 22. Juli 2008, 15:47

Habe das Code-Schnipsel mit der Klasse 'Tank' und TankHandler Spielfeld unabhängig erweitert:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#~ Skriptname programm_logic_04_01.py (22.07.2008)

class Tank(object):
    """Klasse:Panzer"""

    def __init__(self, name):
        """Konstruktor für die Klasse Tank"""
        self.name = name

MECHTEC = Tank('Mechtec')
RASPUTIN = Tank('Rasputin')
LEOPARD = Tank('Leopard')

class Tile(object):
    """Klasse:Spielfeld"""

    def __init__(self, name):
        """Konstruktor für die Klasse Tile"""
        self.name = name

#~~ Spielfeld-Instanzen
DESERT = Tile('Desert')
WOODS = Tile('Woods')

class Map(object):
    """Klasse:Spielkarte"""

    #~~ Konstante für die Abfrage der Nachbarfelder
    DIRECTION_DELTAS = [(0, -1), (1, 0), (0, 1), (-1, 0)]

    #~~ Gibt die Anzahl x-Felder (Spalten) zurück
    @property
    def width(self):
        return len(self.tiles[0])

    #~~ Gibt die Anzahl y-Felder (Reihen) zurück
    @property
    def height(self):
        return len(self.tiles)

    def __init__(self, width, height, tile=DESERT):
        """Konstruktor für die Klasse Map"""

        #~~ Erzeugt eine Feldobjekt-Liste mit der
        #   Anzahl 'width' * 'height' Feldobjekten
        self.tiles = [[tile] * width for dummy in xrange(height)]

    def __getitem__(self, coordinates):
        """Adressiert das Feldobjekt"""
        x, y = coordinates
        return self.tiles[y][x]

    def __setitem__(self, coordinates, tile):
        """Setzt den Feldtyp"""
        x, y = coordinates
        self.tiles[y][x] = tile

    def neighbour_coordinates(self, coordinates):
        """Ermittelt die Koordinaten der Nachbarfelder"""
        x, y = coordinates
        for delta_x, delta_y in self.DIRECTION_DELTAS:
            new_x = x + delta_x
            new_y = y + delta_y
            if 0 <= new_x < self.width and 0 <= new_y < self.height:
                yield new_x, new_y

class TankHandler(object):

    #~~ Gibt Panzer-Koordinaten zurück
    @property
    def coordinates(self):
        return coordinates

    def __init__(self):
        """Konstruktor für die Klasse Map"""
        self.tanks = []

    def __setitem__(self, coordinates, tank):
        """Setzt den Feldtyp"""
        tank.coordinates = coordinates
        self.tanks.append(tank)

def main():
    #~~ Erstellt ein Spielfeld mit 10 * 10 Feldobjekten (default-Feldyp = 'Desert'

    SPALTEN = COLUMNS = 10
    REIHEN = ROWS = 10

    #~~Erstellt eine Instanz der Spielfeld-Klasse (Map)
    game_map = Map(SPALTEN, REIHEN)

    print 'Anzahl Spalten',game_map.width
    print 'Anzahl Reihen',game_map.height

    #~~ Ändert den Feldtyp des Feld auf Koordinate x=2,y=4
    #   in ein Feldtyp 'Wood' um
    game_map[2, 4] = WOODS

    #~~ Test: Abfrage des Feldtyp-Namens der Felder auf Koordinate:
    #         a) x=2,y=4 ('Wood')
    #         b) x=3,y=2 ('Desert')
    for x, y in [(2, 4), (3, 2)]:
        print game_map[x, y].name

    print 'Nachbar-Koordinate',list(game_map.neighbour_coordinates((1, 1)))
    #~~ Gibt die Koordinaten der Nachbarfelder des
    #   Testfeldes auf Koordinate x=1,y=1 zurück.
    #
    #   Testfeld     X  x=1,y=1
    #   Nachbarfeld  a  x=1,y=0
    #   Nachbarfeld  b  x=0,y=1
    #   Nachbarfeld  c  x=1,y=2
    #   Nachbarfeld  d  x=2,y=1
    #
    #         0   1   2   3 - x
    #         ------------------
    #     0 |   | a |   |   |
    #         ------------------
    #     1 | b | X | d |   |
    #         ------------------
    #     2 |   | c |   |   |
    #         ------------------
    #     3 |   |   |   |   |
    #         ------------------
    #     x |   |   |   |   |


    tank_handler = TankHandler()

    #~~ Platziere
    tank_handler[2,4] = LEOPARD
    tank_handler[5,8] = RASPUTIN
    tank_handler[8,1] = MECHTEC

    for tank in tank_handler.tanks:
        print tank.name,tank.coordinates

main()
Gruss wuf :wink:
Take it easy Mates!
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 16:26

äh, Jungs -
ich freue mich, dass Ihr so viel Spass daran habt mit mir zu basteln.
Allerdings ist das für mich ne Nummer zu hoch.

Ich befinde mich immer noch auf dem I Dötzchen Niveau !!!

Ist aber ok, ich versuche mich mal weiter an einer Logik, die
ohne Gui auskommt. Da werden noch eine ganze Menge Probleme auf mich zukommen, bei denen ich dann wieder um Hilfe schreien würde - OK ?!

Kai
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 18:38

so ein Mis... - jetzt fang ich doch gerade wieder bei 0 an.
Ich wolte mir eine Liste aller Hexfelder erstellen :

Code: Alles auswählen

from math import sqrt

laenge =  20
hexliste = []
xpos = xorg = 20
ypos = yorg = 10
xoffset = laenge * 1.5
yoffset = sqrt(3) * laenge


""" Funktion zur Berechnung der Hexagonpunkte """


def neues_feld (xpos,ypos):

    x1 = xpos
    y1 = ypos
    x2 = x1 + laenge
    y2 = y1
    x3 = x2 + (laenge/2.0)
    y3 = y2 + ((laenge * sqrt(3)/2))
    x4 = x2
    y4 = (sqrt(3) * laenge) + y2
    x5 = x1
    y5 = y4
    x6 = x1 - (laenge / 2.0)
    y6 = y3

    return (x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6)



""" Anlegen der Hexliste """


for counter in range (1) :


    if counter %2 == 0 :

        for k in range (2) :
            hexliste.append (neues_feld (xpos,ypos))
            xpos = xpos + xoffset * 2
           

print hexliste


from Tkinter import *
master = Tk()
spiel = Canvas(master, width=900, height=900)
spiel.pack()
spiel.create_polygon(hexliste)
master.mainloop()













     
Die beiden Listen der x,y Koordinaten sollten meiner Anicht nach auch stimmten. Zwei Felder in der ersten Reihe. Allerdings zeichnet der nur Müll.
Selbst wenn ich bestimme, dass er nur Element 1 (hexliste[0]) und NUR Element 2 (hexliste[1]) zeichnen soll, sind diese korrekt positioniert.
Nur bei der ausgabe der gesamten Liste passiert das Durcheinander.

Wo liegt denn der Fehler ?

Kai
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 18:54

ich glaube ich habe es schon, so würde es gehen :

Code: Alles auswählen

for x in range (len(hexliste)) :
    spiel.create_polygon(hexliste[x])
imac
20 Zoll
2,4 ghz
BlackJack

Dienstag 22. Juli 2008, 19:45

Bitte nicht ``range(len(obj))`` und indexe verwenden, sondern direkt über die Elemente von `obj` iterieren. Danke.
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 20:19

das hatte ich probiert, leider ohne Erfolg :

Code: Alles auswählen

for c in hexliste() :
    spiel.create_polygon (hexliste[c],outline="black",fill=choice(farbe))
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 20:21

Code: Alles auswählen

for c in (hexliste) :
    spiel.create_polygon (hexliste[c],outline="black",fill=choice(farbe))
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 20:22

Code: Alles auswählen

for c in range (hexliste) :
    spiel.create_polygon (hexliste[c],outline="black",fill=choice(farbe))
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 20:23

funktoniert leider alles nicht ...

Kai
imac
20 Zoll
2,4 ghz
BlackJack

Dienstag 22. Juli 2008, 20:45

Du solltest vielleicht nicht wild herum raten, sondern erst einmal Python-Grundlagen lernen.
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Dienstag 22. Juli 2008, 21:26

das versuche ich ja gerade,

Code: Alles auswählen

for x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6 in hexliste :
    spiel.create_polygon ((x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6),outline="black",fill=choice(farbe)
imac
20 Zoll
2,4 ghz
Benutzeravatar
wuf
User
Beiträge: 1483
Registriert: Sonntag 8. Juni 2003, 09:50

Mittwoch 23. Juli 2008, 11:10

Hallo Kai

Geht es nicht mehr so reibungslos? :lol:

Hier dein Code leicht abgeändert:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Skriptname: kai_22072008_02.py (wuf 23.07.2008

from math import sqrt

laenge =  20
hexliste = []
xpos = xorg = 20
ypos = yorg = 10
xoffset = laenge * 1.5
yoffset = sqrt(3) * laenge


""" Funktion zur Berechnung der Hexagonpunkte """

def neues_feld (xpos,ypos):

    x1 = xpos
    y1 = ypos
    x2 = x1 + laenge
    y2 = y1
    x3 = x2 + (laenge/2.0)
    y3 = y2 + ((laenge * sqrt(3)/2))
    x4 = x2
    y4 = (sqrt(3) * laenge) + y2
    x5 = x1
    y5 = y4
    x6 = x1 - (laenge / 2.0)
    y6 = y3

    return (x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6)

ANZAHL = 2
#~~ Anlegen der Hexliste
for counter in xrange(1):
    if counter %2 == 0:
        for k in xrange(ANZAHL):
            hexliste.append(neues_feld(xpos,ypos))
            xpos = xpos + xoffset * 2

import Tkinter as tk

master = tk.Tk()
spiel = tk.Canvas(master, width=900, height=900)
spiel.pack()


#~~ Zeichnen der Poly's
for poly_coords in hexliste:
    spiel.create_polygon(poly_coords,fill='red')


master.mainloop()
Hauptänderung von:

Code: Alles auswählen

spiel.create_polygon(hexliste)
auf:

Code: Alles auswählen

#~~ Zeichnen der Poly's
for poly_coords in hexliste:
    spiel.create_polygon(poly_coords,fill='red')
Du kannst nicht die ganze hexliste sondern nur Elemente dieser Liste für die Bildung eines Hex-Poligon verwenden. Ein Element entspricht exakt den Daten eines Hex-Poligons. Ein Element ist ein Tuple mit insgesamt 12 Werten.

Gruss wuf :wink:
Take it easy Mates!
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Sonntag 27. Juli 2008, 13:12

ich bin damit nicht zufrieden :


Code: Alles auswählen

from math import sqrt

class Hexfeld (object) :

    laenge = 20
   
    def __init__ (self):
        pass
    
    def berechne (self, xpos, ypos,feldid):

        laenge = 20
        
        x1 = xpos
        y1 = ypos
        x2 = x1 + laenge
        y2 = y1
        x3 = x2 + (laenge/2.0)
        y3 = y2 + ((laenge * sqrt(3)/2))
        x4 = x2
        y4 = (sqrt(3) * laenge) + y2
        x5 = x1
        y5 = y4
        x6 = x1 - (laenge / 2.0)
        y6 = y3

        return (x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6,feldid)

    def berechne2 (self, xpos, ypos):

        laenge = 20
        
        x1 = xpos
        y1 = ypos
        x2 = x1 + laenge
        y2 = y1
        x3 = x2 + (laenge/2.0)
        y3 = y2 + ((laenge * sqrt(3)/2))
        x4 = x2
        y4 = (sqrt(3) * laenge) + y2
        x5 = x1
        y5 = y4
        x6 = x1 - (laenge / 2.0)
        y6 = y3

        return (x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6)
  

    def test (self,x):
        print x


hexliste = []
xpos = xorg = 20
ypos = yorg = 10
xoffset = Hexfeld.laenge * 1.5
yoffset = sqrt(3) * Hexfeld.laenge


for reihe in range (42) :
    
    if reihe %2 == 0 :

        for feld in range (17) :
            feldid = reihe,feld
            feldid = Hexfeld()
            hexliste.append (feldid.berechne (xpos, ypos,(feldid)))
            xpos = xpos + xoffset * 2
        xpos = xorg + xoffset
        ypos = ypos + yoffset / 2

    else :

        for feld in range (16) :
            feldid = reihe, feld
            feldid = Hexfeld()
            hexliste.append(feldid.berechne (xpos, ypos, (feldid)))
            xpos = xpos + xoffset * 2
        xpos = xorg
        ypos = ypos + yoffset / 2

from Tkinter import *
master = Tk()
spiel = Canvas(master, width=1024, height=768)
spiel.pack()

for x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6,feldid in hexliste :
    spiel.create_polygon ((x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6))

spiel.create_polygon (feldid.berechne2(10,10))

    
master.mainloop()

   

    
Ich möchte zwei Dinge erreichen :

1. Es soll durch eine Schleife die Liste Hexliste erstellt und die x,y Werte der einzelnen Hexfelder übergeben werden. Das hat auch geklappt.

2. Mit jedem Schleifendurchlauf soll eine Instanz der Klasse Hexfeld erstellt werden. Und diese Instanz soll über die Schleife die Wete x1 und y1 erhalten. Die Instanz soll aber einen "für mich" eindeutigen Namen haben über den man dann wieder auf sie zugreife kann. BSP Die erste Instanz soll den NAMEN : 1A erhalten.
Das gelingt mir aber irgendwie nicht.

Ich habe in dem Code also zwei Probleme :

1. der Name der Instanz
2. es sollen jeweils nur die Werte xpos und ypos übergeben und
x1,y1 .. bis x6,y6 gespeichert werden.
Muss ich dass dann schon beim Instanzieren erledigen ?
Also auch die Berechnung meine ich ?

Code: Alles auswählen

from math import sqrt

class Hexfeld (object) :

    laenge = 20
   
 
    def __init__ (self, xpos, ypos,feldid):

        laenge = 20

        self.xpos = xpos
        self.ypos = ypos
        
        x1 = xpos
        y1 = ypos
        x2 = x1 + laenge
        y2 = y1
        x3 = x2 + (laenge/2.0)
        y3 = y2 + ((laenge * sqrt(3)/2))
        x4 = x2
        y4 = (sqrt(3) * laenge) + y2
        x5 = x1
        y5 = y4
        x6 = x1 - (laenge / 2.0)
        y6 = y3
imac
20 Zoll
2,4 ghz
Benutzeravatar
wuf
User
Beiträge: 1483
Registriert: Sonntag 8. Juni 2003, 09:50

Sonntag 27. Juli 2008, 15:14

Hallo derkai

Ich habe deinen Code ein wenig ergänzt. Ist aber nur für Übungszwecke gedacht. Sorry ich habe deine Sechecke anderst eingefärbt, dass Scharze Loch auf meinem Bildschirm machte mich fast blind. :lol:

Hier der Code:

[Code ausgelagert]

Gruss wuf :wink:
Take it easy Mates!
Antworten