verdammt, ich kapier es einfach nicht

Fragen zu Tkinter.
BlackJack

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

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

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

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

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!
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?
Antworten