• 欢迎访问MACD实战投资网站,推荐使用最新版谷歌Chrome浏览器访问本网站,关注公众号 丁火甲木庚金 www.macd11.com/subscriptions

俄罗斯方块之Python实现代码(二)

Python 丁火 11年前 (2013-09-05) 8063次浏览 0个评论

PS:最近学习用Python怎么写小游戏,研究了几个俄罗斯方块的代码。记录一下:

第二个实现代码如下,这个使用了内置的模块实现的,在PY2.7版本直接运行,在3.x版本需要修改部分语法:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from Tkinter import *
import random
from tkMessageBox import askquestion

# 尚需改进,有待提高

# 各种方块的表示,与参考方块的相对位置
shapedic = {1: ((0, 0), (1, 0), (0, -1), (1, -1)),  # 正方形
            2: ((0, 0), (0, -1), (0, -2), (0, 1)),  # 长条
            3: ((0, 0), (0, -1), (1, 0), (1, 1)),  # 之字型
            4: ((0, 0), (0, -1), (-1, 0), (-1, 1)),  # 反之字型
            5: ((0, 0), (1, 0), (-1, 0), (-1, -1)),  # L型
            6: ((0, 0), (1, 0), (-1, 0), (1, -1)),  # 反L型
            7: ((0, 0), (1, 0), (-1, 0), (0, -1))  # T型
            }

# 旋转函数,顺时针旋转90度,相对于参考方块
change_dic = {(0, 0): (0, 0), (0, 1): (-1, 0), (-1, 0): (0, -1), (0, -1): (1, 0), (1, 0): (0, 1),
              (1, -1): (1, 1), (1, 1): (-1, 1), (-1, 1): (-1, -1), (-1, -1): (1, -1),
              (2, 0): (0, 2), (0, 2): (-2, 0), (-2, 0): (0, -2), (0, -2): (2, 0)}

# 随机颜色
colorDict = {
    0: '#CCC0B4',
    1: '#EEE4DA',
    2: '#EDE0C8',
    3: '#F2B179',
    4: '#EC8D54',
    5: '#F67C5F',
    6: '#EA5937',
    7: '#804000',
    8: '#F1D04B',
    9: '#E4C02A',
    10: '#EE7600',
    11: '#D5A500',
    12: '#E4C02A',
    13: '#804000',
    14: '#EA5937',
    15: '#EE7600',
    16: '#776E65',
    17: '#776E65',
    18: '#FFFFFF',
    19: 'yellow',
    20: 'blue',
    21: 'lightblue',
    22: 'red'
}


