Python 3.3 - Ungolfed
Non l'ho mai giocato a golf, dato che ero più interessato a far funzionare prima un gioco bello. In realtà sono totalmente nuovo in Tk, quindi se qualcuno ha qualche suggerimento, li apprezzerei davvero. Le velocità ora funzionano correttamente. Fammi sapere se desideri vedere funzionalità aggiuntive, ad esempio i colori.
Codice
import tkinter as tk
import queue
import random
class Lane():
def __init__(self, row=-1, lanetype="none", direction=0, speed=0, width=0, maxnumber=0, replenish=0, length=0, gap=0):
self.row = row
self.type = lanetype
self.direction = direction
self.speed = speed
self.width = width
self.maxnumber = maxnumber
self.replenish = replenish
self.length = length
self.gap = gap
self.lanelastupdate = 0
self.objects = []
if(self.type == "car"):
for index in range(self.width):
if(len(self.objects) == self.maxnumber):
break
if((self.maxnumber - len(self.objects) == self.width - index) or random.random() < self.maxnumber/self.width):
self.objects.append([index*self.direction + int((self.width-1)/2 - (self.width-1)*self.direction/2), self.row])
if(self.type == "log" or self.type == "turtle"):
if(self.direction == 1):
start = 0
else:
start = self.width - 1
lengthcounter = 0
gapcounter = 0
for index in range(self.width):
if(lengthcounter < self.length):
self.objects.append([start + index*self.direction, self.row])
lengthcounter += 1
else:
gapcounter += 1
if(gapcounter == self.gap):
lengthcounter = 0
gapcounter = 0
### end of __init__ ###
### end of Lane class ###
class Frogger():
def __init__(self):
# configure 'global' variables
self.directions = ['Up', 'Down', 'Left', 'Right']
self.width = 25
self.height = 13
self.frogstart = [12, 12]
self.pointsforup = 10
self.pointsforhome = 500
self.pointsforbug = 200
self.timerthreshold = 1000
self.timerstart = 60
self.speedchange = 2
self.waterbordertop = 1
self.waterborderbottom = 5
self.minspeed = 10
self.maxspeed = 15
self.minbugspeed = 50
self.maxbugspeed = 100
self.timerspeed = 20
# configure program state variables
self.q = queue.Queue(maxsize=1)
self.updateticks = 0
# configure game variables
self.gameover = False
self.speedup = 0
self.timer = self.timerstart
self.lives = 3
self.score = 0
self.frogposition = [0, 0]
self.frogposition[0] = self.frogstart[0]
self.frogposition[1] = self.frogstart[1]
self.highest = 12
self.movedup = False
# configure the lanes of cars, logs, and turtles
self.init_lanes()
# configure the homes and the bug
self.init_special()
# configure TK window
self.root = tk.Tk()
self.label = tk.Label(text="Score: "+str(self.score)+" Lives: "+str(self.lives)+" Time: "+str(self.timer))
self.label.pack()
self.text = tk.Text(self.root, width=self.width, height=self.height, font=("Courier New", 14))
self.text.bind("<Key>", self.key_event)
self.text.focus_set()
self.text.pack()
# configure drawing sprites
self.init_sprites()
# run the game
self.update_clock()
self.process_world()
self.root.mainloop()
### end of init ###
def init_sprites(self):
self.symbols = {"frog":chr(0x238), "rightcar":chr(187), "leftcar":chr(171), "turtle":chr(920), "log":chr(685), "bug":chr(1217), "grass":chr(993), "freehome":chr(164), "fullhome":"@", "road":"-", "water":chr(0x2248), "saferow":"*"}
self.sprites = {value:key for key, value in self.symbols.items()}
self.text.tag_configure("frog", foreground="chartreuse", background="dark green")
self.text.tag_configure("rightcar", foreground="yellow", background="black")
self.text.tag_configure("leftcar", foreground="yellow", background="black")
self.text.tag_configure("turtle", foreground="orange red", background="cyan")
self.text.tag_configure("log", foreground="sienna", background="cyan")
self.text.tag_configure("bug", foreground="maroon", background="green")
self.text.tag_configure("grass", foreground="orange", background="green")
self.text.tag_configure("freehome", foreground="forest green", background="green")
self.text.tag_configure("fullhome", foreground="red", background="green")
self.text.tag_configure("road", foreground="gray", background="black")
self.text.tag_configure("water", foreground="navy", background="cyan")
self.text.tag_configure("saferow", foreground="pink", background="black")
### end of init_sprites ###
def update_clock(self):
self.timer -= 1
self.label.configure(text="Score: "+str(self.score)+" Lives: "+str(self.lives)+" Time: "+str(self.timer))
if(self.gameover == False):
self.root.after(max(1, self.timerthreshold - self.speedup), self.update_clock)
### end of update_clock ###
def key_event(self, event):
direction = event.keysym
if(direction in self.directions):
try:
self.q.put(direction, block=False)
except:
pass
### end of key_event ###
def process_world(self):
# acquire user input and process it if necessary
if(self.q.qsize() > 0):
self.move_frog(self.q.get())
# update the state of non-frog objects
self.update_world()
# draw the world
self.draw_world()
# schedule another pass unless the game is over
if(self.gameover == False):
self.root.after(self.timerspeed, self.process_world)
else:
self.root.after(self.timerspeed, self.gameover_screen)
### end of process_world ###
def move_frog(self, d):
x = self.frogposition[0]
y = self.frogposition[1]
if(d == 'Up'):
y -= 1
elif(d == 'Down'):
y += 1
elif(d == 'Left'):
x -= 1
else:
x += 1
if(x >= 0 and y >= 0 and x < self.width and y < self.height):
self.frogposition[0] = x
self.frogposition[1] = y
self.movedup = False
if(d == 'Up' and y < self.highest):
self.movedup = True
### end of move_frog ###
def gameover_screen(self):
self.label2 = tk.Label(text="Game over! Your score was: " + str(self.score))
self.label2.pack()
### end of gameover_screen ###
def update_world(self):
# update the internal timer
self.updateticks += 1
# check for loss conditions
if((self.timer == 0) or self.hit_by_car() == True or self.in_water() == True or self.home_twice() == True or self.in_grass() == True):
self.process_death()
return
# credit good moves up
if(self.movedup == True):
self.score += self.pointsforup
self.highest = self.frogposition[1]
self.movedup = False
# check for win condition
if(self.at_home() == True):
self.process_victory()
return
# check for total win
if(self.all_done() == True):
self.process_win()
return
# update the positions of the cars, logs, and turtles
self.update_positions()
### end of update_world ###
def all_done(self):
if(len([x for x in self.homes if x[1]==False])==0):
return True
return False
### end of all_done ###
def process_win(self):
self.gameover = True
return
### end of process_win ###
def process_death(self):
self.lives -= 1
if(self.lives < 1):
self.gameover = True
return
self.frogposition[0] = self.frogstart[0]
self.frogposition[1] = self.frogstart[1]
self.highest = 12
self.timer = self.timerstart
### end of process_death ###
def hit_by_car(self):
for lane in self.lanes:
if(lane.type != "car"):
continue
for car in lane.objects:
if(car == self.frogposition):
return True
return False
### end of hit_by_car
def in_water(self):
if(self.frogposition[1] < self.waterbordertop or self.frogposition[1] > self.waterborderbottom):
return False
for lane in self.lanes:
if(lane.type == "turtle"):
for turtle in lane.objects:
if(turtle == self.frogposition):
return False
elif(lane.type == "log"):
for log in lane.objects:
if(log == self.frogposition):
return False
return True
### end of in_water
def home_twice(self):
for h in self.homes:
if(h[0] == self.frogposition and h[1] == True):
return True
return False
### end of home_twice
def in_grass(self):
if(self.frogposition[1] == 0 and self.at_home() == False):
return True
return False
### end of in_grass
def at_home(self):
for h in self.homes:
if(h[0] == self.frogposition):
return True
return False
### end of at_home ###
def process_victory(self):
self.score += self.pointsforhome
if(self.bugposition == self.frogposition):
self.score += self.pointsforbug
for h in self.homes:
if (h[0] == self.frogposition):
h[1] = True
break
self.timer = self.timerstart
self.frogposition[0] = self.frogstart[0]
self.frogposition[1] = self.frogstart[1]
self.highest = 12
self.speedup += self.speedchange
### end of process_victory ###
def init_lanes(self):
random.seed()
self.lanes = []
self.lanes.append(Lane(row=11, lanetype="car", maxnumber=10, replenish=0.1, direction=1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=10, lanetype="car", maxnumber=8, replenish=0.2, direction=-1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=9, lanetype="car", maxnumber=5, replenish=0.6, direction=1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=8, lanetype="car", maxnumber=9, replenish=0.4, direction=-1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=7, lanetype="car", maxnumber=6, replenish=0.3, direction=1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=5, lanetype="turtle", direction=-1, length=3, gap=4, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=4, lanetype="log", direction=1, length=3, gap=3, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=3, lanetype="log", direction=-1, length=8, gap=9, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=2, lanetype="turtle", direction=1, length=2, gap=6, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
self.lanes.append(Lane(row=1, lanetype="log", direction=-1, length=4, gap=4, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
### end of init_lanes
def init_special(self):
self.bugposition = [2, 0]
self.buglastupdate = 0
self.bugspeed = random.randint(self.minbugspeed, self.maxbugspeed)
self.homes = [[[2, 0], False], [[7, 0], False], [[12, 0], False], [[17, 0], False], [[22, 0], False]]
### end of init_special ###
def update_positions(self):
if(self.updateticks - self.buglastupdate >= self.bugspeed - self.speedup):
self.buglastupdate = self.updateticks
while(True):
freeslots = [x for x in self.homes if x[1] == False]
if(len(freeslots)==0):
self.bugposition = [-1,-1]
break
if(len(freeslots)==1):
self.bugposition = freeslots[0][0]
break
newhomeindex = random.randint(0, 4)
if(self.homes[newhomeindex][0] != self.bugposition and self.homes[newhomeindex][1] == False):
self.bugposition = self.homes[newhomeindex][0]
break
for lane in self.lanes:
lanemovedfrog=False
if(self.updateticks - lane.lanelastupdate >= lane.speed - self.speedup):
lane.lanelastupdate = self.updateticks
else:
continue
for o in lane.objects:
if(o == self.frogposition and lanemovedfrog==False):
self.move_frog(self.directions[int(0.5*lane.direction + 2.5)])
lanemovedfrog=True
o[0] += lane.direction
if((o[0] < 0) or (o[0] >= self.width)):
lane.objects.remove(o)
if(lane.type == "car" and len(lane.objects) < lane.maxnumber and random.random() < lane.replenish):
lane.objects.append([int((self.width-1)/2 - (self.width-1)*lane.direction/2), lane.row])
if(lane.type == "log" or lane.type == "turtle"):
if(lane.direction == 1):
start = min([x[0] for x in lane.objects])
nxt = min([x for x in range(start, self.width) if (len([y for y in lane.objects if y[0] == x]) == 0)])
if(start >= lane.gap or (nxt - start) < lane.length):
lane.objects.append([0, lane.row])
else:
start = max([x[0] for x in lane.objects])
nxt = max([x for x in range(start, -1, -1) if (len([y for y in lane.objects if y[0] == x]) == 0)])
if(self.width - start - 1 >= lane.gap or (start - nxt) < lane.length):
lane.objects.append([self.width - 1, lane.row])
lane.objects.sort()
### end of update_positions ###
def draw_world(self):
self.text.state = "normal"
self.text.delete('1.0', str(self.width + 1) + '.' + '0')
drawstr = ""
# draw home row
newstr = self.symbols["grass"] * self.width
for h in self.homes:
if(h[1] == False):
if(self.bugposition == h[0]):
newstr = self.str_replace(newstr, h[0][0], self.symbols["bug"])
else:
newstr = self.str_replace(newstr, h[0][0], self.symbols["freehome"])
else:
newstr = self.str_replace(newstr, h[0][0], self.symbols["fullhome"])
drawstr += newstr
drawstr += "\n"
# draw water rows
for index in range(self.waterborderbottom - self.waterbordertop + 1):
newstr = self.symbols["water"] * self.width
for lane in self.lanes:
if(lane.row == index + self.waterbordertop):
for o in lane.objects:
if(lane.type == "log"):
newstr = self.str_replace(newstr, o[0], self.symbols["log"])
elif(lane.type == "turtle"):
newstr = self.str_replace(newstr, o[0], self.symbols["turtle"])
drawstr += newstr
drawstr += "\n"
# draw safe row
drawstr += self.symbols["saferow"] * self.width
drawstr += "\n"
# draw car rows
for index in range(len([l for l in self.lanes if l.type == "car"])):
newstr = self.symbols["road"] * self.width
for lane in self.lanes:
if(lane.row == self.waterborderbottom + 2 +index):
for o in lane.objects:
if(lane.direction == 1):
newstr = self.str_replace(newstr, o[0], self.symbols["rightcar"])
elif(lane.direction == -1):
newstr = self.str_replace(newstr, o[0], self.symbols["leftcar"])
drawstr += newstr
drawstr += "\n"
# draw safe row
drawstr += self.symbols["saferow"] * self.width
# do actual drawing
self.text.insert('1.0', drawstr)
# draw frog
self.text.delete(str(1 + self.frogposition[1]) + '.' + str(self.frogposition[0]))
self.text.insert(str(1 + self.frogposition[1]) + '.' + str(self.frogposition[0]), self.symbols["frog"])
# apply colors
for sprite in self.sprites.keys():
self.highlight_pattern(sprite, self.sprites[sprite])
# turn off editability
self.text.state = "disabled"
### end of draw_world ###
def str_replace(self, targetstr, index, char):
return targetstr[:index] + char + targetstr[index+1:]
### end of str_replace ###
def highlight_pattern(self, sprite, tag):
start = self.text.index("1.0")
end = self.text.index("end")
self.text.mark_set("matchStart", start)
self.text.mark_set("matchEnd", start)
self.text.mark_set("searchLimit", end)
count = tk.IntVar()
while True:
index = self.text.search(sprite, "matchEnd", "searchLimit", count=count, regexp=False)
if(index == ""):
break
self.text.mark_set("matchStart", index)
self.text.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
self.text.tag_add(tag, "matchStart","matchEnd")
### end of highlight_pattern ###
### end of Frogger class ###
# Run the game!!!
frogger = Frogger()