基于Pierre Dellacherie算法实现俄罗斯方块的人工智能(python实现)《二》

基于Pierre Dellacherie算法实现俄罗斯方块的人工智能(python实现)《二》

  • 本文章将会说明,把俄罗斯方块从面向过程到面向对象的改进,以及个性化功能的添加
  • 个性化功能包括:
    • 暂停
    • 重新开始
    • 结束动画
    • AD广告板
    • 显示下一个
  • 面对对象的设计我主要分为三个类:WallHouseWorker,和Brick
  • 下面一个一个类来说明

1. Wall类

  • 有些简单的功能我只提一提函数名,需要讲解的话请评论
class Wall():
    global GRID_NUM_WIDTH
    global LINE_COLOR
    global HEIGHT
    global HEIGHT

    def __init__(self):
        pass
    # 绘制背景格子
    def draw_grids(self):
        pass
    # 根据颜色矩阵绘制格子
    def draw_matrix(self):
        pass
    # 满行消除
    def remove_full_line(self):
        pass
    # 欢迎界面
    def show_welcome(self):
        pass
  • 展示文字,上一章说到这个函数我修改了,是因为我有时候也想显示文字的背景色

    def show_text(self, text, size, x, y, color=(0xff, 0xff, 0xff),bgColor = None):

        fontObj = pygame.font.Font('font/font.ttc', size)
        textSurfaceObj = fontObj.render(text, True, color,bgColor)
        textRectObj = textSurfaceObj.get_rect()
        textRectObj.center = (x, y)
        screen.blit(textSurfaceObj, textRectObj)
  • 写分
  • 新增了个性化功能:最高分,我用最简单的方法实现,直接把最高分写进一个txt文件,开始游戏的时候读取即可
    def draw_score(self):
        global heightScore
        self.show_text( u'得分 : {}'.format(score), 18, WIDTH + SIDE_WIDTH // 2, 180)

        if heightScore is None:
            self.getHeightScore()

        if score>heightScore:
            heightScore = score

        self.show_text( u'level : {}  最高分 : {}'.format(level,heightScore), 15, WIDTH + SIDE_WIDTH // 2, 205)

    # 暂停界面的显示
    def showPause(self):
        GREEN = ( 0, 255, 0)
        BLUE = ( 0, 0, 128)
        self.show_text(u'暂停中...', 50, 250, 200, BLUE , GREEN)
        pygame.display.update()
    # 因为文字描述(最高分,当前分,基本操作提示以及等级)多了,所以我干脆封装一个函数全部显示这些东西
    def drawAll(self):
        # 更新屏幕

        screen.fill(BLACK)
        self.draw_grids()
        self.draw_matrix()
        self.draw_score()
        self.drawNextBrick()

        self.show_text( u'再来一次:R',13, WIDTH+100,HEIGHT-140 , WHITE )
        self.show_text( u'我要暂停:P',13, WIDTH+100,HEIGHT-120 , WHITE )
        self.show_text( u'我要变形:↑',13, WIDTH+100,HEIGHT-100 , WHITE )
        self.show_text( u'左右移动: ← or →',13, WIDTH+100,HEIGHT-80 , WHITE )
        self.show_text( u'下落一步:↓',13, WIDTH+100,HEIGHT-60 , WHITE )
        self.show_text( u'一步到底:SPACE',13, WIDTH+100,HEIGHT-40 , WHITE )
        self.show_text( u'Author:Charming(2018.4)',13, SCREEN_WIDTH-100,HEIGHT-10 , WHITE )

        # 个性化功能-AD广告板,当我暂停的时候,广告板的文字会变,更具趣味性
        if pause :
            self.showAD(u'突然暂停', u'害怕了吗')
        else:
            self.showAD()




        if live_cube is not None:
            live_cube.draw()

        if gameover:
            self.show_welcome()
  • 个性化功能-显示下一个。显示下一个的设计原理非常简单,因为我一开始的设计是,当上一个方块下落完成之后再生成一个新的,现在是一开始就生成两个新的Brick对象,分别是new_cubelive_cube,然后当上一个下落完成之后,把new_cube赋值给live_cube,然后再生成新的new_cube即可
    # 绘制下一个方块
    def drawNextBrick(self):
        global new_cube
        if new_cube is not None:
            new_cube.drawNext()
    # 读取文件,获取最高分
    def getHeightScore(self):
        global heightScore
        f = open('score.txt', 'r')
        heightScore = int( f.read() )
    # 把最高分写入文件
    def writeHeightScore(self):
        global heightScore
        f = open('score.txt', 'w')
        f.write( str(heightScore) )
        f.close()
    # 显示广告板
    def showAD(self,text1 = None , text2 = None):
        global CUBE_COLORS
        global colorBool

        line1 = ['哇塞萌新', '运气好而已', '回去吧', '是不是快挂了', '年轻人不简单', '哇塞!!', '围观大佬']
        line2 = ['你会玩吗', '狗屎运而已', '后面太难了', '哈哈哈', '看走眼了', '这样都行?', '大佬请喝茶']
        if level > len(line1):
            num = len(line1)-1
        else:
            num = level
        if text1 is None and text2 is None:
            if gameover:
                text1 = u'广告位招租'
                text2 = u'非诚勿扰'
            else:
                text1 = line1[num - 1].decode('utf-8')
                text2 = line2[num - 1].decode('utf-8')

        GREEN = (0, 255, 0)
        # 广告底板和边框
        pygame.draw.rect(screen, BLACK,
                         (WIDTH + 20, 240,
                          160, 80))
        pygame.draw.rect(screen, GREEN,
                         (WIDTH + 20, 240,
                          160, 80), 1)
        # 这里有一个彩蛋,当你正常运行程序时,按c键,广告板的文字会闪动
        if colorBool :
            color = CUBE_COLORS[num]
        else :
            color =  CUBE_COLORS[random.randint(0, len(CUBE_COLORS) - 1)]
        # 广告的文字信息
        self.show_text( text1,18, WIDTH+100,265 , color )
        self.show_text( text2,18, WIDTH+100,295 , color )

Brick类

与上一章的CubeShape类类似,代码略

    # 在特定的位置绘制下一方块
    def drawNext(self):
        for cube in self.get_all_gridpos((0,0)):
            pygame.draw.rect(screen, self.color,
                             (cube[1] * GRID_WIDTH+WIDTH+100, cube[0] * GRID_WIDTH+70,
                              GRID_WIDTH, GRID_WIDTH))
            pygame.draw.rect(screen, WHITE,
                             (cube[1] * GRID_WIDTH+WIDTH+100, cube[0] * GRID_WIDTH+70,
                              GRID_WIDTH, GRID_WIDTH),1)

HouseWorker类

下面是最长的代码,也是最重要的逻辑部分,大家可以喝杯茶冷静下再来看

  • 这里特别说明一下dead参数和gameover参数,gameover是指整个游戏运行的结束,dead只是指当前游戏的结束,因为游戏结束还有结束动画,当显示结束动画是dead已经为True,但是gameover仍为False,所以要加入dead参数加以区分
# 这些是全局参数,参数指结束动画的初始位置和xy方向的速度
x, y = 10., 10.
speed_x, speed_y = 133., 170.
class HouseWorker():
    # 开始游戏
    # 开始游戏没得说的,就是初始化好各种参数
    def start(self):
        global gameover
        global live_cube
        global new_cube
        global score
        global screen_color_matrix
        gameover = False
        live_cube = Brick()
        new_cube = Brick()
        score = 0
        screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
        pass
    # 暂停操作
    # 暂停就是改变pause的值,具体的情况看whenPause函数
    def pause(self):
        global pause
        if pause:
            pause = False
        else :
            pause = True
  • 为了当暂停时能够显示闪动的提示信息,可视窗口有两种状态,带暂停提示的信息的游戏界面,和正常但是静止了的游戏界面。用pause_count来决定不同时候窗口的不同状态即可
  • 暂停时依然能够重新开始游戏和退出游戏,所以需要监察键盘的P,R,ESC三个按键的操作
    # 当暂停时
    def whenPause(self):
        # 暂停动画
        global pause_count
        global score
        global live_cube
        global level
        global screen_color_matrix
        global colorBool
        global dead
        pause_count += 1
        if pause_count % FPS > 10 and pause_count % FPS < 20:
            w.drawAll()
        else:
            w.showPause()

        pygame.display.update()
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_p:
                    hw.pause()
                elif event.key == pygame.K_ESCAPE:
                    hw.pause()
                    w.writeHeightScore()
                    # 退出pygame
                    pygame.quit()
                    # 退出系统
                    sys.exit()
                #   重新开始
                elif event.key == pygame.K_r:
                    w.writeHeightScore()
                    hw.pause()
                    score = 0
                    live_cube = Brick()
                    level = 1
                    dead = False
                    screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
                # ad广告板闪动的彩蛋
                elif event.key == pygame.K_c:
                    if colorBool :
                        colorBool = False
                    else:
                        colorBool = True
                else:
                    pass
  • 正常运行时,
    # 当正常时
    def whenNormal(self):
        global score
        global live_cube
        global level
        global screen_color_matrix
        global gameover
        global running
        global counter
        global new_cube
        global colorBool
        global dead
        # 正常运行时
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN and pause == False:
                # 初始化是gameover是True,会显示欢迎界面
                if gameover:
                    # hw.start()函数包括把gameover改成False的操作
                    hw.start()
                    break
                # 上下左右的监控
                if event.key == pygame.K_LEFT:
                    live_cube.left()
                elif event.key == pygame.K_RIGHT:
                    live_cube.right()
                elif event.key == pygame.K_DOWN:
                    live_cube.down()
                elif event.key == pygame.K_UP:
                    live_cube.rotate()
                elif event.key == pygame.K_SPACE:
                    while live_cube.down() == True:
                        pass
                elif event.key == pygame.K_ESCAPE:
                    w.writeHeightScore()
                    # 退出pygame
                    pygame.quit()
                    # 退出系统
                    sys.exit()
                #   重新开始
                elif event.key == pygame.K_r:
                    w.writeHeightScore()
                    score = 0
                    live_cube = Brick()
                    new_cube = Brick()
                    colorBool = True
                    dead = False
                    level = 1
                    screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
                elif event.key == pygame.K_c:
                    if colorBool :
                        colorBool = False
                    else:
                        colorBool = True
                elif event.key == pygame.K_p:
                    hw.pause()

        # 判断是否结束函数和执行down动作
        if gameover is False and counter % (FPS // level) == 0:
            if live_cube.down() == False:
                for cube in live_cube.get_all_gridpos():
                    screen_color_matrix[cube[0]][cube[1]] = live_cube.color
                live_cube = new_cube
                new_cube = Brick()
                # 这里游戏结束
                # 这里是到顶的意思
                if live_cube.conflict(live_cube.center):
                    w.writeHeightScore()
                    dead = True
                    gameover = True
                    colorBool = False

            # 消除满行
            w.remove_full_line()

        # 计时作用
        counter += 1

        if not dead:
            w.drawAll()
            pygame.display.update()
  • 当游戏结束的时候
    def whenGameOver(self):
        global score
        global live_cube
        global new_cube
        global level
        global screen_color_matrix
        global colorBool
        global dead
        global speed_x
        global speed_y
        global SCREEN_WIDTH
        global x
        global y

        # 以下部分是结束动画的弹动,没有封装成函数是我的错。
        GREEN = (0, 255, 0)
        BLUE = (0, 0, 128)
        w.drawAll()
        w.showAD(u'挂了挂了', u'哈哈哈')
        w.show_text(u'Game Over', 50, x, y, BLUE, GREEN)
        w.show_text(u'按任意键重新开始', 25, x, y+38, BLUE, GREEN)

        time_passed = clock.tick(30)
        time_passed_seconds = time_passed / 1000.0

        x += speed_x * time_passed_seconds
        y += speed_y * time_passed_seconds

        # 到达边界则把速度反向
        if x > SCREEN_WIDTH - 150:
            speed_x = -speed_x
            x = SCREEN_WIDTH - 150
        elif x < 150:
            speed_x = -speed_x
            x = 150.

        if y > HEIGHT-38 - 25:
            speed_y = -speed_y
            y = HEIGHT-38 - 25
        elif y < 25:
            speed_y = -speed_y
            y = 25.
        pygame.display.update()
        # 结束动画的弹动到这里结束

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if gameover and dead:
                    dead = False
                    colorBool = True
                    hw.start()
                    break
                if event.key == pygame.K_ESCAPE:
                    # 退出pygame
                    pygame.quit()
                    # 退出系统
                    sys.exit()
                #   重新开始
                elif event.key == pygame.K_r:
                    w.writeHeightScore()
                    score = 0
                    live_cube = Brick()
                    new_cube = Brick()
                    level = 1

                    colorBool = True
                    dead = False
                    screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
                elif event.key == pygame.K_c:
                    if colorBool:
                        colorBool = False
                    else:
                        colorBool = True
                else:
                    pass

 游戏的主逻辑

之所以叫游戏的主逻辑是因为我不知道怎么命名。。。

# 新建两个类
w =  Wall()
hw = HouseWorker()

while running:
    # 设定帧数
    clock.tick(FPS)

    # 暂停时的事件循环
    if pause == True:
        hw.whenPause()
        continue
    if dead:
        hw.whenGameOver()
        continue
    # 正常时的事件循环
    hw.whenNormal()
  • 至此本章内容全部结束,下一章是为这个代码加上人工智能功能。

你可能感兴趣的:(python)