【问题标题】:ASCII art in PythonPython中的ASCII艺术
【发布时间】:2012-10-25 19:54:35
【问题描述】:

我对 python 很陌生,把它作为一种爱好来学习,通过一些搜索发现自己有一堆来自“计算实践”的练习,其中一个问关于写作一个 ASCII 数字,如下所示。

这一切似乎都是一个简单的练习,但我似乎无法用数字来画这个,练习表明上面的画是通过使用数字“1”绘制的。

它还指出,任何小于 0 或大于 100 的数字都不能或不应该用于创建 ASCII 绘图。

这是另一个例子:

这里的输入是数字“2”。

我找到了一种让第一张图片出现的方法,但不是通过以任何方式使用给定的数字,只是在 while 循环中使用一个简单的“else”,这样我就可以过滤掉下面的数字或等于 0 或更高或等于 100。

我已经死机了。

如上所述,我的代码不使用变量号来创建第一张图纸:

while True:
s = input("Give me a number to make a drawing with that is between 0 and 100: ")


if not s.isdigit():
    print ("Error, only numbers will make this program run.")
    continue #Try Again but with a number this time

if int(s) >= 100:
    print ("The number is bigger than or equal to 100 and won't work. \nDo try again.")
    continue #try again

if int(s) <= 0:
    print ("The number is smaller than or equal to 0 and won't work. \nDo try again.")
    continue #try again

else:
    print ("%5s" %("*" *3),"\n"'%5s' %("* *"),"\n" '%7s' %("*** ***"),"\n" '%7s' %("*     *"),"\n" '%7s' %("*** ***"),"\n" '%5s' %("* *"),"\n" '%5s' %("*" *3))


    print ('Want to make another drawing ?')
    continue #make another drawing

练习陈述如下:

$n$ 大小的 ASCII 图形由一行或多行组成。在每一行上只允许空格和星号 (*),在一行上的每个星号之后不允许有空格,因此您应该以“\n”或换行符结尾。然后是上面的例子。

我的新代码示例依赖于变量输入: 另外,在这个代码示例中,它设置为在输入为 1 时触发,当我增加输入数字时,我仍然遇到“放大”整个绘图的问题。

    while True:

 A = input("Give me a number to make a drawing with that is between 0 and 100: ")
 b = "***"
 c = "*"
 d = " "


 if not A.isdigit():
        print ("Error, only numbers will make this program run.")
        continue #Try Again but with a number this time

 if int(A) >= 100:
        print ("The number is bigger than or equal to 100 and won't work. \nDo try again.")
        continue #try again

 if int(A) <= 0:
        print ("The number is smaller than or equal to 0 and won't work. \nDo try again.")
        continue #try again


 else :
  range(1,99)
 if int(A) == (1) :
  print ((d *((int(A))*2)) + b,)
  print ((d *((int(A))*2))+ c + d + c,)
  print ((d *((int(A))*0))+ b + d + b,)
  print ((d *((int(A))*0))+ c + d*5 + c,)
  print ((d *((int(A))*0))+ b + d + b,)
  print ((d *((int(A))*2))+ c + d + c,)
  print ((d *((int(A))*2)) + b,)

  continue #try again

但我仍然有一个问题,即 ASCII 数字内的空格数随着从 1 到 2 的增加而“增加”。

因为我也遇到了第 3 行的问题,因为它需要沿着控制台的侧面表示,它应该与侧面有 0 的间距,但它必须增加到 2 的间距数字 2。

【问题讨论】:

  • 我认为如果我们完成整个练习会有所帮助
  • 练习陈述如下: 一个大小为 $n$ 的 ASCII 图形由一行或多行组成。在每一行上只允许空格和星号 (*),在一行上的每个星号之后不允许有空格,因此您应该以“\n”或换行符结尾。然后是上述示例。
  • 我为横幅找到了 this。还有here.
  • @fp:有关横幅,请参阅Is there a python library that allows to easily print ascii-art text?。但这与当前问题无关
  • @fp 是的,我之前已经找到了这些,但其中一个在“table”e 中有一个看似语法错误,而另一个与我的几乎不一样。但仍然感谢任何帮助或提示。

标签: python ascii


【解决方案1】:

想想 1 和 2 之间的区别。试着用手画出 3 和 4 应该是什么样子才能使序列正常工作。把它想象成一个问题,你得到一个序列的开始,你必须处理剩下的问题。

喜欢:

0 1 1 2 3 5 8 13

如果您没有立即识别,那就是斐波那契数列。一旦你弄清楚了模式,你就可以编写任意长的值序列。

想想这个简单的 ascii 序列:

1)

#

2)

##
#

3)

###
##
#

4) 是什么样子的?

或另一个 ascii 序列:

1)

#

2)

 #
# #
 #

3)

  #
 # #
#   #
 # #
  #

什么是(4)?

如果仍然没有意义,请尝试设计一些您自己的递归形状,这些形状与您要弄清楚的形状有点相似(可能类似于我的第二个示例)。现在不要担心如何编码,只需担心输出应该是什么。然后查看模式并得出一个算法。

