verdammt, ich kapier es einfach nicht

Fragen zu Tkinter.
BlackJack

Ich meinte schon was ich geschrieben habe. Die einfachste Lösung, solange niemand auf die Idee kommt, dass verschiedene Felder des gleichen Feldtyps unterschiedliche Werte haben können. Davon ist in der Anforderung aber nichts zu lesen, also warum einen Haufen gleichwertiger Objekte erzeugen, wenn es *eines* auch tut.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Hallo BlackJack,
hab mir's grade nochmal angeschaut...
stimmt, Du ersetzt die Feldobjekte im nachhinein.

Ich ging von individuellen Feldobjekten aus,
deren Werte man veraendert, anstelle von
Feldern, denen man neue Objekte zuweist.

Geht auch so herum.
(und spart Speicher...)

:wink:
LG yipyip
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo derkai

Ich habe noch weitere Fragen:

Kann ein Spielfeld (Sechseck oder auch Quadrat) noch weitere topografische Eigenschaften haben so zum Beispiel Wasser, Berge usw.? Was für weitere Eigenschaften oder Objekte werden einem Spielfeld sonst noch zugeordnet?
Sicher ein Panzer- oder sonstiges Waffenobjekt, eine Feldnummer usw.

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

na ja, ganz weit entfernte Planungen gehen dahin, dass die Landschaft neben dem "normalen", Wasser und Wald später auch Berge haben soll.
Dies wirft allerdings dann so Problematiken auf, wie ob man den
Gegner überhaupt sehnen kann oder nicht. Daher rückt das noch ganz weit weg.

Ausserdem weit weg sind folgende Gedanken. Es wäre gut, wenn jeder
Spieler zu Beginn des Spiels nur etwa 10 Felder im eigenen Umkreis sehen könnte. Jeder Panzer würde dann einen Sensor besitzen, der eben jene 10 Felder Umkreis betrachten könnte. Jedes Feld, was aber durch die eigenen Bewegung betreten würde (+10 Umkreisfelder) bleiben aber dauerhaft sichtbar, sobald sie einmal vom Panzer erfasst wurden. So würde sich dann erst langsam das gesamte Terrain auftun.

An sonsten soll die Spielfläche erst einmal keine weiteren Obejekte beinhalten.

Helft Ihr mir mal bei meinem OHNE GUI CODE Schnipsel weiter ?

Code: Alles auswählen

import Daten
from math import sqrt

laenge = 20

class Panzer (object):


    def __init__ (self, var) :

        self.var = var
        print self.var



    def vorlage_bewegung (self, feldalt, feldneu) :

        """ dient der Ermittlung der Vorlage durch die
            eigene Bewegung. """

        entfernungx = 0
        entfernungy = 0
        feldmitteneu = 0
        feldmittealt = 0
        

        """ Berechnung der Feldmitten alt + neu """

        feldmittealt = ((feldalt[0]+laenge/2),(feldalt[1]+(laenge*sqrt(3)/2)))
        feldmitteneu = ((feldneu[0]+laenge/2),(feldneu[1]+(laenge*sqrt(3)/2)))


        """ Berechnung der Differenz der x y Mitten der Felder alt + neu """

        print   (feldalt, feldneu)       
        print   (feldmittealt,feldmitteneu)


        """ Ermittlung der Felderdifferenz """

        entfernungx = feldmittealt[0] - feldmitteneu[0]
        entfernungy = feldmittealt[1] - feldmitteneu[1]
        


        print   "X Differenz : ", entfernungx
        print   "Y Differenz : ", entfernungy
        
        print   laenge * sqrt(3) / 2


        """ Ermittlung der tasaechlich bewegten Felder """


    


        

    
Spieler1 = Panzer (Daten.tiger)
Spieler2 = Panzer (Daten.leopard)
Spieler1.var ["pav"] = 20
print Spieler1.var
print Spieler1.vorlage_bewegung((20,10),(110,61.9615242271))




        

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

ich dachte mir, ich übergebe ein Tupel bestehend aus x/y Koordinate des
späteren Spielfeldes, bestimme den Mittelpunkt des Hexagon und berechne die Differenz x/y zwischen dem Feld, von welchem die Bewegung aus begann und jenem wo der Panzer das Ende seiner Bewegung findet.

Dies soll dazu dienen, zu ermitteln, wieviele Felder der Panzer zurückgelegt hat. Nun stehe ich aber auf dem Schlauch.

Ich habe die Enfernuung x/y, wie komme ich nun aber zu der Anzahl der zurückgelegten Felder ???

Kai
imac
20 Zoll
2,4 ghz
BlackJack

