Math 用大小逐渐减小的数字框填充网格

Math 用大小逐渐减小的数字框填充网格,math,geometry,2d,Math,Geometry,2d,有一个有趣的游戏,在网格中有数字,每个数字都有逐渐变小的字体。玩家的任务是连续点击数字 我对创建数字框的算法感兴趣,我想不出它的工作方式 显然,网格有N个数字(除了图中的1.88),数字1的字体最大,字体大小也随之减小。然后,数字以某种方式放置在网格上,框围绕着它们生长。但它似乎不是完全随机的,因为有一些水平线穿过整个网格 你知道这是怎么回事吗 在我看来,这些方框似乎是通过连续的除法生成的。也就是说,从完整的矩形开始,放置一条分界线(水平或垂直),然后依次细分得到的两个矩形,直到游戏中有足够的矩

有一个有趣的游戏,在网格中有数字,每个数字都有逐渐变小的字体。玩家的任务是连续点击数字

我对创建数字框的算法感兴趣,我想不出它的工作方式

显然,网格有N个数字(除了图中的1.88),数字1的字体最大,字体大小也随之减小。然后,数字以某种方式放置在网格上,框围绕着它们生长。但它似乎不是完全随机的,因为有一些水平线穿过整个网格

你知道这是怎么回事吗


在我看来,这些方框似乎是通过连续的除法生成的。也就是说,从完整的矩形开始,放置一条分界线(水平或垂直),然后依次细分得到的两个矩形,直到游戏中有足够的矩形

这是我要尝试的第一个算法的草图。N是我想要将原始矩形分割成的矩形的数量,A是用于阻止小矩形变得太窄的关键纵横比。(也许A=1.5将是一个良好的开端。)

  • 创建一个空的矩形并将其添加到完整的矩形中

  • 如果优先级队列的长度大于或等于N,请停止

  • 从优先级队列中删除最大的矩形R

  • 选择是水平分割还是垂直分割:如果其纵横比(宽度/高度)大于A,则垂直分割;如果小于1/A,则水平分割,否则随机选择

  • 决定把分界线放在哪里。(沿所选尺寸,可能随机介于40%和60%之间。)

  • 这将R分成两个较小的矩形。将它们都添加到优先级队列中。转至步骤2

  • 当此算法完成时,队列中有N个矩形。把数字1放在其中最大的一个,把数字2放在第二个,依此类推

    事实证明,将数字放入框中并不像我第一次尝试时想象的那样简单。面积度量可以很好地细分矩形,但无法将数字放入框中,因为要将文本放入框中,必须同时考虑高度和宽度(面积不是很有用)

    我将不解释将数字放入框中的算法,而是给您一些Python示例代码,让您对其进行反向工程

    导入heapq、itertools、随机
    导入图像、ImageDraw、ImageFont
    #算法参数
    纵横比_max=1.5#高于此比率,始终垂直分割
    纵横比_min=1.0#低于此比率时,始终水平分割
    div_min=0.4#分界线的最小位置
    div_max=0.6#分界线的最大位置
    数字比=0.7#字体中最宽数字的纵横比
    标签_边距=2#标签周围的边距(像素)
    类矩形(对象):
    定义初始值(self,x,y,w,h):
    self.x=x
    self.y=y
    self.w=w
    self.h=h
    self.area=self.w*self.h
    self.aspect=浮动(self.w)/self.h
    定义(自我、其他):
    #这种比较的意义是颠倒的,所以我们可以
    #矩形变成一个最小的堆,并且能够弹出最大的。
    返回other.area aspect\u max
    或r.aspect>aspect\u min
    和random.random()<0.5):
    #垂直分割
    w=除法(r.w)
    heapq.heappush(队列,矩形(r.x,r.y,w,r.h))
    heappush(队列,矩形(r.x+w,r.y,r.w-w,r.h))
    其他:
    #水平分割
    h=除法(r.h)
    heapq.heappush(队列,矩形(r.x,r.y,r.w,h))
    heappush(队列,矩形(r.x,r.y+h,r.w,r.h-h))
    排队时:
    产量heapq.heappop(队列)
    def字体高度(自身,n):
    """
    返回最大字体高度,以便我们可以绘制'n`
    这个矩形中的数字。
    """
    返回最小值(int((self.w-label_margin*2)/(digital_ratio*n)),
    self.h-标签(页边距*2)
    def draw_矩形(矩形、fontfile):
    """
    创建并返回包含“矩形”的图像。标记每个矩形
    带有数字的矩形,使用“fontfile”中的TrueType字体。
    """
    矩形=列表(矩形)
    im=图像。新('RGBA',(1+最大值(矩形中r的r.x+r.w),
    1+最大值(矩形中的r的r.y+r.h)))
    draw=ImageDraw.draw(im)
    对于itertools.count(1)中的数字:
    矩形=已排序(矩形,
    key=lambda r:r.font\u高度(数字),
    反向=真)
    i_min=10**(数字-1)
    i_max=10**位
    i_范围=i_最大值-i_最小值
    对于X范围内的i(i_范围):
    如果i>=len(矩形):返回im
    r=矩形[i]
    画线((r.x,r.y,r.x+r.w,r.y,r.x+r.w,r.y+r.h,
    r、 x,r.y+r.h,r.x,r.y),
    填充=黑色,宽度=1)
    标签=str(i+i_最小值)
    font=ImageFont.truetype(字体文件,r.font\U高度(数字))
    lw,lh=font.getsize(标签)
    text((r.x+(r.w-lw)//2,r.y+(r.h-lh)//2),
    标签,填充='黑色',字体=字体)
    矩形=矩形[i_范围:]
    
    下面是一个运行示例:

    >>> R = Rectangle(0, 0, 400, 400)
    >>> draw_rectangles(R.divide(30), '/Library/Fonts/Verdana.ttf').save('q10009528.png')
    

    在我看来,这些方框似乎是通过连续的除法生成的。也就是说,从完整的矩形开始,放置一条分界线(水平或垂直),然后放置两条分界线