【讨论】:

  • 是的,这很容易理解,但我的练习中的顺序似乎一次又一次地让我难以理解,我感觉自己无法掌握。另外,让我的笼子嘎嘎作响的是我如何“增加”星星之间的间距以适应“2”。
  • 我的附加示例有帮助吗?
  • 很遗憾,没有。我只是坚持用那个可变数字创建那些空间和星星的前提,我的意思是我不知道如何创建,例如你的数字 2,在第一个“星星”之前的那些空间,然后放一个“在这些空格后面加星号。
  • 我的例子有意义吗?如果是这样,请尝试再发明一些自己的东西,直到得到问题示例。否则你可能想睡在上面。
  • 我已经走得更远了,并且找到了一种使算法依赖的方法,愚蠢的是我没有想到只是将星星命名为空格作为字符串并使用字符串而不是 ,所以我使用 a = ""。我已经用我现在拥有的程序更新了我的帖子,但是当出现更大的数字时,我仍然坚持添加这些空格,我没有看到两颗星之间的空间增加与数字 1 到 2。
【解决方案2】:

首先,逐行分析图形以识别不同类型的模式。

  • 帽子,仅出现在顶行和底行。它是任意数量的空格,后跟三颗星。
  • 构成图形垂直部分的墙。它是任意数量的空格,后跟一颗星,然后是任意数量的空格,然后是一颗星。
  • 地板,构成图形的水平部分。它是任意数量的空格,后跟三颗星,然后是任意数量的空格,然后是三颗星。

我们可以编写一个函数来打印这些模式中的每一个。

def cap(spacesBefore):
    print " " * spacesBefore + "***"

def wall(spacesBefore, spacesBetween):
    print " " * spacesBefore + "*" + " " * spacesBetween + "*"

def floor(spacesBefore, spacesBetween):
    print " " * spacesBefore + "***" + " " * spacesBetween + "***"

接下来,编写代码以显示大小为 0、1 和 2 的图形。这将使您了解如何显示任意大小的图形。

#size 0
cap(0)
wall(0,1)
cap(0)

print "\n"

#size 1
cap(2)
wall(2, 1)
floor(0, 1)
wall(0, 5)
floor(0, 1)
wall(2, 1)
cap(2)

print "\n"

#size 2
cap(4)
wall(4, 1)
floor(2, 1)
wall(2, 5)
floor(0, 5)
wall(0, 9)
floor(0, 5)
wall(2, 5)
floor(2, 1)
wall(4, 1)
cap(4)

输出:

***
* *
***


  ***
  * *
*** ***
*     *
*** ***
  * *
  ***


    ***
    * *
  *** ***
  *     *
***     ***
*         *
***     ***
  *     *
  *** ***
    * *
    ***

分析用于制作这些数字的代码,一些模式变得明显。对于大小为 N 的图形:

  • 两个端盖前面都有 N*2 个空格。
  • 有2*N+1条墙线。
  • 有 2*N 条地板线。
  • 该图的前半部分和后半部分是镜像。
  • 每条墙线的前面空格数从 N*2 开始,然后缩小 2 直到达到零;然后它再次增长 2,直到再次达到 N*2。
  • 墙之间的空间数量从 1 开始,增加 4 直到达到 4*N+1;然后它再次缩小 4,直到再次达到 1。
  • 每层前面的空格数从 2N-2 开始,然后缩小 2 直到为零;然后它再次增长 2,直到再次达到 2N-2。
  • 楼层之间的空间数从1开始,增加4直到达到4*N-3;然后它再次缩小 4,直到再次达到 1。

图案全部以线性速率增长和收缩,然后以线性速率收缩和增长。这意味着我们应该使用两个条件相反的for 循环,并为帽子和中心墙添加一些额外的代码。

def draw(N):
    cap(2*N)
    for i in range(N):              #loop from 0 to N-1
        wall(2*(N-i), 1+(4*i))
        floor(2*(N-i-1), 1+(4*i))
    wall(0, 4*N+1)
    for i in range(N-1, -1, -1):    #loop from N-1 to 0
        floor(2*(N-i-1), 1+(4*i))
        wall(2*(N-i), 1+(4*i))
    cap(2*N)

现在测试代码。

for i in range(7,10):
    draw(i)
    print "\n"

输出:

              ***
              * *
            *** ***
            *     *
          ***     ***
          *         *
        ***         ***
        *             *
      ***             ***
      *                 *
    ***                 ***
    *                     *
  ***                     ***
  *                         *
***                         ***
*                             *
***                         ***
  *                         *
  ***                     ***
    *                     *
    ***                 ***
      *                 *
      ***             ***
        *             *
        ***         ***
          *         *
          ***     ***
            *     *
            *** ***
              * *
              ***


                ***
                * *
              *** ***
              *     *
            ***     ***
            *         *
          ***         ***
          *             *
        ***             ***
        *                 *
      ***                 ***
      *                     *
    ***                     ***
    *                         *
  ***                         ***
  *                             *
