Hallo zusammen und vielen Dank für die vielen Antworten.
Im Speziellen habe ich das Problem beim Erstellen eines Scoreboards für mein Spiel Snake.
Ich hänge jetzt einfach mal die gesamte Klasse hier rein um das eigentliche Problem verständlicher darzustellen.
Code: Alles auswählen
class Scoreboard():
""" Create a scroeboard and saves the values in a txt-file.
It also shows actual score information in the game window.
points for actions:
level_solved = 10000
eat_apple = 1000
command_sent = 100
speed_index = (slow=100, medium=250, fast=500, ultra=1000)
time passed in s = 1 x speed_index
"""
def __init__(self,spielfeld,snake,canvas,scrollbox,player_name):
self.spielfeld = spielfeld
self.snake = snake
self.canvas = canvas
self.scrollbox = scrollbox
# total data for player saved in the db
self.levels_solved = 0
self.apples_eaten = 0
self.commands_sent = 0
self.total_time_passed = 0
self.total_points = 0
# data for actual level shown in the game window
self.player_name = player_name
self.act_level = 0
self.time_passed = 0
self.act_points = 0
# other variables
self.time_level_start = 0
self.time_level_end = 0
# database
self.point_db = { 'level_solved': 10000,
'eat_apple': 1000,
'command_sent' : 100,
'speed_index_slow' : 100,
'speed_index_medium' : 250,
'speed_index_fast' : 500,
'speed_index_ultra' : 1000,
}
self.scoreboard_db = { self.player_name : [self.levels_solved, self.apples_eaten, self.commands_sent,
self.total_time_passed, self.total_points]
}
self.load_db_file()
#for item in self.scoreboard_db:
# print('scoreboard_db:','player:',item,'stats:',self.scoreboard_db[item] )
#print('init class Scoreboard done')
def load_db_file(self):
try:
scoreboard_file = open("snake_scoreboard.txt", "r")
liste = scoreboard_file.read().splitlines()
scoreboard_file.close()
if liste:
#print('liste:', liste)
for item in liste:
temp = item.split(" ")
#print('temp =',temp)
self.scoreboard_db[temp[0]] = [temp[1],temp[2],temp[3],temp[4],temp[5]]
else:
self.create_db_file()
except:
print('===> no scoreboard file found. It will be created now!')
self.create_db_file()
def create_db_file(self):
try:
scoreboard_file = open("snake_scoreboard.txt", "w")
print('----------------------------')
for line in self.scoreboard_db:
if line: # dont create empty name entrys in scoreboard_file
temp = self.scoreboard_db[line]
out_line = "{0:s} {1:d} {2:d} {3:d} {4:d} {5:d}\n".format(line,temp[0],temp[1],temp[2],temp[3],temp[4])
print("{0:s} {1:d} {2:d} {3:d} {4:d} {5:d}".format(line,temp[0],temp[1],temp[2],temp[3],temp[4]))
#print(out_line)
scoreboard_file.write(out_line)
print('----------------------------')
scoreboard_file.close()
except:
print('===> scoreboard file could not be created!')
def save_player(self):
try:
scoreboard_file = open("snake_scoreboard.txt", "a")
print('----------------------------')
out_line = "{0:s} {1:d} {2:d} {3:d} {4:.3f} {5:d}\n".format(self.player_name,self.levels_solved,self.apples_eaten,self.commands_sent,self.total_time_passed,self.total_points)
print("{0:s} {1:d} {2:d} {3:d} {4:.3f} {5:d}".format(self.player_name,self.levels_solved,self.apples_eaten,self.commands_sent,self.total_time_passed,self.total_points))
scoreboard_file.write(out_line)
print('----------------------------')
scoreboard_file.close()
except:
print('===> saving player data to scoreboard_file could not be done!')
def new_game(self):
# total data for player saved in the db
self.levels_solved = 0
self.apples_eaten = 0
self.commands_sent = 0
self.total_time_passed = 0
self.total_points = 0
# data for actual level shown in the game window
self.act_level = 1
self.time_passed = 0
self.act_points = 0
# other variables
self.time_level_start = 0
self.time_level_end = 0
def next_level(self):
# data for actual level shown in the game window
self.act_level += 1
self.time_passed = 0
self.act_points = 0
# other variables
self.time_level_start = 0
self.time_level_end = 0
def level_summary(self):
print('_____level summary------------------------------')
if self.act_level != self.levels_solved:
print('_____actual level:',self.act_level,'===>>> failed !!!' )
else:
print('_____levels solved:',self.levels_solved )
print('_____total apples eaten:', self.apples_eaten)
print('_____total commands sent:', self.commands_sent)
print('_____time played this level:', self.time_passed)
print('_____total time:', self.total_time_passed)
print('_____points gained this level:', self.act_points)
print('_____total points:', self.total_points)
print('------------------------------------------------')
def calc_time_passed(self,start,end):
""" calculates time in s between a start and an end point """
self.time_passed = ((end.hour - start.hour)*3600*1000 +
(end.minute - start.minute)*60*1000 +
(end.second - start.second)*1000 +
(end.microsecond - start.microsecond)/1000)/1000
return self.time_passed
def output_level_time(self):
""" calculates the time spent in this level """
self.calc_time_passed(self.time_level_start, self.time_level_end)
def calc_act_points(self,reason):
""" possible reasons: level_solved, eat_apple, command_sent """
new_value = self.point_db[reason] # get the new value from the dict
self.act_points += new_value # update actual points
self.total_points += new_value # update total points
if reason == "level_solved":
self.levels_solved += 1
if reason == "eat_apple":
self.apples_eaten += 1
if reason == "command_sent":
self.commands_sent += 1
def calc_total_points(self,speed_index):
""" calculates total points until game over
'speed_index_slow' : 1
'speed_index_medium' : 2
'speed_index_fast' : 5
'speed_index_ultra' : 10 """
new_value = int((self.time_passed * self.point_db[speed_index.get()])) # adds spent time * time_multiplier
self.act_points += new_value # update actual points
self.total_points += new_value # update total points
self.total_time_passed += self.time_passed # update total time passed
def reset(self):
# total data for player saved in the db
self.levels_solved = 0
self.apples_eaten = 0
self.commands_sent = 0
self.total_time_passed = 0
self.total_points = 0
# data for actual level shown in the game window
#self.player_name = 0
self.act_level = 0
self.time_passed = 0
self.act_points = 0
# other variables
self.time_level_start = 0
self.time_level_end = 0
print("reset scoreboard done")
Wie man sieht gibt es Variablen für die gesamt Punkte und welche für das aktuelle Level:
Code: Alles auswählen
# total data for player saved in the db
self.levels_solved = 0
self.apples_eaten = 0
self.commands_sent = 0
self.total_time_passed = 0
self.total_points = 0
# data for actual level shown in the game window
self.player_name = player_name
self.act_level = 0
self.time_passed = 0
self.act_points = 0
Die gesamten Punkte sowie der Name sollen dann in einer Datenbank (Dictionary) abgelegt werden und für jeden Spielernamen ein extra Eintrag erstellt werden.
Code: Alles auswählen
self.scoreboard_db = { self.player_name : [self.levels_solved, self.apples_eaten, self.commands_sent,
self.total_time_passed, self.total_points]
}
Weiterhin gibt es für verschiedene Spiel-Events Punkte die man dann sowohl zu den gesamt Punkten und zu den Level-Punkte addiert.
Diese Punkte stehen ebenfalls in einem Dictionary:
Code: Alles auswählen
# database
self.point_db = { 'level_solved': 10000,
'eat_apple': 1000,
'command_sent' : 100,
'speed_index_slow' : 100,
'speed_index_medium' : 250,
'speed_index_fast' : 500,
'speed_index_ultra' : 1000,
}
Wenn jetzt ein Event stattfindet und die Punkte neu berechnet werden sollen, wird folgende Methode aufgerufen:
Code: Alles auswählen
def calc_act_points(self,reason):
""" possible reasons: level_solved, eat_apple, command_sent """
new_value = self.point_db[reason] # get the new value from the dict
self.act_points += new_value # update actual points
self.total_points += new_value # update total points
if reason == "level_solved":
self.levels_solved += 1
if reason == "eat_apple":
self.apples_eaten += 1
if reason == "command_sent":
self.commands_sent += 1
Und hier ist nun mein Problem, dass ich das event als "reason" der Methode zuführe und aus dem Dictionary "point_db[reason]" die zugehörigen raussuche. Das passt auch soweit nur müssen diese Punkte zu den zugehörigen Punkten addiert werden. Und das mache ich zur Zeit von Hand und filtere mittels if-Abfrage aus und jeweils von Hand zu. Da es hier ja nur 3 Abfragen sind geht es ja noch. Aber schöner wäre es, wenn ich die Punkte Varariablen (self.levels_solved, self.apples_eaten, self.commands_sent ) auch in das Dictionary für die Punkte "self.point_db " anhänge und dann in einem Rutsch alles erledige.
Also quasi so:
Code: Alles auswählen
# database
self.point_db = { 'level_solved': [10000, self.levels_solved],
'eat_apple': [1000, self.apples_eaten],
'command_sent' : 100, self.commands_sent],
'speed_index_slow' : 100,
'speed_index_medium' : 250,
'speed_index_fast' : 500,
'speed_index_ultra' : 1000,
}
def calc_act_points(self,reason):
""" possible reasons: level_solved, eat_apple, command_sent """
new_value = self.point_db[reason] # get the new value from the dict
self.act_points += new_value[0] # update actual points
self.total_points += new_value[0] # update total points
new_value[1] += 1 # update level_events_counter(apples,levels_solved,commands_sent)
Wenn ich nun am Ende eines Levels die Punkte anzeigen will mittels der Methode:
Code: Alles auswählen
def calc_total_points(self,speed_index):
""" calculates total points until game over
'speed_index_slow' : 1
'speed_index_medium' : 2
'speed_index_fast' : 5
'speed_index_ultra' : 10 """
new_value = int((self.time_passed * self.point_db[speed_index.get()])) # adds spent time * time_multiplier
self.act_points += new_value # update actual points
self.total_points += new_value # update total points
self.total_time_passed += self.time_passed # update total time passed
def level_summary(self):
print('_____level summary------------------------------')
if self.act_level != self.levels_solved:
print('_____actual level:',self.act_level,'===>>> failed !!!' )
else:
print('_____levels solved:',self.levels_solved )
print('_____total apples eaten:', self.apples_eaten)
print('_____total commands sent:', self.commands_sent)
print('_____time played this level:', self.time_passed)
print('_____total time:', self.total_time_passed)
print('_____points gained this level:', self.act_points)
print('_____total points:', self.total_points)
print('------------------------------------------------')
Dann sind die Werte in der geänderten "self.point_db" (self.levels_solved, self.apples_eaten,self.commands_sent) nicht identisch mit denen die bei "level_summary(self
)" abgefragt werden.
So da ich nun noch eine Nacht drüber geschlafen habe, ist es eigentlich logisch das es so ist. Es sind ja 2 verschiedene Speicherbereiche die belegt werden wenn ich der Variable die nun zufällig den gleichen Namen hat, aber ein Element einer Liste ist einen neuen Wert zuweise.
Ich muss also "level_summary(self)" folgendermaßen ändern:
Code: Alles auswählen
def level_summary(self):
temp, self.levels_solved = self.point_db['level_solved']
temp, self.apples_eaten = self.point_db['eat_apple']
temp, self.commands_sent = self.point_db['command_sent']
print('_____level summary------------------------------')
if self.act_level != self.levels_solved:
print('_____actual level:',self.act_level,'===>>> failed !!!' )
else:
print('_____levels solved:',self.levels_solved )
print('_____total apples eaten:', self.apples_eaten)
print('_____total commands sent:', self.commands_sent)
print('_____time played this level:', self.time_passed)
print('_____total time:', self.total_time_passed)
print('_____points gained this level:', self.act_points)
print('_____total points:', self.total_points)
print('------------------------------------------------')
Und ein weiteres Problem das ich aktuell habe ist ebenfalls sichtbar:
Code: Alles auswählen
def load_db_file(self):
try:
scoreboard_file = open("snake_scoreboard.txt", "r")
liste = scoreboard_file.read().splitlines()
scoreboard_file.close()
if liste:
#print('liste:', liste)
for item in liste:
temp = item.split(" ")
#print('temp =',temp)
self.scoreboard_db[temp[0]] = [temp[1],temp[2],temp[3],temp[4],temp[5]]
else:
self.create_db_file()
Ist es möglich in einer verschachtelten Liste auf die inneren Elemente direkt zuzugreifen und sich den Umweg über meine "temp" Variable zu sparen und "self.scoreboard_db[temp[0]] = [temp[1],temp[2],temp[3],temp[4],temp[5]]" einfacher zu erhalten?
Also wie bei folgendem Beispiel:
Code: Alles auswählen
>>> a=1
>>> b=2
>>> c=3
>>> d=4
>>> e=5
>>> f=6
>>> liste=[[a,b,c],[d,e,f],2,3,4,5,6]
>>> x=liste[0]
>>> x[0]
1
>>>
Ich möchte in der Liste "liste" auf das Element "a" zugreifen. Aber ich möchte nicht er das Objekt "x" erstellen nur um dann "x[0]" schreiben zu können. Geht das einfacher?
Ich weiß, viel Text und und etwas kaotisch.... Aber ich hoffe weiterhin auf Hilfe bei Verbesserung und mögliche TIpps zur Optimierung und besseren Strukturierung.
Danke!