Python 函数式编程中的弹跳球游戏
Python Bounce Ball Game in functional programming
这是一款常见的街机游戏,目标是尽可能多地击中所有目标以获得最高分。每次球击中“石头”,您将获得 1 分,如果击中 2 个,您将获得 2 分。如果玩家未能接住横杆或“杆”上的球,则游戏结束。
我的任务是把这个用面向对象编程写的游戏变成函数式编程。
import time
class Ball:
def __init__(self, cvs, pole, stones, scre):
self.stones = stones
self.cvs = cvs
self.pole = pole
self.scre = scre
self.bottom_hit = False
self.hit = 0
self.id = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
self.cvs.move(self.id, 230, 461)
self.a = 3
self.b = -3
self.cvs.move(self.id, self.a, self.b)
self.cvs_height = canvas.winfo_height()
self.cvs_width = canvas.winfo_width()
def stone_strike(self, push):
for stone_line in self.stones:
for stone in stone_line:
stone_push = self.cvs.coords(stone.id)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
self.hit += 1
self.scre.configure(text="Score: " + str(self.hit))
self.cvs.delete(stone.id)
return True
except:
continue
return False
def pole_strike(self, push):
pole_push = self.cvs.coords(self.pole.id)
if push[2] >= pole_push[0] and push[0] <= pole_push[2]:
if push[3] >= pole_push[1] and push[1] <= pole_push[3]:
return True
return False
def draw(self):
self.cvs.move(self.id, self.a, self.b)
push = self.cvs.coords(self.id)
if self.stone_strike(push):
self.b = 3
if push[1] <= 0:
self.b = 3
if push[3] >= self.cvs_height:
self.bottom_hit = True
if push[0] <= 0:
self.a = 3
if push[2] >= self.cvs_width:
self.a = -3
if self.pole_strike(push):
self.b = -3
class Pole:
def __init__(self, cvs):
self.cvs = cvs
self.id = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
self.cvs.move(self.id, 200, 485)
self.a = 0
self.cvs_width = canvas.winfo_width()
self.cvs.bind_all("<Left>", self.turn_left)
self.cvs.bind_all("<Right>", self.turn_right)
def draw(self):
push = self.cvs.coords(self.id)
if push[0] + self.a <= 0:
self.a = 0
if push[2] + self.a >= self.cvs_width:
self.a = 0
self.cvs.move(self.id, self.a, 0)
def turn_left(self, event):
self.a = -5
def turn_right(self, event):
self.a = 5
class Stone:
def __init__(self):
self.id = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
def start_game(event):
score.configure(text="Score: 00")
canvas.delete("all")
pole = Pole(canvas)
stones = []
for i in range(0, 5):
b = []
for j in range(0, 19):
tmp = Stone()
b.append(tmp)
stones.append(b)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j].id, 25 * j, 25 * i)
ball = Ball(canvas, pole, stones, score)
root.update()
time.sleep(1)
while 1:
if not ball.bottom_hit:
ball.draw()
pole.draw()
root.update()
time.sleep(0.01)
if ball.hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", start_game)
root.mainloop()
这是我写的代码..肯定有逻辑错误,因为它不工作。有什么想法吗??
import time
def startgame(event):
score.configure(text="score:00")
canvas.delete("all")
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
pole = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
canvas.move(pole, 200, 425)
pa = 0
def turn_left(event):
pa = -5
def turn_right(event):
pa = 5
def stone_strike(push):
for stone_line in stones:
for stone in stone_line:
stone_push = canvas.coords(stone)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
hit += 1
score.configure(text="score:" + str(hit))
stonaki.delete()
return True
except:
continue
return False
def pole_strike(push_b):
pole_push = canvas.coords(pole)
if push_b[2] >= pole_push[0] and push_b[0] <= pole_push[2]:
if push_b[3] >= pole_push[1] and push_b[1] <= pole_push[3]:
return True
return False
canvas.bind_all("<Left>", turn_left)
canvas.bind_all("<Right>", turn_right)
push_p = canvas.coords(pole)
if push_p[0] + pa <= 0:
pa = 0
if push_p[2] + pa >= canvas_width:
pa = 0
stones = []
for i in range(0, 5):
lista = []
for j in range(0, 19):
stonaki = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
lista.append(stonaki)
stones.append(lista)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j], 25 * j, 25 * i)
root.update()
bottom_hit = False
hit = 0
ball = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
canvas.move(ball, 230, 461)
ba = 3
bb = -3
canvas.move(ball, ba, bb)
push_b = canvas.coords(ball)
if stone_strike(push_b):
bb = 3
if push_b[1] <= 0:
bb = 3
if push_b[3] >= canvas_height:
bottom_hit = True
if push_b[0] <= 0:
ba = 3
if push_b[2] >= canvas_width:
ba = -3
if pole_strike(push_b):
bb = -3
time.sleep(1)
while 1:
if not bottom_hit:
root.update()
time.sleep(0.01)
if hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", startgame)
root.mainloop()
在将这个用object-oriented编程编写的游戏变成函数式编程的过程中,我们需要处理每个函数都在使用的variables/widgets。如果我们正在对局部函数中的某个变量进行更改,并希望在函数调用结束后保留所做的更改,那么我将 将这些 variables/widgets 设为全局 .
此外,在 OOP 代码中,每次在 canvas 中使用函数 draw()
对“球”和“杆”进行更改。因此,为相同的 drawB()
和 drawP()
创建两个函数:
from tkinter import *
import time
def startgame(event):
score.configure(text="score:00")
canvas.delete("all")
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
global pole,pa, ba,bb,bottom_hit, hit,ball
pole = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
canvas.move(pole, 200, 425)
pa = 0
def turn_left(event):
global pa
pa = -5
def turn_right(event):
global pa
pa = 5
def stone_strike(push):
global stones, hit
for stone_line in stones:
for stone in stone_line:
stone_push = canvas.coords(stone)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
hit += 1
score.configure(text="score:" + str(hit))
canvas.delete(stone) #what to delete
return True
except:
continue
return False
def pole_strike(push_b):
global pole
pole_push = canvas.coords(pole)
if push_b[2] >= pole_push[0] and push_b[0] <= pole_push[2]:
if push_b[3] >= pole_push[1] and push_b[1] <= pole_push[3]:
return True
return False
canvas.bind_all("<Left>", turn_left)
canvas.bind_all("<Right>", turn_right)
def drawP():
global pa,pole
push_p = canvas.coords(pole)
if push_p[0] + pa <= 0:
pa = 0
if push_p[2] + pa >= canvas_width:
pa = 0
canvas.move(pole, pa, 0)
global stones
stones = []
for i in range(0, 5):
lista = []
for j in range(0, 19):
stonaki = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
lista.append(stonaki)
stones.append(lista)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j], 25 * j, 25 * i)
bottom_hit = False
hit = 0
ball = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
canvas.move(ball, 230, 461)
ba = 3
bb = -3
root.update()
def drawB():
global ba,bb,bottom_hit, hit,ball,pole
canvas.move(ball, ba, bb)
push_b = canvas.coords(ball)
if stone_strike(push_b):
bb = 3
if push_b[1] <= 0:
bb = 3
if push_b[3] >= canvas_height:
bottom_hit = True
if push_b[0] <= 0:
ba = 3
if push_b[2] >= canvas_width:
ba = -3
if pole_strike(push_b):
bb = -3
time.sleep(1)
while 1:
if not bottom_hit:
drawB()
drawP()
root.update()
time.sleep(0.01)
if hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", startgame)
root.mainloop()
您可以进一步优化此代码。
这是一款常见的街机游戏,目标是尽可能多地击中所有目标以获得最高分。每次球击中“石头”,您将获得 1 分,如果击中 2 个,您将获得 2 分。如果玩家未能接住横杆或“杆”上的球,则游戏结束。
我的任务是把这个用面向对象编程写的游戏变成函数式编程。
import time
class Ball:
def __init__(self, cvs, pole, stones, scre):
self.stones = stones
self.cvs = cvs
self.pole = pole
self.scre = scre
self.bottom_hit = False
self.hit = 0
self.id = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
self.cvs.move(self.id, 230, 461)
self.a = 3
self.b = -3
self.cvs.move(self.id, self.a, self.b)
self.cvs_height = canvas.winfo_height()
self.cvs_width = canvas.winfo_width()
def stone_strike(self, push):
for stone_line in self.stones:
for stone in stone_line:
stone_push = self.cvs.coords(stone.id)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
self.hit += 1
self.scre.configure(text="Score: " + str(self.hit))
self.cvs.delete(stone.id)
return True
except:
continue
return False
def pole_strike(self, push):
pole_push = self.cvs.coords(self.pole.id)
if push[2] >= pole_push[0] and push[0] <= pole_push[2]:
if push[3] >= pole_push[1] and push[1] <= pole_push[3]:
return True
return False
def draw(self):
self.cvs.move(self.id, self.a, self.b)
push = self.cvs.coords(self.id)
if self.stone_strike(push):
self.b = 3
if push[1] <= 0:
self.b = 3
if push[3] >= self.cvs_height:
self.bottom_hit = True
if push[0] <= 0:
self.a = 3
if push[2] >= self.cvs_width:
self.a = -3
if self.pole_strike(push):
self.b = -3
class Pole:
def __init__(self, cvs):
self.cvs = cvs
self.id = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
self.cvs.move(self.id, 200, 485)
self.a = 0
self.cvs_width = canvas.winfo_width()
self.cvs.bind_all("<Left>", self.turn_left)
self.cvs.bind_all("<Right>", self.turn_right)
def draw(self):
push = self.cvs.coords(self.id)
if push[0] + self.a <= 0:
self.a = 0
if push[2] + self.a >= self.cvs_width:
self.a = 0
self.cvs.move(self.id, self.a, 0)
def turn_left(self, event):
self.a = -5
def turn_right(self, event):
self.a = 5
class Stone:
def __init__(self):
self.id = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
def start_game(event):
score.configure(text="Score: 00")
canvas.delete("all")
pole = Pole(canvas)
stones = []
for i in range(0, 5):
b = []
for j in range(0, 19):
tmp = Stone()
b.append(tmp)
stones.append(b)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j].id, 25 * j, 25 * i)
ball = Ball(canvas, pole, stones, score)
root.update()
time.sleep(1)
while 1:
if not ball.bottom_hit:
ball.draw()
pole.draw()
root.update()
time.sleep(0.01)
if ball.hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", start_game)
root.mainloop()
这是我写的代码..肯定有逻辑错误,因为它不工作。有什么想法吗??
import time
def startgame(event):
score.configure(text="score:00")
canvas.delete("all")
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
pole = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
canvas.move(pole, 200, 425)
pa = 0
def turn_left(event):
pa = -5
def turn_right(event):
pa = 5
def stone_strike(push):
for stone_line in stones:
for stone in stone_line:
stone_push = canvas.coords(stone)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
hit += 1
score.configure(text="score:" + str(hit))
stonaki.delete()
return True
except:
continue
return False
def pole_strike(push_b):
pole_push = canvas.coords(pole)
if push_b[2] >= pole_push[0] and push_b[0] <= pole_push[2]:
if push_b[3] >= pole_push[1] and push_b[1] <= pole_push[3]:
return True
return False
canvas.bind_all("<Left>", turn_left)
canvas.bind_all("<Right>", turn_right)
push_p = canvas.coords(pole)
if push_p[0] + pa <= 0:
pa = 0
if push_p[2] + pa >= canvas_width:
pa = 0
stones = []
for i in range(0, 5):
lista = []
for j in range(0, 19):
stonaki = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
lista.append(stonaki)
stones.append(lista)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j], 25 * j, 25 * i)
root.update()
bottom_hit = False
hit = 0
ball = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
canvas.move(ball, 230, 461)
ba = 3
bb = -3
canvas.move(ball, ba, bb)
push_b = canvas.coords(ball)
if stone_strike(push_b):
bb = 3
if push_b[1] <= 0:
bb = 3
if push_b[3] >= canvas_height:
bottom_hit = True
if push_b[0] <= 0:
ba = 3
if push_b[2] >= canvas_width:
ba = -3
if pole_strike(push_b):
bb = -3
time.sleep(1)
while 1:
if not bottom_hit:
root.update()
time.sleep(0.01)
if hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", startgame)
root.mainloop()
在将这个用object-oriented编程编写的游戏变成函数式编程的过程中,我们需要处理每个函数都在使用的variables/widgets。如果我们正在对局部函数中的某个变量进行更改,并希望在函数调用结束后保留所做的更改,那么我将 将这些 variables/widgets 设为全局 .
此外,在 OOP 代码中,每次在 canvas 中使用函数 draw()
对“球”和“杆”进行更改。因此,为相同的 drawB()
和 drawP()
创建两个函数:
from tkinter import *
import time
def startgame(event):
score.configure(text="score:00")
canvas.delete("all")
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
global pole,pa, ba,bb,bottom_hit, hit,ball
pole = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
canvas.move(pole, 200, 425)
pa = 0
def turn_left(event):
global pa
pa = -5
def turn_right(event):
global pa
pa = 5
def stone_strike(push):
global stones, hit
for stone_line in stones:
for stone in stone_line:
stone_push = canvas.coords(stone)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
hit += 1
score.configure(text="score:" + str(hit))
canvas.delete(stone) #what to delete
return True
except:
continue
return False
def pole_strike(push_b):
global pole
pole_push = canvas.coords(pole)
if push_b[2] >= pole_push[0] and push_b[0] <= pole_push[2]:
if push_b[3] >= pole_push[1] and push_b[1] <= pole_push[3]:
return True
return False
canvas.bind_all("<Left>", turn_left)
canvas.bind_all("<Right>", turn_right)
def drawP():
global pa,pole
push_p = canvas.coords(pole)
if push_p[0] + pa <= 0:
pa = 0
if push_p[2] + pa >= canvas_width:
pa = 0
canvas.move(pole, pa, 0)
global stones
stones = []
for i in range(0, 5):
lista = []
for j in range(0, 19):
stonaki = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
lista.append(stonaki)
stones.append(lista)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j], 25 * j, 25 * i)
bottom_hit = False
hit = 0
ball = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
canvas.move(ball, 230, 461)
ba = 3
bb = -3
root.update()
def drawB():
global ba,bb,bottom_hit, hit,ball,pole
canvas.move(ball, ba, bb)
push_b = canvas.coords(ball)
if stone_strike(push_b):
bb = 3
if push_b[1] <= 0:
bb = 3
if push_b[3] >= canvas_height:
bottom_hit = True
if push_b[0] <= 0:
ba = 3
if push_b[2] >= canvas_width:
ba = -3
if pole_strike(push_b):
bb = -3
time.sleep(1)
while 1:
if not bottom_hit:
drawB()
drawP()
root.update()
time.sleep(0.01)
if hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", startgame)
root.mainloop()
您可以进一步优化此代码。