如何绘制双空 ASCII 菱形?

问题描述

如何画一个带星号的双空菱形?我已经实现了菱形本身,但我不明白如何使它加倍。

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

我的代码

int i,j,n = 6;
String str = "";
for (i = 1; i <= n; i++) {
    for (j = n; j > i; j--)
        str += " ";
    str += "*";
    for (j = 1; j < (i - 1) * 2; j++)
        str += " ";
    if (i == 1)
        str += ("\n");
    else
        str += ("*\n");
}
for (i = 2; i <= n; i++) {
    for (j = 1; j < i; j++)
        str += " ";
    for (j = 1; j <= n * 2 - (2 * i - 1); j++)
        if (i == 0 || j == 1 || j == n * 2 - (2 * i - 1))
            str += "*";
        else
            str += " ";
    str += "\n";
}
System.out.println(str);

解决方法

将您的代码分成两个函数,生成一行带有一两个星号的行。 此函数应接受一个字符串、菱形宽度和星号位置作为参数,并返回一个字符串,并将创建的行附加到作为参数给出的字符串。此外,创建的线条应始终具有相同的宽度,这意味着在右侧也填充了空白。并且它不能附加换行符。 所以你的代码看起来像:

private final static int WIDTH = 11;
...
StringBuilder rhombusBuilder = new StringBuilder();
String line = "";

line = singleAsteriskLine( line,WIDTH ); // outputs "     *     "
line = singleAsteriskLine( line,WIDTH ); // outputs "     *          *     "
rhombusBuilder.append( line + "\n" );
for (int pos = 0; pos < (WIDTH - 1) / 2; ++pos) {
    line = doubleAsteriskLine( "",WIDTH,pos ) // pos = 0 "   * *    "
    line = doubleAsteriskLine( line,pos ) // pos = 5 "*         **         *"
// append to stringbuilder
} 
// same backwards....
// append a single asterisk line again...

`

您可以通过在每一行中再重复一次行生成器函数来添加更多菱形。

,

我会计算所需输出的位掩码,计算适当的整数值,然后使用它来驱动一切。喜欢,

int[] bitmask = { 65568,163920,278664,532740,1053186,2100225,65568 };
for (int v : bitmask) {
    for (int j = 0; j < 22; j++) {
        System.out.print((v & (1 << j)) == 0 ? ' ' : '*');
    }
    System.out.println();
}

输出(根据要求)

     *          *     
    * *        * *    
   *   *      *   *   
  *     *    *     *  
 *       *  *       * 
*         **         *
 *       *  *       * 
  *     *    *     *  
   *   *      *   *   
    * *        * *    
     *          *     
,

我会将您的代码重构为一个返回单行菱形的方法,包括末尾和开头的空格:

String rhombLine(int i,int n)
{
    String side = repeat(" ",n-i);
    String mid = "*";
    if (i > 1)
    {
        mid += repeat(" ",(i - 1) * 2 - 1);
        mid += "*";
    }
    return side + mid + side;
}

我们通过使用重复 nString 个副本的方法来简化代码:

static String repeat(String s,int n)
{
    String r = "";
    for(int i=0; i<n; i++) r += s;
    return r;
}

如果您使用的是 Java 11,则可以改用 String.repeat() 方法。

现在您只需在每行打印两份菱形线:

void rhombus(int n)
{
    for(int i=1; i<=n; i++)
        System.out.println(repeat(rhombLine(i,n),2));         

    for(int i=n-1; i>0; i--)
        System.out.println(repeat(rhombLine(i,2));                 
}

作为替代,有一个使用递归的好技巧,这意味着您只需要生成每一行一次:

void rhombus(int i,int n)
{       
    String line = repeat(rhombLine(i,2);       
    
    System.out.println(line);
    
    if(i == n) return;
    
    rhombus(i+1,n);
    
    System.out.println(line);
}

最初将通过 rhombus(1,6)

调用 ,

想象一个坐标平面并以菱形形式绘制函数的图形:

Math.abs(y - n) + Math.abs(x - n) == n

Try it online!

在这段代码中,零点位于左上角,坐标轴向下和向右:

// size of the rhombus
int n = 6;
// number of rhombuses
int m = 4;
// vertical axis
for (int y = 0; y <= 2 * n; y++) {
    // horizontal axis
    for (int x = 0; x < 2 * n * m + m; x++) {
        // current rhombus
        int k = x / (2 * n + 1);
        // center of the rhombus
        int c = (2 * k + 1) * n + k;
        // check if this point is on the rhombus
        if (Math.abs(y - n) + Math.abs(x - c) == n)
            System.out.print("*");
        else
            System.out.print(" ");
    }
    System.out.println();
}

输出:

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

另见:Output an ASCII diamond shape using loops