Dictionary wird nicht ergenzt bzw verändert

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PILLE

Hallo liebe Leute

Ich habe ein ganz dickes Problem.
seit einiger Zeit programmiere ich in der Schule Python. Aufgabe war ein Conway game of live mit Donout world zu schreiben.
hier ist eine url mit einer Erklärung und einem Testprogramm leider ohne Donout world. Dies ist jedoch nicht weiter schlim. die Donout world sorgt ledentlich dafür das auch am rand auf der gegenüberligenden seite geschaut wird ob es nachbarn gibt.

so viel zur Aufgabe

ich habe nun also eine Klasse geschrieben die einige Methoden verwendet um das Spiel gemäß den Regeln zu realisieren. Dazu habe ich ein Dictionary verwendet. nur leider verändert sich das dictionary nicht. ich kann keine elemente Löschen und auch keins zufügen

Meine Klasse sieht wie folgt aus:

# -*_ coding: cp1252 _*_

from random import *
import copy

class GameOfLive:

# Initialisierung
def __init__(self):
self.__m_yalt = 0
self.__m_xalt = 0
self.__m_x = 0
self.__m_y = 0
self.__m_anz = 0
self.__m_fielddic = {}
self.__m_lastgenerationdic={}
self.__m_eingabe = 0

# setzen der ersten Zellen
def platzieren(self, anz):
self.__m_fielddic[5,3]='C'
self.__m_fielddic[4,4]='C'
self.__m_fielddic[3,5]='C'
self.__m_fielddic[4,6]='C'
self.__m_fielddic[5,7]='C'
self.__m_fielddic[6,6]='C'
self.__m_fielddic[7,5]='C'
self.__m_fielddic[6,4]='C'

# Nachbarn ermitteln
def nachbar(self, x,y):
self.__m_nachbar=[] for z in range (-1,2): for j in range (-1,2): if x!=x+z or y!=y+j: self.__m_nachbar.append([x+z,y+j]) return copy.copy(self.__m_nachbar)

def ersetzen(self, nachbar):
self.__m_nachbar=nachbar
for item in self.__m_nachbar : for z in range (0,2) : if item[z]<0 : item[z] = 9
if item[z] >9 : item [z]=0 return copy.copy(self.__m_nachbar)

# auswerten
def auswerten(self, nachbar):
self.__m_anz=0
for item in nachbar: if self.__m_lastgenerationdic.has_key(tuple(item)):
self.__anz+=1 return self.__m_anz

# wachsen
def wachse(self,anz,x,y):
if anz==3: if self.__m_lastgenerationdic.has_key((x,y))==False:
self.__m_fielddic[(x,y)]='C'

# sterben
def sterbe(self,anz,x,y):
if (anz < 2) or (anz > 3): if self.__m_lastgenerationdic.has_key((x,y)):
del self.__m_fielddic[(x,y)]

# Attribut hole Feld nach Außen geben
def holeFeld(self):
return copy.copy(self.__m_fielddic)


# Letzte gerneration in einem anderen dictionary speichern
def letztegerneration(self):
self.__m_lastgeneration=copy.copy(self.__m_fielddic)

#Testprogramm

if __name__ == '__main__':

gol=GameOfLive()
field={}
nachbar=[]
eingabe=0

anz=0
zahl=0
# platzieren der ersten zellen und bei Fehler abbrechen
gol.platzieren(zahl)

field=gol.holeFeld()
print 'Startkombination'
print
for z in range (0,100):
if z % 10 == 0 :
print
print field.get((z%10, z/10),' '),
print

gol.letztegerneration()

for i in range (0,100):
nachbar=gol.nachbar(i%10,i/10)
nachbar=gol.ersetzen(copy.copy(nachbar))
anz=gol.auswerten(copy.copy(nachbar))
gol.sterbe(anz,i%10,i/10)
gol.wachse(anz,i%10,i/10)

gol.holeFeld()
print 'naechste gerneration'
print
for z in range (0,100):
if z % 10 == 0 :
print
print field.get((z%10, z/10),' '),
print


soo sieht das programm also ungefair aus
in der Methode wachse passiert nichts und bei sterbe eben so wenig, obwohl der interpreter die Klasse und die Methoden ausführt. Auch die If. ich weiß einfach nicht mehr weiter

