在python上制作俄罗斯方块
这是我的第一个完全由我自己编写的程序,但有一点我不明白问题出在哪里。这是密码在python上制作俄罗斯方块,python,class,oop,tetris,Python,Class,Oop,Tetris,这是我的第一个完全由我自己编写的程序,但有一点我不明白问题出在哪里。这是密码 from scene import * import random, sound sw, sh = get_screen_size() rect_w = sw/3 #343.33 rect_h = 612 #668 side = int(rect_w/10) NEW = None A = Action x = 0 y = rect_h/2 dot = [[ [x, y]
from scene import *
import random, sound
sw, sh = get_screen_size()
rect_w = sw/3 #343.33
rect_h = 612 #668
side = int(rect_w/10)
NEW = None
A = Action
x = 0
y = rect_h/2
dot = [[
[x, y]
]]
line = [
[[x, y], [x+side, y]],
[[x, y], [x, y-side]]
]
shapes = [dot, line]
class Board(ShapeNode):
def __init__(self, stroke_color='lightgrey', line_width=1, parent=None, *args, **kwargs):
path = ui.Path.rect(0, 0, rect_w, rect_h)
path.line_width = line_width
if stroke_color == 'lightgrey':
d = int(rect_w/10)
for l in range(int(rect_w/d)):
x = l*d
path.move_to(x, 0)
path.line_to(x, rect_h)
super().__init__(path,
fill_color='white',
stroke_color=stroke_color,
parent=parent,
*args, **kwargs)
class Shape(SpriteNode):
def __init__(self, parent, x, y):
self.x, self.y = x, y
print(self.x)
shape = random.choice(shapes)
var = random.choice(range(len(shape)))
self.shape = []
self.grounded_blocks = []
for pos in shape[var]:
block = SpriteNode('pzl:Yellow3',
pos,
size=(side, side),
parent=parent)
self.shape.append(block)
class Game(Scene):
def setup(self):
self.background_color = 'white'
self.grey_rect = Board(line_width=2, parent=self, position=(sw/3, sh/2), z_position=0)
self.board = Board(stroke_color='purple', line_width=15, parent=self, position=(sw/3, sh/2), z_position=-1)
self.seconds = 0
self.figure = None
self.NEW = None
self.add_figure()
def update(self):
self.seconds += self.dt
if self.seconds > 0.05:
self.seconds = 0
self.figure.move_down()
#i deleted move_down() cause it's not important for this question
if NEW:
self.add_figure()
def add_figure(self):
x = random.randrange(10) * int(rect_w/10)
self.figure = Shape(self.grey_rect, x, y)
global NEW
NEW = False
run(Game())
尽管我在add_figure()中更改了全局x,但图形始终显示在同一位置。不知道为什么全局x没有改变,在同一个add_figure()中使用global NEW可以工作
我删除了一些东西,因为这个问题不需要它们,而让这些东西工作。
希望我解释的好,如果没有,我会提供更多细节,谢谢大家的帮助我想你可以添加
全局
关键字,就像你使用新建
虽然我在add\u figure()
中更改了全局x
不,你真的不知道
如果在函数中的任意位置赋给变量,而该变量未显式标记为全局变量,则该变量在函数中的任何位置都被视为局部变量
这就是为什么NEW
有效,而x
无效的原因!向函数中添加一个global x
,它将更改全局,而不是创建一个新的本地。下面是使用tke tkinter模块制作的俄罗斯方块:
从tkinter导入画布、Tk、ALL、messagebox
从随机导入选择,随机范围
投票率=500
CV_宽度=380
W_BOX_NUM=19
H_-BOX_-NUM=22
长方体L=int(CV_宽度/W_长方体数量)
CVS\u高度=长方体高度*H\u长方体数量
分数={1:10,2:20,3:50,4:100}
FONT=f'Fixedsys{int(框2)}粗体'
破折号=(整数(方框1/2),整数(方框1/4))
图_形状=(
('square'、'snow3'、(5,1)、(6,1)、(5,2)、(6,2)),
(‘线’、‘雪3’、(5,1)、(6,1)、(7,1)、(8,1)),
(‘右’、‘黄花三’、(7,1)、(5,2)、(6,2)、(7,2)),
(‘左’、‘黄花三’、(5,1)、(5,2)、(6,2)、(7,2)),
(‘right_z’、‘IndianRed4’、(5,2)、(6,2)、(6,1)、(7,1)),
(‘左’、‘印度红4’、(5,1)、(6,1)、(6,2)、(7,2)),
(“雪3”(6,1),(5,2),(6,2),(7,2))
)
类别UTIL:
@静力学方法
def convert_坐标(x,y,x_size=0,y_size=0):
返回框长*x,框长*y,框长*(x+x长*),框长*(y+y长)
@静力学方法
def find_重叠(x、y、x_大小、y_大小、画布、排除的_项):
x1,y1,x2,y2=Utils.转换坐标(x,y,x\u大小,y\u大小)
所有重叠=画布。查找封闭的(x1-1,y1-1,x2+1,y2+1)
返回列表(集合(所有重叠)-集合(排除的项目))
@静力学方法
def tgm3_随机化器():
池=列表(范围(7))*5
订单=[]
目标_idx=无
rand_idx=无
第一个索引=选择([1,2,3,6])
收益率第一指数
历史=[4,5,4,第一个索引]
尽管如此:
对于滚入范围(6):
rand_idx=randrange(len(池))
target_idx=池[rand_idx]
如果目标_idx不在历史记录中或滚动==5:
打破
如果订购:
池[rand_idx]=订单[0]
如果目标_idx按顺序排列:
订单。删除(目标_idx)
order.append(target_idx)
池[rand_idx]=订单[0]
history.pop(0)
附加(目标_idx)
产量目标
四重奏类游戏:
画布=无
tk=无
当前数字=无
下一个数字=无
背景_项=[]
极限坐标=无
分数=0
兰德=无
def启动(自):
self.tk=tk()
self.tk.title('Tkinter-Tetris'))
self.canvas=canvas(self.tk,bg='red',width=CVS\u width,height=CVS\u height)
self.Draw_Background()
self.rand=Utils.tgm3\u随机化器()
self.curr\u figure=figure(self.canvas,figure\u SHAPES[next(self.rand)],
self.background\u项目、self.limit\u协调)
self.next\u figure=figure(self.canvas,figure\u SHAPES[next(self.rand)],
self.background\u项目、self.limit\u协调)
self.curr\u figure.Create()
self.next\u figure.Create(next\u area=True)
self.canvas.pack()
self.tk.bind(“,self.Handle\u事件)
self.run()
self.tk.mainloop()
def Draw_背景(自身):
play\u area\u id=self.canvas.create\u rectangle(Utils.convert\u coords(1,1,10,20)),
填充class='绿色',标记class='TRS')
next\u area\u id=self.canvas.create\u rectangle(Utils.convert\u坐标(12,1,6,5),
填充(绿色)
self.limit\u coords=self.canvas.coords(play\u area\u id)
创建矩形(Utils.convert\u坐标(12,7,6,4),fill='green')
self.canvas.create_text(Utils.convert_coords(15,2)[0:2],fill='snow3',text='NEXT',
字体=字体)
self.canvas.create_text(Utils.convert_coords(15,8)[0:2],fill='snow3',text='SCORE',
字体=字体)
self.canvas.create_text(Utils.convert_coords(15,9)[0:2],fill='snow3',text='0000000',
font=font,tag='SCR')
self.background\u items.append(播放区域\u id)
self.background\u items.append(下一个\u区域\u id)
对于范围(2,21)内的i:
line\u id=self.canvas.create\u line(Utils.convert\u coords(1,i,10,0),dash=dash,
填充(橙色)
self.background\u items.append(行\u id)
对于范围(2,11)内的i:
line\u id=self.canvas.create\u line(Utils.convert\u coords(i,1,0,20),dash=dash,
填充(黄色)
self.background\u items.append(行\u id)
def句柄_事件(自身、事件):
如果event.keysym==“Escape”:
self.tk.quit()
elif event.keysym==“Left”:
自电流图移动(-1,0))
elif event.keysym==“Right”:
自电流图移动((1,0))
elif event.keysym==“向下”:
自身电流图移动((0,1))
elif event.keysym==“向上”:
self.curr\u figure.rotate()
def运行(自):
self.Delete_行()
如果self.curr\u figure.stopped:
[self.canvas.delete(blk)用于self.next_figure.blocks中的blk]
self.curr\u图=self.next\u图
self.next\u figure=figure(self.canvas,figure\u SHAPES[next(self.rand)],
from tkinter import Canvas, Tk, ALL, messagebox
from random import choice, randrange
POLL_MS = 500
CVS_WIDTH = 380
W_BOX_NUM = 19
H_BOX_NUM = 22
BOX_L = int(CVS_WIDTH / W_BOX_NUM)
CVS_HEIGHT = BOX_L * H_BOX_NUM
SCORES = {1: 10, 2: 20, 3: 50, 4: 100}
FONT = f'Fixedsys {int(BOX_L/2)} bold'
DASH = (int(BOX_L / 2), int(BOX_L / 4))
FIGURE_SHAPES = (
('square', 'snow3', (5, 1), (6, 1), (5, 2), (6, 2)),
('line', 'snow3', (5, 1), (6, 1), (7, 1), (8, 1)),
('right_l', 'goldenrod3', (7, 1), (5, 2), (6, 2), (7, 2)),
('left_l', 'goldenrod3', (5, 1), (5, 2), (6, 2), (7, 2)),
('right_z', 'IndianRed4', (5, 2), (6, 2), (6, 1), (7, 1)),
('left_z', 'IndianRed4', (5, 1), (6, 1), (6, 2), (7, 2)),
('_|_', 'snow3', (6, 1), (5, 2), (6, 2), (7, 2))
)
class Utils:
@staticmethod
def convert_coords(x, y, x_size=0, y_size=0):
return BOX_L * x, BOX_L * y, BOX_L * (x + x_size), BOX_L * (y + y_size)
@staticmethod
def find_overlaps(x, y, x_size, y_size, canvas, excluded_items):
x1, y1, x2, y2 = Utils.convert_coords(x, y, x_size, y_size)
all_overlaps = canvas.find_enclosed(x1 - 1, y1 - 1, x2 + 1, y2 + 1)
return list(set(all_overlaps) - set(excluded_items))
@staticmethod
def tgm3_randomizer():
pool = list(range(7)) * 5
order = []
target_idx = None
rand_idx = None
first_index = choice([1, 2, 3, 6])
yield first_index
history = [4, 5, 4, first_index]
while True:
for roll in range(6):
rand_idx = randrange(len(pool))
target_idx = pool[rand_idx]
if target_idx not in history or roll == 5:
break
if order:
pool[rand_idx] = order[0]
if target_idx in order:
order.remove(target_idx)
order.append(target_idx)
pool[rand_idx] = order[0]
history.pop(0)
history.append(target_idx)
yield target_idx
class TetrisGame:
canvas = None
tk = None
curr_figure = None
next_figure = None
background_items = []
limit_coords = None
score = 0
rand = None
def start(self):
self.tk = Tk()
self.tk.title('Tkinter-Tetris')
self.canvas = Canvas(self.tk, bg='red', width=CVS_WIDTH, height=CVS_HEIGHT)
self.Draw_Background()
self.rand = Utils.tgm3_randomizer()
self.curr_figure = Figure(self.canvas, FIGURE_SHAPES[next(self.rand)],
self.background_items, self.limit_coords)
self.next_figure = Figure(self.canvas, FIGURE_SHAPES[next(self.rand)],
self.background_items, self.limit_coords)
self.curr_figure.Create()
self.next_figure.Create(next_area=True)
self.canvas.pack()
self.tk.bind("<Key>", self.Handle_Events)
self.run()
self.tk.mainloop()
def Draw_Background(self):
play_area_id = self.canvas.create_rectangle(Utils.convert_coords(1, 1, 10, 20),
fill='green', tag='TRS')
next_area_id = self.canvas.create_rectangle(Utils.convert_coords(12, 1, 6, 5),
fill='green')
self.limit_coords = self.canvas.coords(play_area_id)
self.canvas.create_rectangle(Utils.convert_coords(12, 7, 6, 4), fill='green')
self.canvas.create_text(Utils.convert_coords(15, 2)[0:2], fill='snow3', text='NEXT',
font=FONT)
self.canvas.create_text(Utils.convert_coords(15, 8)[0:2], fill='snow3', text='SCORE',
font=FONT)
self.canvas.create_text(Utils.convert_coords(15, 9)[0:2], fill='snow3', text='0000000',
font=FONT, tag='SCR')
self.background_items.append(play_area_id)
self.background_items.append(next_area_id)
for i in range(2, 21):
line_id = self.canvas.create_line(Utils.convert_coords(1, i, 10, 0), dash=DASH,
fill='orange')
self.background_items.append(line_id)
for i in range(2, 11):
line_id = self.canvas.create_line(Utils.convert_coords(i, 1, 0, 20), dash=DASH,
fill='yellow')
self.background_items.append(line_id)
def Handle_Events(self, event):
if event.keysym == "Escape":
self.tk.quit()
elif event.keysym == "Left":
self.curr_figure.move((-1, 0))
elif event.keysym == "Right":
self.curr_figure.move((1, 0))
elif event.keysym == "Down":
self.curr_figure.move((0, 1))
elif event.keysym == "Up":
self.curr_figure.rotate()
def run(self):
self.Delete_Lines()
if self.curr_figure.stopped:
[self.canvas.delete(blk) for blk in self.next_figure.blocks]
self.curr_figure = self.next_figure
self.next_figure = Figure(self.canvas, FIGURE_SHAPES[next(self.rand)],
self.background_items, self.limit_coords)
if not self.curr_figure.Create():
self.Game_Over()
self.next_figure.Create(next_area=True)
if all([self.curr_figure._move_allowed(0, 1, self.canvas.coords(block)) for block in
self.curr_figure.blocks]):
self.curr_figure.move((0, 1))
else:
self.curr_figure.stopped = True
self.tk.after(POLL_MS, self.run)
def Delete_Lines(self):
full_lines = []
for i in range(1, 21):
overlap_items = Utils.find_overlaps(1, i, 10, 1, self.canvas, self.background_items)
if len(overlap_items) == 10:
full_lines.append(i)
[self.canvas.delete(curr_blk) for curr_blk in overlap_items]
blocks_to_move = Utils.find_overlaps(1, 1, 10, i, self.canvas, self.background_items)
[self.canvas.move(block, 0, BOX_L) for block in blocks_to_move]
if full_lines:
self.Update_Score(SCORES[len(full_lines)])
def Update_Score(self, score):
self.score += score
self.canvas.itemconfigure(self.canvas.find_withtag('SCR')[0], text=f'{self.score:07}')
def Game_Over(self):
self.canvas.delete(ALL)
self.tk.quit()
messagebox.showinfo("End of Game", f'Game Over\nYour score: {self.score:07}')
class Figure:
def __init__(self, canvas, shape_data: tuple, background_items, limit_coords):
self.canvas = canvas
self.tag = shape_data[0]
self.color = shape_data[1]
self.blk_coords = shape_data[2:]
self.limit_coords = limit_coords
self.rotation_parity = 1
self.background_items = background_items
self.stopped = False
self.blocks = []
def Create(self, next_area=False):
self.blocks = []
for (p_x, p_y) in self.blk_coords:
if next_area:
p_x, p_y = p_x + 8, p_y + 2
overlap_items = Utils.find_overlaps(p_x, p_y, 1, 1, self.canvas, self.background_items)
if overlap_items:
return False
block = self.canvas.create_rectangle(Utils.convert_coords(p_x, p_y, 1, 1), fill=self.color)
self.blocks.append(block)
return True
def _move_allowed(self, x_delta, y_delta, item_coords):
if item_coords and len(item_coords) == 4:
new_x1, new_y1 = item_coords[0] + x_delta * BOX_L, item_coords[1] + y_delta * BOX_L
new_x2, new_y2 = item_coords[2] + x_delta * BOX_L, item_coords[3] + y_delta * BOX_L
if new_x1 >= self.limit_coords[0] and new_y1 >= self.limit_coords[1]:
if new_x2 <= self.limit_coords[2] and new_y2 <= self.limit_coords[3]:
overlap_items = Utils.find_overlaps(new_x1 // BOX_L, new_y1 // BOX_L, 1, 1, self.canvas, self.background_items + self.blocks)
if not overlap_items:
return True
return False
def rotate(self):
if self.tag != 'square':
coords = [(self.canvas.coords(block)) for block in self.blocks]
if coords and len([xy for block_coords in coords for xy in block_coords]) == 16:
grouped_coords = list(zip(*coords))
min_x, min_y = min(grouped_coords[0]), min(grouped_coords[1])
max_x, max_y = max(grouped_coords[2]), max(grouped_coords[3])
cx, cy = (max_x - min_x) / 2 + min_x, (max_y - min_y) / 2 + min_y
coords_after_rotation = []
for (up_l_x, up_l_y, _, _) in coords:
rx, ry = cx - up_l_x, cy - up_l_y
new_x, new_y = ry + cx, -rx + cy
new_x_aligned, new_y_aligned = (new_x - up_l_x) // BOX_L, (new_y - up_l_y) // BOX_L
if self.rotation_parity % 2 == 0:
new_x_aligned -= 1
new_y_aligned += 1
coords_after_rotation.append((new_x_aligned, new_y_aligned))
self.move(coords_after_rotation)
self.rotation_parity += 1
def move(self, coords):
coords_list = coords if len(coords) == 4 else [coords] * 4
if all([self._move_allowed(x, y, self.canvas.coords(self.blocks[i])) for i, (x, y) in enumerate(coords_list)]):
for i, curr_item in enumerate(self.blocks):
x_delta, y_delta = coords_list[i]
self.canvas.move(curr_item, x_delta * BOX_L, y_delta * BOX_L)
if __name__ == "__main__":
tetris_game = TetrisGame()
tetris_game.start()