Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python上制作俄罗斯方块_Python_Class_Oop_Tetris - Fatal编程技术网

在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()