verdammt, ich kapier es einfach nicht

Fragen zu Tkinter.
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

schon einmal danke, ich guck es mir an :

trotzdem noch einmal meine Frage :
Wie kann ich aus einer For Schleife Namen und Instanzierungen einer Klasse Hexfeld erreichen.
Wie muss ich meine For Schleife ändern, damit ich nachher über den Namen einer Instanz eine Methode aufrufen kann ?

Kai

Code: Alles auswählen

from math import sqrt

class Hexfeld (object) :

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

        laenge = 20

        self.xpos = xpos
        self.ypos = ypos

     
    def berechne (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)

x = 0
y = 0


for x in ("a","b","c") :

    for y in ("d","e","f") :
        feld = x+y
        feld = Hexfeld(20,10)
        print feld.berechne(20,10), feld
"cf".berechne(20,10)

imac
20 Zoll
2,4 ghz
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

from math import sqrt

class Hexfeld (object) :

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

        laenge = 20

        self.xpos = xpos
        self.ypos = ypos

     
    def berechne (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)

x = 0
y = 0

felder = {}
for x in ("a","b","c") :
    for y in ("d","e","f") :
        name = x+y
        feld = Hexfeld(20,10)
        print feld.berechne(20,10), feld
        felder[name] = feld
felder["cf"].berechne(20,10)
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

ok, ich wäre bereit für den nächsten Schritt : die Ermittlung der Nachbarfelder eines Hexagon, um darüber dann Entfernungen zum Gegner berechnen zu können.

In einem meiner schlauen Bücher steht, dass man dabei wie folgt vorgehen könnte :

x1 x2 x3 x4
x1 0 1 1 0
x2 1 0 1 0
x3 1 1 0 1
x4 usw......

dann bildet man eine Liste der Elemte die miteinander verbunden sind :
L = [{0,1,1,0),(1,0,1,0), usw ....)]

Ich hoffe Ihr könnt nachvollziehen was ich meine.

Ich könnte mir dann eine Suche überlege, wie die Nachbarfelder miteinander verbunden sind. Den von BLACKJACK vorgeschlagenen A - Algorythmus habe ich zwar nicht verstanden, aber ich habe dann noch ein weiteres Problem :

Es wären Unmengen von Daten.

Habt Ihr vielleicht eine bessere Idee ?

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

keinen Code bitte, ich würde gerne selber grübeln, mir fehlt aber das
Handwerkszeug.

Kai
imac
20 Zoll
2,4 ghz
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@derkai: Die Struktur die du suchst nenn sich "Graph". Den kannst du entweder als Adjazenzmatrix darstellen, so wie du es gerade machst, oder du speicherst an jedem Knoten (in deinem Fall ein Feld) die maximal sechs Nachbarn dex Hexagons. Beide Strukturen musst du natürlich automatisch generieren, falls du das mit "Unmenge von Daten" meinst.

Wenn Dir der A*-Algorithmus noch zu unübersichtlich ist, dann wirf einen Blick auf den Dijkstra-Algorithmus. Das ist ein Spezialfall das A* mit der Heuristik h(x) = 0.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo derkai

Sorry meine idiotische Frage. Warum musst du die benachbarten Felder kennen, wenn der feindliche Panzer z.B. 20 Felder neben dem eigenen steht. Jedes Feld hat doch seine exakte Zentrum-Koordinate so musst du doch nur wissen auf welchem Feld der feindliche Panzer steht.

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

den Algorythmus schaue ich mir an, vielen Dank

@wuf
die Frage ist sogar sehr gut.

ich dachte zuerst auch, dass ich mit der Entfernung von xy von Freund zu Gegner weiterkommen würde - leider ist dem nicht so, da die Entfernung nicht der Anzahl der Felder entspricht.

Wie würdest Du denn sonst die Anzahl der Felder bestimmen ?

Nach dem von blackjack vorgeschlagenen Prinzip hatte ich es so verstanden, dass es um Knoten und Seitenlängen geht.
Daher auch meine Idee "Graph".
Dem zu Folge habe ich den code jetzt auch so geändert, dass ich auf die Angabe von Zeilen- und Feldnr. verzichten wollte und einfach eine Durchnummerierung von 1 ... vorgenommen habe.
Wenn ich nun aber alle und knapp 660 Felder so mit Knoten verbinden möchte, werde ich wahrscheinlich eine riesen "Latte" von Liste erhalten.
Meine Befürchtungen gehen dahin, dass die Performance leiden wird.
Das merke ich ja sogar schon jetzt, wenn ich mir die hexliste (also die Liste aller xy Koordinaten aller Hexfelder) am Bildschirm ausgeben lassen möchte.