# 俄罗斯方块
class Game_Russia:
    def __init__(self):

        # 每个方块的大小
        self.width = 20

        # 方块数目,长和宽
        self.row = 28
        self.column = 19

        #        #初始化
        #        self.scores=0
        #        self.all_square={}#坐标系网格中个位置方块的存在性
        #        self.head_square=[]#参考方块绝对位置
        #        self.new_square=[]#移动方块相对位置
        #        self.direction=-1#方块初始方向
        #        #规定界限
        #        #i表示第i列,0在左边
        #        #j表示第j行,零在上面
        #        for j in range(-4,self.row):
        #            for i in range(self.column):
        #                self.all_square[i,j]=0
        #        #划界,开口向上
        #        for j in range(self.row+1):
        #            self.all_square[19,j]=1
        #            self.all_square[-1,j]=1
        #        for i in range(-1,self.column+1):
        #            self.all_square[i,28]=1

        """
        用来debug
        for j in range(self.row+1):
            for i in range(-1,self.column+1):
                print self.all_square[i,j],
            print
        """

        self.window = Tk()
        self.window.geometry()
        self.window.maxsize(400, 610)
        self.window.minsize(400, 610)
        self.window.title(u"俄罗斯方块")

        self.frame1 = Frame(self.window, bg="white", relief=GROOVE, borderwidth=5)
        self.frame2 = Frame(self.window, bg="white", relief=RAISED, borderwidth=2, height=40,
                            width=570)
        self.canvas = Canvas(self.frame1, bg='purple', width=400, height=570)
        self.score_label = Label(self.frame2, text="Score: 0")

        self.frame1.pack()
        self.frame2.pack(fill=BOTH)
        self.score_label.pack(side=LEFT)
        self.canvas.pack(fill=BOTH)

        self.draw_wall()

        self.initial()

        self.get_new_square()

        self.draw_new_square()

        self.play()

        self.window.mainloop()

    "=== View Part ==="

    # 边界
    def draw_wall(self):
        self.canvas.create_line(5, 5, 385, 5, fill='blue', width=1)
        self.canvas.create_line(385, 5, 385, 565, fill='blue', width=1)
        self.canvas.create_line(5, 5, 5, 565, fill='blue', width=1)
        self.canvas.create_line(5, 565, 385, 565, fill='blue', width=1)

    # 得分
    def draw_score(self):
        self.get_score()
        self.score_label.config(self.score_label, text="Score: " + str(self.scores))

    # 画下面所有不动的方块
    def draw_square(self):
        color = colorDict[random.randint(0, len(colorDict) - 1)]
        for j in range(self.row):
            self.canvas.delete("line" + str(j))
            for i in range(self.column):
                if self.all_square[i, j]:
                    self.canvas.create_rectangle(5 + i * self.width,
                                                 5 + j * self.width, 5 + (i + 1) * self.width,
                                                 5 + (j + 1) * self.width, fill=color, tags="line" + str(j))

    # 画移动的方块
    def draw_new_square(self):
        self.canvas.delete("new")
        self.head_square[1] += 1
        color = colorDict[random.randint(0, len(colorDict) - 1)]
        for i in range(4):
            self.canvas.create_rectangle(5 + (self.head_square[0] + self.new_square[i][0]) * self.width,
                                         5 + (self.head_square[1] + self.new_square[i][1]) * self.width,
                                         5 + (self.head_square[0] + self.new_square[i][0] + 1) * self.width,
                                         5 + (self.head_square[1] + 1 + self.new_square[i][1]) * self.width, fill=color,
                                         tags="new")

    "=== Model Part ==="

    def initial(self):
        # 初始化
        self.scores = 0
        self.all_square = {}  # 坐标系网格中个位置方块的存在性
        self.head_square = []  # 参考方块绝对位置
        self.new_square = []  # 移动方块相对位置
        self.direction = -1  # 方块初始方向
        # 规定界限
        # i表示第i列,0在左边
        # j表示第j行,零在上面
        for j in range(-4, self.row):
            for i in range(self.column):
                self.all_square[i, j] = 0
        # 划界,开口向上
        for j in range(self.row + 1):
            self.all_square[19, j] = 1
            self.all_square[-1, j] = 1
        for i in range(-1, self.column + 1):
            self.all_square[i, 28] = 1

    def is_dead(self):
        # 判断死亡与否,最上方中间四个方块
        for i in {8, 9, 10, 11}:
            if self.all_square[i, 0]:
                return True
        else:
            return False

    def get_new_square(self):
        # 获得新的方块,初始位置均为(9,-2)
        self.new = random.randrange(1, 8)  # 随机方块
        # 主方块(参考方块)的位置
        self.direction = random.randrange(4)
        self.head_square = [9, -2]
        self.new_square = list(shapedic[self.new])
        for i in range(self.direction):
            self.change()

    def delete_one_line(self, j):
        # 得分后删除整行
        for t in range(j, 2, -1):
            for i in range(self.column):
                self.all_square[i, t] = self.all_square[i, t - 1]
        for i in range(self.column):
            self.all_square[i, 0] = 0

    def get_score(self):
        for j in range(self.row):
            for i in range(self.column):
                # 判断某行是否全满
                if not self.all_square[i, j]:
                    break
            else:
                self.scores += 10
                self.delete_one_line(j)

    # 移动方块停止
    def get_seated(self):
        self.all_square[tuple(self.head_square)] = 1
        for i in range(4):
            self.all_square[self.head_square[0] + self.new_square[i][0],
                            self.head_square[1] + self.new_square[i][1]] = 1

    # 方块是否到了最底端
    def is_seated(self):
        for i in range(4):
            if self.all_square[self.head_square[0] + self.new_square[i][0],
                               self.head_square[1] + self.new_square[i][1] + 1]:
                return True
        return False

    "=== Control Part ==="

    # 改变方块朝向
    # 通过旋转改变,主方块不动
    def change(self):
        if self.new > 1:
            for i in range(4):
                if self.all_square[self.head_square[0] + change_dic[self.new_square[i]][0], self.head_square[1] +
                        change_dic[self.new_square[i]][1]]:
                    return
            else:
                for i in range(4):
                    self.new_square[i] = change_dic[self.new_square[i]]
        else:
            return

    # 右移
    def right_move(self):
        # 先判断是否可以移动
        for i in range(4):
            if self.all_square[self.head_square[0] + self.new_square[i][0] - 1,
                               self.head_square[1] + self.new_square[i][1]]:
                return True
        self.head_square[0] -= 1

    # 左移
    def left_move(self):
        for i in range(4):
            if self.all_square[self.head_square[0] + self.new_square[i][0] + 1,
                               self.head_square[1] + self.new_square[i][1]]:
                return True
        self.head_square[0] += 1

    # 向下加速
    def down_quicker(self):
        while (not self.is_seated()):
            self.draw_new_square()

            self.canvas.after(50)
            self.canvas.update()

    # 方向键控制
    def move(self, event):
        if event.keycode == 39:
            self.left_move()
        elif event.keycode == 38:
            self.change()
        elif event.keycode == 37:
            self.right_move()
        elif event.keycode == 40:
            self.down_quicker()
        else:
            pass

    # 开始游戏
    def play(self):
        self.canvas.bind('<Key>', self.move)
        self.canvas.focus_set()

        while True:
            if self.is_dead():
                self.gameover()
                break

            if self.is_seated():

                self.get_seated()
                self.get_new_square()

                self.draw_score()
                self.draw_square()
                self.draw_new_square()


            else:
                self.draw_new_square()

                self.canvas.after(500)
                self.canvas.update()

    # 游戏结束
    def gameover(self):
        if askquestion("LOSE", u"你输了!\n重新开始吗?") == 'yes':
            return self.restart()
        else:
            return self.window.destroy()

    # 重新开始
    def restart(self):
        self.initial()

        self.draw_square()

        self.get_new_square()

        self.draw_new_square()

        self.play()


# 主程序
if __name__ == "__main__":
    Game_Russia()

注意:这个程序依赖图形界面,要在图形界面上才能正常运行,win和Linux的图形界面都可以。在纯终端命令界面是不能正常运行的。
运行截图如下:
Tetris2


macd11.com 和 丁火甲木庚金 公众号版权所有丨如未注明 , 均为原创丨转载请注明原文链接。
喜欢 (0)
[sp91@qq.com]
分享 (0)

您必须 登录 才能发表评论!