Kann mir jemand helfen? :cry:
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Könntest Du bitte erst mal den Code in Python-Tags setzen, damit die Einrückung erhalten bleibt. So ist das Lesen etwas mühsam :wink:

Gruß, mawe
PILLE
User
Beiträge: 8
Registriert: Mittwoch 23. Februar 2005, 15:38
Kontaktdaten:

okk erfolgt sogleich muss mich noch etwas zurecht finden

Code: Alles auswählen


class GameOfLive:

# Initialisierung
	def __init__(self):
		self.__m_yalt = 0
		self.__m_xalt = 0
		self.__m_x = 0
		self.__m_y = 0
		self.__m_anz = 0
		self.__m_fielddic = {}
		self.__m_lastgenerationdic={}
		self.__m_eingabe = 0

# setzen der ersten Zellen
	def platzieren(self, anz):		
        self.__m_fielddic[5,3]='C'
		self.__m_fielddic[4,4]='C'
		self.__m_fielddic[3,5]='C'
		self.__m_fielddic[4,6]='C'
		self.__m_fielddic[5,7]='C'
		self.__m_fielddic[6,6]='C'
		self.__m_fielddic[7,5]='C'
		self.__m_fielddic[6,4]='C'

# Nachbarn ermitteln
	def nachbar(self, x,y):
		self.__m_nachbar=[]
			for z in range (-1,2):
                for j in range (-1,2):
                    if x!=x+z or y!=y+j:
                         self.__m_nachbar.append([x+z,y+j])
                         return copy.copy(self.__m_nachbar)


	def ersetzen(self, nachbar):
		self.__m_nachbar=nachbar
		for item in self.__m_nachbar :		
			for z in range (0,2) :		
				if item[z]<0 :	
					item[z] = 9
				if item[z] >9 :	
					item [z]=0	
		return copy.copy(self.__m_nachbar)

# auswerten
	def auswerten(self, nachbar):
		self.__m_anz=0
		for item in nachbar:
            if self.__m_lastgenerationdic.has_key(tuple(item)):
                self.__anz+=1				
        return self.__m_anz

# wachsen
	def wachse(self,anz,x,y):
		if anz==3:	
            if self.__m_lastgenerationdic.has_key((x,y))==False:
                self.__m_fielddic[(x,y)]='C'								

# sterben
	def sterbe(self,anz,x,y):
		if (anz < 2) or (anz > 3):
            if self.__m_lastgenerationdic.has_key((x,y)):
                del self.__m_fielddic[(x,y)]		

# Attribut hole Feld nach Außen geben
	def holeFeld(self):
		return copy.copy(self.__m_fielddic)

# Letzte gerneration in einem anderen dictionary speichern
	def letztegerneration(self):
		self.__m_lastgeneration=copy.copy(self.__m_fielddic)



if __name__ == '__main__':

	gol=GameOfLive()
	field={}
	nachbar=[]
	eingabe=0
	zelle=0
	anz=0
	zahl=0
	
    gol.platzieren(zelle
    field=gol.holeFeld()
    print 'Startkombination'
    print
    for z in range (0,100):
        if z % 10 == 0 :
             print
        print  field.get((z%10, z/10),' '),
    print

    gol.letztegerneration()

    for i in range (0,100):
        nachbar=gol.nachbar(i%10,i/10)
        nachbar=gol.ersetzen(copy.copy(nachbar))
        anz=gol.auswerten(copy.copy(nachbar))
        gol.sterbe(anz,i%10,i/10)
        gol.wachse(anz,i%10,i/10)

    gol.holeFeld()
    print 'naechste gerneration'
    print
    for z in range (0,100):
        if z % 10 == 0 :
            print
        print field.get((z%10, z/10),' '),
    print
aber danke schon mal für das interesse :)
Theorie und Praxis sind in der Theorie das selbe, doch unterscheiden sie sich meist in der Praxis meilenweit
BlackJack