Gruß
derkai

Wie gesagt, ich bin für alle Vorschläge offen.
imac
20 Zoll
2,4 ghz
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Deshalb bietet es sich ja an, an einem Feld alle Knoten anzugeben die man erreichen kann. Das sind bei einem Hexagon nicht mal 6*n Einträge, wenn n die Anzahl der Felder ist. Auch eine Adjazenzliste mit 660 Knoten ist noch nicht all zu groß. Das sind um die 200000 Einträge, da du nur 660^2/2 Felder benötigst, wenn die Abstände symmetrisch sind. Am einfachsten ließe sich das wohl in einem Dictionary ablegen, mit den Schlüsseln der Form (a, b) mit a<=b, wobei a und b die IDs der Felder sind.

Aber mach Dir über die Performance zunächst nicht all zu viele Gedanken. Am Ende kannst du zur Not noch daran drehen, zu Beginn des Projekts macht es aber keinen Sinn.

P.S.: Es heißt Algorithmus, sogar im Englischen kommt kein y vor ;-)
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

jetzt muss ich aber EyDu noch einmal fragen.

Meinst Du meine Idee des Graph zu verfolgen und eine Liste aller miteinander verbundenen Felder zu erstellen, oder exakt für jedes Feld meine bestehendes Dicionary um die Angabe der jeweiligen Nachbarfelder mit aufzunehmen ?

Also :
- eigene Liste der Knotenpunkte aller Felder
- oder bestehende Liste je Feld um die Angabe der Nachbarfelder zu
erweitern ?

Kai
imac
20 Zoll
2,4 ghz
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Jedes Hexagon bekommt einfach eine Liste von seinen Nachbarn:

Code: Alles auswählen

h0 = Hex()
h1 = Hex()
h2 = Hex()
h3 = Hex()

#h0 hat Nachbarn h1 und h2
h0.neighbours = [h1, h2]

#h1 hat Nachbarn h0, h2 und h3
h1.neighbours = [h0, h2, h3]

#h2 hat Nachbarn h0 und h3
h2.neighbours = [h0, h3]

#h3 hat Nachbarn h1 und h2
h3.neighbours = [h1, h2]
Der Aufbau enthält zwar ein wenig Redundanz, aber es lässt sich gut damit arbeiten.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo derkai

Ich nehme an du hast dein Battle-Game-Projekt noch nicht an den Nagel gehängt? :lol:

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

nein, nein - ich bin fleissig dran -

es gäb da allerdings wieder ein weiteres kleines Problem :

ich habe eine Liste mit sechs Elementen :

[0.0, 0.0, 80.0, 120.0, 0.0, 0.0]

und brauche den Index des kleinsten Elementes, was größer
als Null ist.

Ich habe mir dazu die Funktion min angeschaut.
Die gibt mir natürlich aber immer die null zurück.

Kann man der Funktion min beibringen, dass sie das kleinste
Element, was größer als null ist zurückgeben soll ?

Kai
imac
20 Zoll
2,4 ghz
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

derkai hat geschrieben:es gäb da allerdings wieder ein weiteres kleines Problem :

ich habe eine Liste mit sechs Elementen :
[0.0, 0.0, 80.0, 120.0, 0.0, 0.0]
und brauche den Index des kleinsten Elementes, was größer als Null ist.

Code: Alles auswählen

>>> alt = [0.0, 0.0, 80.0, 120.0, 0.0, 0.0]
>>> neu = sorted(list(set(alt)))
>>> mini = neu[0] if abs(neu[0])>0.001 else neu[1]
>>> mini
80.0
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Einmal den Werte und einmal den Index:

Code: Alles auswählen

>>> l = [0.0, 0.0, 80.0, 120.0, 0.0, 0.0]
>>> min(x for x in l if x>0)
80.0
>>> min(i for (i,x) in enumerate(l) if x>0)
2
>>> 
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ups, den Index hatte ich vergessen.
Also dann noch eine Zeile ergänzen:

Code: Alles auswählen

