Skip to main content
 首页 » 编程设计

python之挣扎于二进制数组 : python

2025年05月04日11zlslch

我目前正在为一款游戏开发已发布的机器人,希望能学习更多关于编程的知识。不幸的是,当我进入二进制数组的主题时,我添加的一个起初看起来很简单的新命令变得非常困难。基本上,我采用了一个已经制定的命令,您可以在其中将一个项目放置在两个位置,以定义您将要恢复的区域。我对该命令的编辑是,它将允许完全恢复整个 map ,而无需放置任何项目来定义 map 。

在执行恢复命令之前,先执行备份命令,其中二进制数组由整个 map 组成,然后存储在文件中。为了恢复整个 map ,新命令仍然需要处理两点的坐标。一个位于 map 的底角 (0,0,0),然后另一个位于 map 顶部对面的角落,这将始终根据您想要的服务器而有所不同。我解决这个问题的理由是简单地检索每个坐标的二进制数组的长度。不幸的是,我在尝试这样做时运气不佳,而且我真的不知道如何找到二进制数组的维数。显示了数组的打包和解包以及我无法解决的代码部分。

一件奇怪的事情是,如果我像 if 语句那样用那个服务器 ip 地址手动输入数字,bot 会完美运行。只是任何试图编写适用于任何 map 而不仅仅是一张 map 的代码的努力都是徒劳的。

enter code here 
def onBackup(self,user,filename): 
    fn = bakFolder+filename+".backup" 
    try: 
        f = open(fn,"r") 
        self.bot.sendMessage("A backup by that name already exists.") 
        f.close() 
        return 
    except IOError: 
      try: 
        f = open(fn,"wb") 
        f.write(struct.pack("!3i",self.bot.level_x,self.bot.level_y,self.bot.level_z)) 
        self.bot.block_array.tofile(f) 
        self.bot.sendMessage("Backup saved to file %s.backup"%filename) 
        print "Backup save to %s.backup"%filename 
        return 
      except IOError: 
        self.bot.sendMessage("Error opening %s.backup"%filename, false) 
        print "Backup: Error opening file" 
        return 
def restoremap(self): 
    fn = bakFolder+self.restore_filename+".backup" 
    try: 
        f = open(fn,"rb") 
        header_x, header_y, header_z = struct.unpack('!3i',f.read(12)) 
        backup_array = array.array('B') 
        backup_array.fromfile(f,header_x*header_y*header_z) 
        x1,y1,z1 = (0,0,0)  
        if server == "204.232.197.228": 
            x2,y2,z2 = (64,1020,64) #special server that already has coordinates 
        else: 
            x2,y2,z2 = ??? rest of servers, coordinates derived from the binary array 
        if x1 > x2 : x1, x2 = x2, x1 
        if y1 > y2 : y1, y2 = y2, y1 
        if z1 > z2 : z1, z2 = z2, z1 
        tiles_to_deglass = [] 
        tiles_to_build   = [] 
        while x1 <= x2: 
            y = y1 
            while y <= y2: 
                z = z1 
                while z <= z2: 
                    offset = self.bot.calculateOffset(x1,y,z) 
                    current_tile = int(self.bot.block_array[offset]) 
                    backup_tile  = int(backup_array[offset]) 
                    if not ( current_tile == backup_tile): 
                        if (current_tile == 0) and (backup_tile in self.valid_blocks): 
                            tiles_to_build.append((backup_tile,x1,y,z)) 
                        elif (current_tile >= 8) and (current_tile <= 11) and (backup_tile == 0): 
                            ## This deals with water & lava in what used to be empty spaces 
                            ## first we'll glass it all, and then deglass later! 
                            self.blocks.append((20,x1,y,z)) 
                            tiles_to_deglass.append((0,x1,y,z)) 
                        elif backup_tile == 7:##use stone 
                            tiles_to_build.append((0,x1,y,z)) 
                            tiles_to_build.append((1,x1,y,z)) 
                        elif backup_tile in self.valid_blocks: 
                            ## This is the fall through... We'll try to erase 
                            ## the current tile and then restore it to the other state 
                            tiles_to_build.append((0,x1,y,z)) 
                            tiles_to_build.append((backup_tile,x1,y,z)) 
                        elif (backup_tile == 0) and not (current_tile == 0): 
                            tiles_to_build.append((0,x1,y,z)) 
 
                    z+=1 
                y += 1 
            x1 +=1 
        self.DrawBlocks() 
        self.blocks += tiles_to_build 
        self.DrawBlocks() 
        self.blocks += tiles_to_deglass 
        self.DrawBlocks() 
        self.bot.sendMessage("Restoring...",ignorable=True) 
        ##self.bot.action_queue.append(SayAction(self.bot,"Done restoring.")) 
        self.onReset(silent=True) 
 
    except IOError: 
        self.bot.sendMessage("Error while restoring (couldn't read file).") 

请您参考如下方法:

似乎您唯一使用 x2,y2,z2 的地方是在这些循环中对 x1,y 和 z 设置限制:

    while x1 <= x2: 
        y = y1 
        while y <= y2: 
            z = z1 
            while z <= z2: 
                offset = self.bot.calculateOffset(x1,y,z) 
                current_tile = int(self.bot.block_array[offset]) 
                ... 
                z+=1 
            y += 1 
        x1 +=1 

如果您将 x2 设置得太大会怎样?你有异常(exception)吗?如果是这样, 也许您可以简单地捕获异常以找出 x2 的大小。 例如:

    x2=y2=z2=None 
    while x2 is None or x1<=x2: 
        y = y1 
        while y2 is None or y<=y2: 
            z = z1 
            while z2 is None or z<=z2: 
                try: 
                    offset = self.bot.calculateOffset(x1,y,z) 
                    current_tile = int(self.bot.block_array[offset]) 
                except Exception: #<-- Change to most specific exception possible 
                    if z2 is None: 
                        z2=z-1 
                    elif y2 is None: 
                        y2=y-1 
                    elif x2 is None: 
                        x2=x1-1 
                    break 
                ... 
                z+=1 
            y += 1 
        x1 +=1 

俗话说,it's easier to ask for forgiveness than permission .


附言。要找出要捕获的特定异常,请删除上面的 try 和 except 并运行脚本,让它失败。回溯错误消息的最后一行告诉您引发的异常类型。例如,它可能会说类似的话

IndexError: x,y,z out of bounds 

在这种情况下,添加 try 和 except 将 Exception 更改为 IndexError。