Ich blicke da nicht so ganz durch. Die Welt wird offensichtlich in einem Dictionary gehalten bzw. zweien um Zugriff auf die letzte Generation zu haben, aus der die jeweils aktuelle berechnet wird. Warum initialisierst Du einige Felder mit einer Zeichenkette ('C')? Ich hätte erwartet, das es sich um Zahlen handelt, die da verwaltet werden. Vergleichen von Zahlen und Zeichenketten geht in Python, bzw. das vergleichen von zwei beliebigen unterschiedlichen Typen, aber es wird nur garantiert, dass bei je zwei Typen immer das gleiche Ergebnis kommt. Also das Zahlen z.B. grundsätzlich "kleiner" sind als Zeichenketten. Das kann bei einem anderen Interpreter oder einer anderen Version andersherum sein.

Ich habe ganz stark das Gefühl Du willst C++ nach Python übertragen. Und das 1:1. Entferne bitte mal alle '__m_' Präfixe von Deinen Attributen. Wozu soll das gut sein?

Dann legst Du in der __init__()-Methode einige Attribute an, die sehr danach aussehen als sollten sie lokale Namen in Methoden sein.

Und im '__main__'-Code steckt Logik, die eigentlich in der Klasse sein sollte. Die sollte eine Methode haben, die ohne Parameter aufgerufen wird und den nächsten Schritt berechnet. So wie es jetzt da steht sind alle möglichen Daten nochmal ausserhalb der Klasse vorhanden. Du kopierst viel zu viel herum. Darum steige ich auch nicht ganz durch was genau passiert.

Noch ein Wort zu Python und der üblichen C++/Java Paranoia: Es ist okay Attribute einfach nach aussen zugänglich zu machen und darauf zu vertrauen, dass sie niemand von aussen "kaputt" macht. Wenn man etwas als privat markieren möchte, dann reicht ein einzelner Unterstrich, also zum Beispiel '_foo' als Name. Da kann zwar jeder rankommen, aber es ist ein eindeutiges Zeichen, das man es von aussen nicht benutzen soll.
PILLE
User
Beiträge: 8
Registriert: Mittwoch 23. Februar 2005, 15:38
Kontaktdaten:

Also, Das mit dem 'C' füllen muss ich laut Aufgabe so machen. ist aber auch eigedlich nicht das Problem.

Mit __ mach ich Variblen doch strong Privat? Laut Erfahrung ist es sicherer es so zu machen.. aber anderes ist auch ok

das m_ steht für member. So bennen ich alle Attribute

Ich Programmiere gerne C++ und ich mag Python noch nicht besonders, deshalb kann es durchaus sein das ich einiges übertrage..

Zur Erklärung

Ich speicher nur die Zellen die schon vorhanden sind mit eine 'C' alle anderen brauch ich nicht speichern.
Dann finde ich mit nachnbar() herraus, welche Koordinaten die benachbarten sind. Für die Donout Welt werden die gegenüberliegenden Ränder 'ersetz' und ich kann mit has.key prüfen ob sich an der Stelle ein Nachbar(Zelle) befindet.

so weit so gut

die Anzahl der Nachbar stimmt auch und wird richtig ausgewertet.
allerdings wird das Dic. nicht um den neune Wert erweiter.

Die Copys dienen dazu nicht die Referenzen zu verändern. Denn wenn die Letzte und die Neue Generation die selben Referenzen benutzen,ist es sinnlos da beide dictionarys verändert werden.

Nachbar kopiere ich nur zur Sichheit weil einemal mehr schadet meiner Meinung bei einer Sprache wie Python nicht da es ja den Gagbage collector gibt.

Ich hoffe das hilft noch ein bischen..

cu PILLE
Theorie und Praxis sind in der Theorie das selbe, doch unterscheiden sie sich meist in der Praxis meilenweit
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!
PILLE hat geschrieben: Mit __ mach ich Variblen doch strong Privat?
Naja, irgendwie schon, aber man kann trotzdem von aussen auf sie zugreifen (wenn man weiss wie :wink:)
Die Namenskonventionen sind aber hier nebensächlich.

Wenn mich nicht alles täuscht, kann ersetzen nicht so funktionieren wie Du das willst. Mal ein einfacheres Beispiel:

Code: Alles auswählen

nachbar = [1,2,3]
for item in nachbar:
    if item == 1:
        item = 100