***                             ***
*                                 *
***                             ***
  *                             *
  ***                         ***
    *                         *
    ***                     ***
      *                     *
      ***                 ***
        *                 *
        ***             ***
          *             *
          ***         ***
            *         *
            ***     ***
              *     *
              *** ***
                * *
                ***


                  ***
                  * *
                *** ***
                *     *
              ***     ***
              *         *
            ***         ***
            *             *
          ***             ***
          *                 *
        ***                 ***
        *                     *
      ***                     ***
      *                         *
    ***                         ***
    *                             *
  ***                             ***
  *                                 *
***                                 ***
*                                     *
***                                 ***
  *                                 *
  ***                             ***
    *                             *
    ***                         ***
      *                         *
      ***                     ***
        *                     *
        ***                 ***
          *                 *
          ***             ***
            *             *
            ***         ***
              *         *
              ***     ***
                *     *
                *** ***
                  * *
                  ***

【讨论】:

    【解决方案3】:

    要找到图案,您可以想象turtle 将如何绘制它。例如,绘制:

    ***
    * *
    ***
    

    乌龟可以遵循以下说明:

    • 右转,前进
    • 右转,前进
    • 右转,前进
    • 右转,前进

    作为 Python 程序:

    import turtle
    
    turtle.right(90); turtle.forward(50)
    turtle.right(90); turtle.forward(50)
    turtle.right(90); turtle.forward(50)
    turtle.right(90); turtle.forward(50)
    turtle.exitonclick() # leave GUI open until a click
    

    如果我们将“右转”缩写为'r',将“向前”缩写为"f",则说明如下:

    'rfrfrfrf'
    

    很容易看出是'rf' * 4。遵循相同的程序:

      ***  
      * *  
    *** ***
    *     *
    *** ***
      * *  
      ***
    

    指令为'rflfrfrflfrfrflfrfrflfrf''rflfrf' * 4,其中'l' 代表“左转”。

    描述n 等于01 的两种情况的规则是:

    ("rf" + "lfrf" * n) * 4
    

    即,如果n = 0 则为'rf' * 4,如果n = 1 则为('rf' + 'lfrf') * 4。要检查公式,您可以将其绘制为 n = 2 并将其与已知答案进行比较:

        ***    
        * *    
      *** ***  
      *     *  
    ***     ***
    *         *
    ***     ***
      *     *  
      *** ***  
        * *    
        ***    
    

    作为 Python 程序:

    from turtle import Turtle
    
    def get_romb_program(n):
        assert n >= 0
        side = "rf" + "lfrf" * n
        program = side * 4  # romb has 4 sides
        return program
    
    
    def draw(turtle, n):
        assert 0 <= n < 101
        commands = {'r': lambda t: t.right(90),  # turn right
           'l': lambda t: t.left(90),  # turn left
           'f': lambda t: t.forward(2)
        }
        run(get_romb_program(n), turtle, commands)
    
    def run(program, t, commands):
        for c in program:
            commands[c](t)
    
    n = 2
    t = Turtle()
    scr = t.getscreen()
    scr.xscale, scr.yscale = [101 // (n + 1)] * 2
    draw(t, n)
    scr.exitonclick()
    

    要将其打印为 ascii 艺术,您可以使用 AsciiTurtle 而不是 turtle.Turtle

    class AsciiTurtle(object):
        def __init__(self):
            self.path = [(0, 0)]
            self.direction = (1, 0)
    
        def forward(self, distance):
            x, y = self.path[-1]
            for i in range(1, distance + 1):
                self.path.append((x + self.direction[0] * i,
                                  y + self.direction[1] * i))
    
        def right(self, angle_ignored):  # 90 degree turn right
            self.direction = self.direction[1], -self.direction[0]
    
        def left(self, angle_ignored):  # 90 degree turn left
            self.direction = -self.direction[1], self.direction[0]
    
        def show(self):
            minx, maxx, maxy, miny = [f(xy[i] for xy in self.path)
                                      for i in [0, 1] for f in [min, max]]
            miny, maxy = -miny, -maxy  # upside-down
            board = [[' '] * (maxx - minx + 1) for _ in range(maxy - miny + 1)]
            for x, y in self.path:
                board[-y - miny][x - minx] = '*'
            print('\n'.join(''.join(row) for row in board))
    

    示例

    n = 5
    t = AsciiTurtle()
    draw(t, n) # defined above
    t.show()
    

    输出

              ***          
              * *          
            *** ***        
            *     *        
          ***     ***      
          *         *      
        ***         ***    
        *             *    
      ***             ***  
      *                 *  
    ***                 ***
    *                     *
    ***                 ***
      *                 *  
      ***             ***  
        *             *    
        ***         ***    
          *         *      
          ***     ***      
            *     *        
            *** ***        
              * *          
              ***          
    

    【讨论】:

      猜你喜欢
      • 2013-06-27
      • 2016-10-12
      • 2010-12-14
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多