alt = [0.0, 0.0, 80.0, 120.0, 0.0, 0.0]
neu = sorted(list(set(alt)))
mini = neu[0] if abs(neu[0])>0.001 else neu[1]
mini_index = alt.index(mini)
@EyDu:
Da hier mit Fließkommawerten gearbeitet wird, ist ein "x>0" nicht unproblematisch. Vielleicht sollte man ein "Epsilon" einbauen.

@derkai:
Im Übrigen ist die Aufgabenstellung nicht eindeutig: Was ist, wenn es mehrere gleiche Werte gibt, die alle die Bedingung "der kleinste Wert größer als Null" erfüllen? Brauchst du dann ALLE Indizes oder nur EINEN dieser Indizes und wenn letzteres zutrifft: Welchen dann?
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

die Liste spiegelt die Entfernung aller Nachbarfelder eines Feldes X
zu einem Zielfeld wieder. Die Entfernungen belaufen sich auf fast 8 Stellen nach dem komma. Es dürfte nicht vorkommen, dass die Liste gleiche Entfernungen / Elemente enthält.

Habt Dank.

Ich werde Euch bald mal meine neuen Ideen zeigen können.

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

EyDu hat geschrieben:Einmal den Werte und einmal den Index:

Code: Alles auswählen

>>> l = [0.0, 0.0, 80.0, 120.0, 0.0, 0.0]
>>> min(x for x in l if x>0)
80.0
>>> min(i for (i,x) in enumerate(l) if x>0)
2
>>> 

das verstehe ich leider noch nicht :
min ( x for x in l if x > o)

grob übersetzt heisst das doch :
- for x in l
gehe die Liste Element für Element durch
- if x > 0
heisst das : nimm nur das Element, dass gößer null ist ???
- x
aber was macht das x vor dem for ???

Kai
imac
20 Zoll
2,4 ghz
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ach, meine Variante mit den Indizes funktioniert gar nicht, das passt nur zufällig bei der Liste. Das hier sollte gehen:

Code: Alles auswählen

min([(i,x) for (i,x) in enumerate(l) if x>0], key=operator.itemgetter(1))
@derkai: Deine Ausführungen sind so weit schon richtig. Mit dem Ausdruck wird ein Generator erzeugt, das hat mit der min-Funktion erst mal nichts zu tun. Oben im Code ist das gleiche noch mal als list comprehension. Das "x" gibt an, was in die Liste mit aufgenommen wird, bzw. in den Generator.

@numerix: Wenn die Anforderung größer 0 lautet, dann gibt es keine Probleme ohne ein Epsilon. Außerdem lässt 0 sich richt gut binär darstellen ;-) Falsch ist allerdings in diesem Fall deine Verwendung von abs ;-)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

EyDu hat geschrieben:@numerix: Wenn die Anforderung größer 0 lautet, dann gibt es keine Probleme ohne ein Epsilon. Außerdem lässt 0 sich richt gut binär darstellen ;-) Falsch ist allerdings in diesem Fall deine Verwendung von abs ;-)
Ja, die "Anforderungen". Fakt ist doch, dass hier Fließkommazahlen im Spiel sind und ich nicht weiß, wo die Nullen herkommen. Falls die mal bei irgendeiner Rechnung ausgepuckt wurden (und nur noch theoretisch 0 sind) nützt mir die "gute Binärdarstellung der Null" gar nichts, weil eben nicht mehr Null steht, wo Null stehen sollte. Insofern ist man mit eine "Unschärfeprüfung" immer auf der sicheren Seite.

Was an dem abs() falsch sein soll, sehe ich nicht. :?:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Es macht einfach keinen Sinn in ein Problem mit so wenig Kontext etwas hineinzu interpretieren. Und mit Unschärfe ist man nicht immer auf der sicheren Seite: entstehen die Zahlen aus einer Multiplikation mit kleinen Zahlen und mit der Bedingung größer 0 willst du nur an das Vorzeichen ran, dann ist ein abs einfach falsch. Man kann sich also sonst was für Sonderfälle einfallen lassen.

Zu dem abs aus meinem letzten Thread:

Code: Alles auswählen

>>> alt = [0.0, 0.0, 80.0, 120.0, -40.0, 0.0]
>>> neu = sorted(list(set(alt)))
>>> mini = neu[0] if abs(neu[0])>0.001 else neu[1]
>>> print mini
-40.0
Antworten