print nachbar     # -> [1,2,3] nix verändert
for i in range(len(nachbar)):
    if nachbar[i] == 1:
        nachbar[i] = 2
print nachbar   # -> [2,2,3] jetzt passts
Gruß, mawe
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hi

ob C++ oder Python, manche Dinge betreffen einfach das Design und da solltest Du schon noch ein paar Dinge ändern - weil Du Dir auf Dauer das Leben unnötig schwer machst und dann auch nicht so viel Spaß beim Programmieren hast. Was Du Dir genau zu Herzen nimmst ist natürlich Deine Sache, aber die Anmerkungen von BlackJack zum Thema __main__ haben Hand und Fuß.

Außerdem: Die Funktion platzieren erwartet "anz", damit machst Du aber nichts. Und diese Funktion wird auch nur einmal bei der Erstellung der ersten Instanz aufgerufen. Na? Wie wäre es Du schreibst all dieses in __init__, ggf. kannst Du ja auch mit verschiedenen Paramteren verschiedene Initialisierungen machen, damit das Feld nicht immer gleich aussieht. Und schließlich kannst Du das Füllen der ersten Felder auch mit weniger Codezeilen machen.

In nachbar() deklarierst Du __m_nachbar, was aber in __init__ gar nicht auftaucht. Es ist manchmal geschickter, wenn Du in __init__ alle Attribute deklarierst und deutlich machst, worum es sich handelt - dann kannst Du in einem halben Jahr Dein Programm immer noch lesen. (Was bei einer Hausaufgabe vielleicht nicht so kritisch ist ;-).)

Ähnliches gilt in auswerten(). Muß __anz überhaupt ein Attribut der Klasse sein?

Und jetzt wird es ganz komisch: Wozu soll field gut sein? Warum nicht alles mit Methoden von GameOfLive machen?

Ob die Logik überall stimmt wage ich außerdem zu bezweifeln: Am besten Du konttrollierst Schritt für Schritt was wo herauskommt - stimmt überall die Anzahl der Nachbarn? Wird richtig ersetzt? usw. Und das für jede Generation. Dann wirst Du schon auf die Lösung kommen.

Tut mir leid, wenn das alles jetzt sehr hart klang. Das sollte es nicht sein. Ich sehe auch, daß das keine einfache Hausaufgabe ist. Na, und während ich hier so vor mich hin tippte hat der mawe schon einen Teil der Lösung gegeben - ist doch toll, oder?

Gruß,
Christian
BlackJack

PILLE hat geschrieben:Also, Das mit dem 'C' füllen muss ich laut Aufgabe so machen. ist aber auch eigedlich nicht das Problem.


War ein Denkfehler meinerseits. Ich hatte eine Variante im Hinterkopf, wo die Zellen nicht leben oder tot sind, sondern einen Wert haben, wie lebendig sie sind. Da kann man schöne bunte Bilder draus machen.
Mit __ mach ich Variblen doch strong Privat? Laut Erfahrung ist es sicherer es so zu machen.. aber anderes ist auch ok
Kommt auf die Definition von "strong" an. Man kommt da immer noch dran, wenn man will. Das mit der Erfahrung stimmt nur wenn man davon ausgeht, das die Leute einfach Attribute von Klassen verändern, die ihnen nicht "gehören". Das macht man nicht. Dann gibt es auch keine Probleme.