``laenge = 20`` hat in dem Code ohne GUI nichts zu suchen, da geht man einfach von einer Einheit aus.

Was soll die Funktion denn genau leisten? Eine Liste von Feldern, die den kürzesten Weg von Feld A nach Feld B darstellt? Da ist der A*-Algorithmus passend. Gewichtung der Felder ist erst einmal 1, später kannst Du dafür die benötigten Bewegungspunkte für die jeweiligen Feldtypen veranschlagen.
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

die Funktion soll die Entfernung des zurückgelegten Weges in Feldern OHNE Berücksichtigung der Art der Felder berechnen. Das ist gleichzeitig auch der kürzeste Weg. Ich schaue mir den "A" Algorithmus nachher einmal an.
Nach der Anzahl der Felder richtet sich dann die Vorlage duch eigene Bewegung.

laenge = 20 ???

Wie kann ich das denn ohne diese Angabe bewerkstelligen ?
Mir ist klar, dass "laenge = 20" später gar nicht benötigt wird, da
dies aus der GUI stammen wird.
Aber ich muss meinen bisherigen Code doch testen können, oder
wie würdest DU / IHR das vorgehen ?

Kai
imac
20 Zoll
2,4 ghz
BlackJack

Du willst doch keine Entfernung in "Luftlinie" haben, sondern die Anzahl der Felder, die als kürzester Weg zwischen zwei Feldern liegen. Und da zählt ein Feld eben als 1.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo derkai

Ich würde mit der Panzer-Klasse.noch warten Wir müssen auf BlackJacks Code-Schnipsel aufbauen. Dieser Code liefert uns eine Spielkplattform mit 10 * 10 also total 100 Punkte (das sind 100 Spielfeld-Objekte der Klasse Tile) die mittels 'x' und 'y' adressiert werden können. Dies sind nur Punkte und haben noch keine geometrische Form. Wir müssen die Klasse-Tile mit einem neuen Attribut dem ich den Namen 'panzer' gebe, erweitern. Später werden diesem Attribut 'panzer' ein Instanz-Objekt der jetzt noch nicht existierenden Klasse-Panzer zugewiesen. Für unser Beispiel hier weisen wir dem Attribut 'panzer' einen das ASCII-Zeichen '.' zu um zu sagen auf diesem Spielfeld hat es keinen Panzer (das Spielfeld ist noch leer). So können wir als nächtes die gute Idee von 'yipyip' mit einbeziehen und einmal die Panzerbelegung aller Spielfelder mit dem 'print-Befehl' als ASCII-Zeichen auf die Konsole ausgeben. Das müsste 10 Zeilen @ 10 Dezimalpunkte ergeben. Also es ist noch keines der Spielfelder von einem Panzer belegt.
Als nächstes können wir einigen Spielfeldern Panzer zuordnen. Hierfür nehmen wir die von 'yipyip' vorgeschlagenen ASCII-Zeichen 'O' und 'X' als zwei verschiedene Panzertypen.

Hier die Erweiterung der Klasse-Tile:

Code: Alles auswählen

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

    def __init__(self, name):
        """Konstruktor für die Klasse"""
        self.name = name 
        self.panzer = '.'
Nun kann ein Spielfeld nach einem darauf stehenden Panzer wie folgt abgefragt werden:

Code: Alles auswählen

print game_map[x, y].panzer
Ein Panzer wird wie folgt auf das Spielfeld gesetzt:

Code: Alles auswählen

game_map[x, y].panzer = 'O'
oder:

Code: Alles auswählen

game_map[x, y].panzer = 'X'
@derkai Könntest du einmal versuchen das Code-Schnipsel so zu erweitern, dass die Panzerbelegung der ganzen Spielplattform (Spielkarte) mit dem 'print-Befehl' auf die Konsole auszugeben. Am besten mit 'for' Schleifen.

Steht noch kein Panzer auf einem Spielfeld müsste dies wie folgt aussehen:

Code: Alles auswählen

..........
..........
..........
..........
..........
..........
..........
..........
..........
..........
@BlackJack Was meinst du zu diesem Veruch?

Gruss wuf :wink:
Take it easy Mates!
BlackJack

@wuf: Das funktioniert aber nur, wenn jede `Tile` in der Karte ein eigenes Objekt ist. Also muss man entweder 100 *verschiedene* `Tile`-Exemplate erzeugen, oder die Position des/der Panzer(s) anders speichern -- nicht in der Karte.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

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: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

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

ä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

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

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

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

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

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

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

funktoniert leider alles nicht ...

Kai
imac
20 Zoll
2,4 ghz
Antworten