【问题标题】:struggling with binary arrays: python与二进制数组作斗争:python
【发布时间】:2011-04-01 10:30:26
【问题描述】:

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

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

一个奇怪的事情是,如果我像 if 语句那样手动输入数字,使用那个服务器 IP 地址,机器人就可以完美运行。只是任何努力编写适用于任何地图的代码而不仅仅是一张地图都没有结果。

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不应该和header_x,header_y,header_z一样吗?
  • 其实答案可能是 header_x,y,z 的 len

标签: python arrays binary


【解决方案1】:

您使用 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 设置得过大会怎样?你有例外吗?如果是这样, 也许您可以简单地捕获异常以找出 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


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

IndexError: x,y,z out of bounds

在这种情况下,将tryexcept 重新添加,将Exception 更改为IndexError

【讨论】:

    【解决方案2】:

    考虑长度1024;这可以变成(x,y,z):

    2  2  256
    2  4  128
    2  8   64
    2 16   32
    2 32   16
    ...
    128 4  2
    256 2  2
    

    即使数组的长度是1001,你也不会得到非常友好的答案:

     7 11 13
    11  7 13
     7 13 11
    11 13  7
    13 11  7
    13  7 11
    

    因此,您保存的文件必须包含每个特定地图的 (x, y, z) 坐标。

    看起来onBackup() 例程将bot 的坐标保存在前三个整数位置(每个四个字节)。您可以通过将机器人移动到地图的最远范围来扩展此程序,然后然后保存坐标。或者你可以看看服务器是否可以以某种方式报告地图的范围,并捕获信息。

    但我认为你不能只猜测给定输入数组的维度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-01
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多