Ein Problem mit den '__' ist, dass sie auch für Unterklassen nicht sichtbar sind. Das kann sehr einschränkend sein.
das m_ steht für member. So bennen ich alle Attribute
Warum? Bei C++ ist die Begründung, dass man Attribute und lokale Variablennamen besser auseinanderhalten kann. Bei Python müssen Attribute immer mit 'self.' angesprochen werden, das heisst ein zusätzliches 'm_' ist überflüssig. Ausserdem sollten Methoden nicht so lang werden und/oder so viele lokale Namen enthalten, dass man durcheinander kommen könnte.
die Anzahl der Nachbar stimmt auch und wird richtig ausgewertet.
allerdings wird das Dic. nicht um den neune Wert erweiter.
Die 'nachbar()'-Methode in Deinem Code oben funktioniert so nicht.
Die Copys dienen dazu nicht die Referenzen zu verändern. Denn wenn die Letzte und die Neue Generation die selben Referenzen benutzen,ist es sinnlos da beide dictionarys verändert werden.
Klar brauchst Du ein eigenes Dictionary für den alten und den neuen Schritt, aber Du kopierts alles mögliche, überall. Und auch für die beiden Dictionaries braucht man kein copy, man kann einfach ein neues, leeres erstellen und die Zellen dann rüberkopieren die noch leben und die hinzufügen die neu sind.
Nachbar kopiere ich nur zur Sichheit weil einemal mehr schadet meiner Meinung bei einer Sprache wie Python nicht da es ja den Gagbage collector gibt.
Es macht den Code aber schwer durchschaubar. Vor allem wenn sich in Deinem Fall etwas nicht ändert, was sich aber ändern sollte, dann könnte es ja sein, dass Du auf irgendeiner Kopie arbeitest, die dann "verloren geht".
PILLE
User
Beiträge: 8
Registriert: Mittwoch 23. Februar 2005, 15:38
Kontaktdaten:

ich sehe ein was mawe sagt, dass ist wohl soo.. aber es funktioniert auch so wie ich das gemacht habe, weil in mein Fall item nur eine Refernez der Liste Nachbar ist, da diese verschachtelt ist und der Interpreter keine Kopie wie bei copy.copy anlegt. Vorrausgeseztz ich hbae alles verstanden was mein Leherer mir vorbrabbelt..

zu Christian.. ich habe die Methoden zum testen vereinfacht. normalerweise lasse ich den Benutzer eingeben, wieviel Zellen er setzten möchte und wieviel Generationen es geben soll. Deshalb die anz in der Methode.

Mein design sehen ich ein kann euch gerne mal die mail addi vn einem "leerer" geben.. dagegen sieht meins gut aus find ich *gg* nein aber spaß am Rand.. hat einer von euch eine Page wo dazu was da steht?

Und das debuggen habe ich auch schon gemacht bis zu den zwei Methoden sterbe und wachse funktioniert alles einwandfrei.. die Werte sind alle richtig bis dahin.. und dann wird das dictionary nicht verändert.. ich verstehe das nicht..

und falls dich das interessiert Das ist die gewöhnkliche platzieren

Code: Alles auswählen

	def platzieren(self, anz):
		i=0
# erste Zelle plazieren
		self.__m_x = randint(0,9)
		self.__m_y = randint(0,9)
		
		self.__m_fielddic [self.__x,self.__y] = 'C'
		self.__m_xalt=self.__x
		self.__m_yalt=self.__y
# weitere Zellen plazieren
		if anz-1>0:
			for i in anz
				self.__m_x = randint(-1,1)
				self.__m_y = randint(-1,1)

				if self.__m_x == 0 and self.__m_y == 0 :
					self.__m_x = 1
				if self.__m_yalt == self.__m_y :
					self.__m_y = self.__m_y* -1
				if self.__m_xalt == self.__m_x :
					self.__m_x = self.__m_x*-1

				if (((self.__m_xalt+self.__m_x<10) and (self.__m_yalt+self.__m_y<10)) and
					((self.__m_xalt+self.__m_x)>=0 and (self.__m_yalt+self.__m_y)>=0)) :
					
					if (((self.__m_xalt+self.__m_x),(self.__m_yalt+self.__m_y)) in self.__m_field) == 0 :
						if self.__m_fielddic.has_key(((self.__m_xalt+self.__m_x),(self.__m_yalt+self.__m_y)))==False :
							self.__m_fielddic[(self.__xalt+self.__x,self.__yalt+self.__y)] = 'C'
							i+=1
		else:
			return -4
das Nachbar gar nicht in der init steht ist mir gar nicht aufgefallen.. na ja ich ergänze es da gleich mal..
bin mal gespannt ob es dann besser oder schlechter geht..
Vielleicht amcht dann auch das was mawe gesagt hat Sinn weiß zwar nichtw arum es dann anerder funktionieren sollte aber mal schaun.. man weiß ja nie.. und wennn es nicht geht gebe ich einem von euch die Schuld :)

