当前位置 主页 > 网站技术 > 代码类 >

    pygame实现俄罗斯方块游戏(AI篇2)

    栏目:代码类 时间:2019-10-29 21:10

    继续pygame实现俄罗斯方块游戏(AI篇1)的代码更新

    一、消除后才做评价

    上一篇我们是对方块落下的位置和落下后出来的空洞进行了评价,但是这些评价都是没有计算消除的,以至于机器人现在不会考虑去进行那些完全不会留下空洞的消除,比如下面这种消除。

    但我们知道这种消除是不会产生空洞的。
    所以我们要在计算评价的时候最好计算消除以后的评价。
    我们只要在Matrix的函数里加一个do_clear函数来进行消除

    def do_clear(self):
     for i in range(self.rows-1,-1,-1):
      if sum(self.cols*i:self.cols*(i+1))==self.cols:
      self.matrix[self.cols:self.cols*(i+1)]=self.matrix[0:self.cols*i]

    然后在clone_matrix.fill_block(center_shape, xdiff=xdiff, ydiff=max_yindex)之后加一行

    clone_matrix.do_clear()

    现在机器人比以前聪明了一点,但是还有问题,只要有下面两个问题:

    1.当有更好的消除方案时,机器人并没有选择更好的方案(比如可以消除两行,但是机器人选择了消除一行)。
    2.人玩的时候会避免空的列两边堆叠太高,而是优先在远离空的列附近填。

    下面我们进行这些修改。

    二、消除时考虑获得更高分

    我们在Matrix的do_clear函数里增加一个clear_num来计算消除了多少行

    def do_clear(self):
     clear_num = 0
     for i in range(self.rows-1,-1,-1):
     if sum(self.data[self.cols*i:self.cols*(i+1)])==self.cols:
     self.data[self.cols:self.cols*(i+1)]=self.data[0:self.cols*i]
     clear_num+=1
     return clear_num

    在计算的地方加这样两行

    clear_num=clone_matrix.do_clear()
    score += clear_num * 5

    这样每多消除一行会多得到5分,会激励机器人在单次消除中去寻找更好的消除方案。

    三、避免空列附近的填塞

    首先空列的定义,我们可以认为像下面的图中,1的位置还不能算完全的空列,因为列右侧高起的是两格,拯救的机会比2处大很多,2处两边都已经高起3格,再这样下去只有等长条了。

    所以我们在Matrix里加一个空列的获取函数

    def get_empty_col(self):
     miny_arr=[]
     for x in range(self.cols):
     miny=19
     for y in range(self.rows):
     miny=y
     if self.get_val(x,y) == 1:break
     miny_arr.append(miny)
     empty_arr=[]
     if miny_arr[1] - miny_arr[0] > 2: empty_arr.append((self.cols,miny_arr[1] - miny_arr[0]))
     if miny_arr[self.cols-2] - miny_arr[self.cols-1] > 2: empty_arr.append((miny_arr[self.cols-2] - miny_arr[self.cols-1],self.cols))
     for x in range(1,self.cols-1):
     if miny_arr[x-1]-miny_arr[x]>2 or miny_arr[x+1]-miny_arr[x]>2: empty_arr.append((miny_arr[x-1]-miny_arr[x],miny_arr[x+1]-miny_arr[x]))
     return empty_arr

    在AIPlayer里增加一个get_cost_of_emptycol函数

    def get_cost_of_emptycol(self, empty_arr):
     cost = 0
     for l,r in empty_arr:
     if l>2 and r>2: cost += (l+r)*2
     elif l>2: cost += l
     else: cost += r
     return cost

    在计算分数的地方增加两行程序

    empty_arr = clone_matrix.get_empty_col()
    score -= self.get_cost_of_emptycol(empty_arr)