python 俄罗斯方块ai_pygame实现俄罗斯方块游戏(AI篇1)

现在继续

一、定义玩家类

定义玩家类是为了便于进行手动和机器模式或各种不同机器人模式的混合使用,增加代码扩展性。

可以先定义一个玩家基类

class Player(object):

auto_mode=False # 是否是自动模式,自动模式应当不响应键盘操作

def __init__(self):

pass

def run(self): # 进行操作

pass

手动类和机器类继承自Player类

class HumanPlayer(Player):

def __init__(self):

super(Player, self).__init__()

class AIPlayer(Player):

auto_mode=True

def __init__(self):

super(Player, self).__init__()

def run(self):

pass

下面然后游戏代码中做下面三处修改

好了,现在玩家类添加完毕,由于HumanPlayer类的run执行的是pass,原来的操作没有受到影响,下面该去实现AIPlayer的run了

二、贪心计算

方块有N种形态,每种形态有若干种水平位置,假设AI只管方块变形和移动能落得最低位置,越低越好。

首先,我们要将当前游戏界面的方块情况告诉玩家,所以我们在Player类的run函数增加一下panel参数,将panel作为run的参数传入。

AIPlayer的代码大致改成下面这样

class AIPlayer(Player):

cal_block_id=-1 # 用于判断是否方块发生了变化

ctl_arr=[] # 存:1=变、2=左、3=右、4=下,这些数

auto_mode=True

def __init__(self):

super(Player, self).__init__()

def run(self, panel):

if panel.block_id == self.cal_block_id: # block_id没变,按原来计算好的操作规则进行

if len(ctl_arr)>0:

ctl = self.ctl_arr.pop(0)

if ctl == 1: panel.change_block()

if ctl == 2: panel.control_block(-1,0)

if ctl == 3: panel.control_block(1,0)

if ctl == 4:

flag = panel.move_block()

while flag==1:

flag = panel.move_block()

if flag == 9: game_state = 2

else: # block_id变了,计算新方块的操作规则

self.cal_block_id = panel.block_id

matrix = panel.get_rect_matrix()

#matrix.print_matrix() # print for debug

#

# 添加计算操作的逻辑

#

pass

这里为了方便计算将panel中rect_arr转成matrix,一般建议matrix用numpy的,这边的使用场景比较简单,就不增加依赖包了,自己实现一个简单的matrix

class Matrix(object):

rows = 0

cols = 0

data = []

def __init__(self, rows, cols):

self.rows = rows

self.cols = cols

self.data = [0 for i in range(rows*cols)]

def set_val(self, x, y, val):

self.data[y*self.cols+x] = val

def get_val(self, x, y):

return self.data[y*cols+x]

def print_matrix(self):

for i in range(self.rows):

print self.data[self.cols*i:self.cols*(i+1)]

panel的get_rect_matrix是这么实现的

def get_rect_matrix(self):

matrix = Matrix(ROW_COUNT, COL_COUNT)

for rect_info in self.rect_arr:

matrix.set_val(rect_info.x, rect_info.y, 1)

return matrix

为获取不同形态的值,Block类和子类的get_shape函数稍作修改,增加一个输入

class TBlock(Block): # 四种形态

shape_id=0

shape_num=4

def __init__(self, n=None):

super(TBlock, self).__init__()

if n is None: n=random.randint(0,3)

self.shape_id=n

self.rect_arr=self.get_shape()

self.color=(255,0,0)

def get_shape(self, sid=None):

if sid is None: sid = self.shape_id

if sid==0: return [(0,1),(1,1),(2,1),(1,2)]

elif sid==1: return [(1,0),(1,1),(1,2),(0,1)]

elif sid==2: return [(0,1),(1,1),(2,1),(1,0)]

else: return [(1,0),(1,1),(1,2),(2,1)]

计算最优操作的代码如下,大致思路是落下的四个方块的Y值加起来越大越好

def cal_best_arr(self, panel):

matrix = panel.get_rect_matrix()

#matrix.print_matrix() # print for debug

cur_shape_id = panel.moving_block.shape_id

shape_num = panel.moving_block.shape_num

max_score = 0

best_arr = []

for i in range(shape_num):

tmp_shape_id = cur_shape_id + i

if tmp_shape_id >= shape_num: tmp_shape_id = tmp_shape_id % shape_num

tmp_shape = panel.moving_block.get_shape(sid=tmp_shape_id)

center_shape = []

for x,y in tmp_shape: center_shape.append((x+COL_COUNT/2-2,y-2))

minx = COL_COUNT

maxx = 0

miny = ROW_COUNT

maxy = -2

for x,y in center_shape:

if x

if x>maxx: maxx = x

if y

if y>maxy: maxy = y

for xdiff in range(-minx,COL_COUNT-maxx): # 左右可以移动的范围

arr = [1 for _ in range(i)]

if xdiff < 0: [arr.append(2) for _ in range(-xdiff)]

if xdiff > 0: [arr.append(3) for _ in range(xdiff)]

arr.append(4)

for yindex in range(-miny, ROW_COUNT-maxy): # 往下检测碰撞

if matrix.cross_block(center_shape, xdiff=xdiff, ydiff=yindex):

break

score = sum([y+yindex for x,y in center_shape])

#print i,xdiff,yindex,score

if score > max_score:

max_score = score

best_arr = arr

self.ctl_arr = best_arr

大概的AI效果有了,但是发现它还不会考虑造成空洞的影响,下面还要继续优化

三、空洞的惩罚

Matrix类加一个获取空洞数的函数,这里先简单定义为上方有方块为空洞

def get_hole_number(self):

hole_num=0

for x in range(0,self.cols):

for y in range(1,self.rows):

if self.get_val(x,y) == 0 and self.get_val(x

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值