eins meiner Problem ist auch das unser Lehere nur die Hälfte der Sachen erklärt die bei Python funktioieren und ich mehr mit Nachschlagen beschäftigt bin als mit Proggen, aber das ist ja nebensache. Er hat ja auch gerade erst angefangen..

okk seh gerade noch einen beitrag.. ich werde das mal ändern und dann die aktuelle varriante auch hier her einstellen wenn es ok ist.. vielelicht finde ich dann den Fehler auch. das mit den Kopien leutet ein .. und als C programmierin bin ich nicht drauf gekommen jedesmal eine neues dict anzulegen.. macht aber auch sinn.. danke schon mal

:wink: PILLE
Theorie und Praxis sind in der Theorie das selbe, doch unterscheiden sie sich meist in der Praxis meilenweit
PILLE
User
Beiträge: 8
Registriert: Mittwoch 23. Februar 2005, 15:38
Kontaktdaten:

soo.. ich habes ich habe es wirklich gelöst

ein Mist das es in dem Sinne keine Sicherheit gibt wenn man einen Variable macht, das der Interpreter da nicht meckert wenn man sie nicht gemacht gemacht hat.

n aja besten dank.. suoper lieb das ihr mir so geholfen habt.. aber schön wäre es wenn irh trtzdem noch mal ausplaudert, wo man eine definition für odendlichen stil in Python findet.. in meinem Buch steht da nicht so viel von..

Noch mal Tausend dank *alle mal knuddel*

heute ist ein erfolgreicher tag :idea:

danke danke dank *happy bin*
Theorie und Praxis sind in der Theorie das selbe, doch unterscheiden sie sich meist in der Praxis meilenweit
BlackJack

Wenn mit Stil hier der Entwurf gemeint war, was in eine Klasse gehört, was Attribut und was lokale Variablen sein sollten, dann ist das keine reine Python-Frage. Das Du in jeder Methode vor so ziemlich alle Variablen 'self.__m_' setzt, wäre auch in C++ und Java sehr fragwürdig. Zum Beispiel Dein `platzieren()` sieht grauenvoll aus. Ist Dir die ganze Tipperei nicht auf die Nerven gegangen!? (Das sieht übrigens alles sehr kryptisch aus)

Ich habe heute auch mal ein kleines GameOfLife gebastelt. Als erstes muss man sich Fragen stellen, was für Daten gehören in so eine Klasse, also was muss über die Welt in jeder Methode bekannt sein. Ich bin auf 4 Sachen gekommen, die Höhe und Breite, ein `Set` für die lebenden Zellen und eine Uhr (`clock`) die die Schritte zählt die schon berechnet wurden. Also nur 4 Namen vor die ein 'self.' kommt.

Dann ist das berechnen des nächsten Schrittes etwas, was in die Klasse gehört, weil man mit Daten arbeitet, die zu dieser Klasse gehören. Wenn man das von aussen macht, also Daten rausholen, bearbeiten und dann wieder in das Objekt zurückschreiben, dann umgeht man den Grund überhaupt eine Klasse zu benutzen. Die sind dazu da, Daten und dazugehörigen Code zu einer Einheit zusammenzufassen.

Das waren jetzt pythonunabhängige Stilfragen. Ob's irgendwo eine gute Zusammenfassung zu Python-Stil gibt weiss ich nicht.

Ich gehe in meinem Code in einem Schritt nicht über alle Felder der Karte, sondern nur die, in denen wirklich etwas passieren kann, also die Zellen die leben und deren Nachbarfelder. Ansonsten ist der Algorithmus ziemlich "straightforward" umgesetzt. Ich habe noch eine ASCII Animation eingebaut, damit man auch was sieht -- die funktioniert aber nur richtig wenn das "Terminal" ANSI Escape-Sequenzen unterstützt. Ich weiss nicht wie das unter Windows aussieht!?

Code: Alles auswählen

#!/usr/bin/env python

import time
from sets import Set as set

class GameOfLife:
    """Conway's *Game of Life*"""
    
    neighbour_positions = [(x, y) for x in xrange(-1, 2)
                                  for y in xrange(-1, 2)
                                  if not x == y == 0]
    
    def __init__(self, width, height, cells):
        self.width = width
        self.height = height
        self.cells = set(cells)
        self.clock = 0
    
    def __len__(self):
        return len(self.cells)
    
    def __str__(self):
        worldmap = [['.'] * self.width for dummy in xrange(self.height)]
        for x, y in self.cells:
            worldmap[y][x] = '#'
        return ('Clock: %d\n' % self.clock
                + '\n'.join([''.join(row) for row in worldmap]))
    
    def _is_within_world(self, field):
        x, y = field
        return 0 <= x < self.width and 0 <= y < self.height
    
    def _neighbour_fields(self, field):
        x, y = field
        for delta_x, delta_y in GameOfLife.neighbour_positions:
            neighbour_field = (x + delta_x, y + delta_y)
            if self._is_within_world(neighbour_field):
                yield neighbour_field
    
    def _fields_of_interest(self):
        fields = set(self.cells)
        for cell in self.cells:
            fields.update(self._neighbour_fields(cell))
        return fields
    
    def step(self):
        new_cells = set()
        
        for field in self._fields_of_interest():
            alive_neighbours = sum(map(int, [(neighbour_field in self.cells)
                                             for neighbour_field
                                             in self._neighbour_fields(field)]))
            if field in self.cells:
                # Cell `field` is alive.
                if 2 <= alive_neighbours <= 3:
                    new_cells.add(field)
            else:
                # Cell `field` is dead.
                if alive_neighbours == 3:
                    new_cells.add(field)
        
        self.cells = new_cells
        self.clock += 1
    
    def run(self, callback=None, steps=1000000):
        while len(self) and self.clock < steps:
            self.step()
            if callback is not None:
                callback(self)


if __name__ == '__main__':

    def display(obj):
        print '\033[H%s' % obj  # Cursor home and `obj` as string.
        time.sleep(0.5)

    game = GameOfLife(10, 10, ((5, 3), (4, 4), (3, 5), (4, 6),
                               (5, 7), (6, 6), (7, 5), (6, 4)))

    print '\033[2J'     # Clear screen.
    try:
        game.run(display)
    except KeyboardInterrupt:
        pass
PILLE
User
Beiträge: 8
Registriert: Mittwoch 23. Februar 2005, 15:38
Kontaktdaten:

uii was ist das denn???? wenn ich das so ähnlich mache sagt der wo ich mir das gezogen haben *dumm aus der wäsche schau* was alles bei Python geht*wunder*
:shock:

Besten dank auf jden fall für diese lehrreichen stunden hier.. ich werde jetzt noch das notwendig protokoll schreiben wenn ich da noch ein bischen verändert habe *einige sachen raussuchen werd*

Besten dank nochmal meine Note ist gerette *alle mal drück die geholfen haben*
Theorie und Praxis sind in der Theorie das selbe, doch unterscheiden sie sich meist in der Praxis meilenweit
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Ich habe noch eine ASCII Animation eingebaut, damit man auch was sieht -- die funktioniert aber nur richtig wenn das "Terminal" ANSI Escape-Sequenzen unterstützt. Ich weiss nicht wie das unter Windows aussieht!?
Miserabel, wie so oft (nur readline ist schlimmer). Man braucht sowas wie Wconio (hab mal Binaries für Py2.4 gemacht, das Modul ist recht nett) oder console.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Geht sowas wirklich nicht in einer normalen "DOS-Eingabeaufforderung"? Unter'm echten MS-DOS gab's dafür einen Treiber, der dabei war (ANSI.SYS). Es geht nicht um eine API wie die, die Du verlinkt hast, sondern nur darum, dass die Escape-Sequenzen vom "Terminal" interpretiert werden. Aber naja, wir reden von Windows... :?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Geht sowas wirklich nicht in einer normalen "DOS-Eingabeaufforderung"? Unter'm echten MS-DOS gab's dafür einen Treiber, der dabei war (ANSI.SYS). Es geht nicht um eine API wie die, die Du verlinkt hast, sondern nur darum, dass die Escape-Sequenzen vom "Terminal" interpretiert werden. Aber naja, wir reden von Windows... :?
Ja, Ansi.sys ging ja auch noch bis Dos Me, aber in der NT Serie geht das nicht mehr. Also ich würde deswegen mir Windows 98 nicht wieder antun.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten