格式化java骰子滚动程序?

问题描述 投票:8回答:4

我正在制作一个java程序,其中选择并显示随机骰子面。最终,我想在控制台中并排显示五个骰子。我做了一些字符串,这些字符串是6个骰子面的ascii表示。

这是一个例子:

+-------+
| o   o |
|   o   |
| o   o |
+-------+

我的问题是:如何在控制台中并排显示其中五个ascii骰子?我希望控制台输出看起来像这样:

+-------+   +-------+   +-------+   +-------+   +-------+
| o   o |   | o   o |   | o   o |   | o   o |   | o   o |
|   o   |   |   o   |   |   o   |   |   o   |   |   o   |
| o   o |   | o   o |   | o   o |   | o   o |   | o   o |
+-------+   +-------+   +-------+   +-------+   +-------+

这是我的代码:

public class Die
{
    private final static int LOWEST_DIE_VALUE = 0;
    private final static int HIGHEST_DIE_VALUE = 6;

    private String die;

    public Die()
    {
        String[] dieFaces = {"+-------+\r\n|       |\r\n|   o   |\r\n|       |\r\n+-------+", 
                             "+-------+\r\n| o     |\r\n|       |\r\n|     o |\r\n+-------+",
                             "+-------+\r\n| o     |\r\n|   o   |\r\n|     o |\r\n+-------+",
                             "+-------+\r\n| o   o |\r\n|       |\r\n| o   o |\r\n+-------+",
                             "+-------+\r\n| o   o |\r\n|   o   |\r\n| o   o |\r\n+-------+",
                             "+-------+\r\n| o   o |\r\n| o   o |\r\n| o   o |\r\n+-------+"};

        die = dieFaces[((int)(Math.random() * 100) % HIGHEST_DIE_VALUE + LOWEST_DIE_VALUE)];        
    }

    public String getDie()
    {
        return die;
    }
}

public class FiveDice
{
    public static void main(String[] args)
    {
        Die die1 = new Die();
        System.out.println(die1.getDie());
    }
}
java
4个回答
14
投票

这听起来有点像家庭作业(如果我错了就道歉),所以我会让你开始朝着正确的方向而不是提供完整的解决方案。

考虑六种可能的骰子:

+-------+   +-------+   +-------+   +-------+   +-------+   +-------+
|       |   | o     |   | o     |   | o   o |   | o   o |   | o   o |
|   o   |   |       |   |   o   |   |       |   |   o   |   | o   o |
|       |   |     o |   |     o |   | o   o |   | o   o |   | o   o |
+-------+   +-------+   +-------+   +-------+   +-------+   +-------+

这些是多么独特,真的吗?你可以把它分成6个字符串:

private static final String xxxxxxxxx = "+-------+";
private static final String x_______x = "|       |";
private static final String x_o_____x = "| o     |";
private static final String x___o___x = "|   o   |";
private static final String x_____o_x = "|     o |";
private static final String x_o___o_x = "| o   o |";

每个模具面都可以通过将这些字符串与换行符组合在一起来表示,例如:

public String[] getLines(int face) {
    switch (face) {
        case 1:
            return new String[] {
                    xxxxxxxxx,
                    x_______x,
                    x___o___x,
                    x_______x,
                    xxxxxxxxx
            };
        case 2:
            ...
        case 3:
            ...
        // etc.
}

如果你想并排渲染它们,可以考虑如何安排几个数组,这样你就可以迭代每个模具一次打印一行。


2
投票

这就是我想出来的。有一个Die类让你通过不同的线创建一个Iterator,然后我们得到这些Iterator的列表并打印出每个骰子的第一行,然后是第二行,等等。

这是Die类:

  class Die implements Iterable<String> {
    private static final String[][] lines = {
      {
        "+-------+",
        "|       |",
        "|   o   |",
        "|       |",
        "+-------+",
      },
      {
        "+-------+",
        "| o     |",
        "|       |",
        "|     o |",
        "+-------+",
      },
      {
        "+-------+",
        "| o     |",
        "|   o   |",
        "|     o |",
        "+-------+",
      },
      {
        "+-------+",
        "| o   o |",
        "|       |",
        "| o   o |",
        "+-------+",
      },
      {
        "+-------+",
        "| o   o |",
        "|   o   |",
        "| o   o |",
        "+-------+",
      },
      {
        "+-------+",
        "| o   o |",
        "| o   o |",
        "| o   o |",
        "+-------+",
      }
    };

    private int value;

    public Die(int value) {
      if (value < 0 || value >= 7) {
        throw new IllegalArgumentException("Illegal die value");
      }
      this.value = value;
    }

    public Iterator<String> iterator() {
      return Arrays.asList(lines[value]).iterator();
    }
  }

这是带有main方法的类,它收集StringBuilder中的行并打印它们:

public class Dice {
  public static void main(String[] args) {
    Die die1 = new Die(0);
    Die die2 = new Die(1);
    Die die3 = new Die(2);
    Die die4 = new Die(3);
    Die die5 = new Die(4);

    List<Iterator<String>> dice = Arrays.asList(
        die1.iterator(),
        die2.iterator(),
        die3.iterator(),
        die4.iterator(),
        die5.iterator());
    StringBuilder sb = new StringBuilder();

    outer:
    while (true) {
      for (Iterator<String> iter : dice) {
        if (!iter.hasNext()) {
          break outer;
        }
      }

      for (Iterator<String> iter : dice) {
        sb.append(iter.next()).append("   ");
      }
      sb.append("\r\n");
    }

    System.out.println(sb);
  }
}

此代码的输出如下:

+-------+   +-------+   +-------+   +-------+   +-------+   
|       |   | o     |   | o     |   | o   o |   | o   o |   
|   o   |   |       |   |   o   |   |       |   |   o   |   
|       |   |     o |   |     o |   | o   o |   | o   o |   
+-------+   +-------+   +-------+   +-------+   +-------+  

1
投票

对于这样的情况,我倾向于创建一些通用的解决方案。对于问题的特定情况,这可能是“过度工程”。但我认为结果可能是应用案例的有用构建块。

  • 有一组字符串应该被格式化为“很好”
  • 字符串的数量是未知的。
  • 字符串可以包含多行(即它们可以包含换行符,\n\r\n)。
  • 换行的数量尚不清楚。
  • 线长度未知。

这里的一种方法是将字符串分成多行,并将它们视为应该水平连接的“块”。

以下示例中的format方法正是如此:

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MultiLineFormatting
{
    public static void main(String[] args)
    {
        showDice();
        showOtherStrings();
    }

    private static void showDice()
    {
        String s1 = 
            "+-------+" + "\n" +
            "|       |" + "\n" +
            "|   o   |" + "\n" +
            "|       |" + "\n" +
            "+-------+";
        String s4 = 
            "+-------+" + "\n" +
            "| o   o |" + "\n" +
            "|       |" + "\n" +
            "| o   o |" + "\n" +
            "+-------+";
        String s5 = 
            "+-------+" + "\n" +
            "| o   o |" + "\n" +
            "|   o   |" + "\n" +
            "| o   o |" + "\n" +
            "+-------+";

        System.out.println(format(Arrays.asList(s1, s4, s5, s4), "  "));
    }

    private static void showOtherStrings()
    {
        String sA = 
            "AAA" + "\n" +
            "AAAAAAAA" + "\n" +
            "AAAAA";
        String sB = 
            "BBBBBBBBBBBBBB" + "\n" +
            "BBBBB" + "\n" +
            "BBBBBBBBBB" + "\n" +
            "BBBBBBBBBBBBBBBBB" + "\n" +
            "BBBBB";
        String sC = 
            "CCC" + "\n" +
            "" + "\n" +
            "CCCCCCC" + "\n" +
            "CCCC";

        System.out.println(format(Arrays.asList(sA, sB, sC, sA), "  "));
    }

    private static String format(Collection<String> strings, String padding)
    {
        StringBuilder sb = new StringBuilder();

        // Convert the strings to lists of strings, breaking them at newlines
        List<List<String>> lineLists = strings.stream()
            .map(s -> s.split("\\R"))
            .map(Arrays::asList)
            .collect(Collectors.toList());

        // Compute the maximum number of lines of any block
        int maxNumLines = lineLists.stream()
            .mapToInt(Collection::size)
            .max().getAsInt();

        // Compute a map from each block index to the maximum length of a line
        Map<Integer, Integer> maxLineLengths = 
            new LinkedHashMap<Integer, Integer>();
        for (int i = 0; i < lineLists.size(); i++)
        {
            List<String> lineList = lineLists.get(i);
            int maxLineLength = lineList.stream()
                .mapToInt(String::length)
                .max().getAsInt();
            maxLineLengths.put(i, maxLineLength);
        }

        // Assemble the resulting lines
        for (int i = 0; i < maxNumLines; i++)
        {
            // Concatenate the i'th line of each block
            for (int j = 0; j < lineLists.size(); j++)
            {
                List<String> lineList = lineLists.get(j);
                int maxLineLength = maxLineLengths.get(j);
                String format = "%-" + maxLineLength + "s";
                if (i < lineList.size())
                {
                    String line = lineList.get(i);
                    sb.append(String.format(format, line));
                }
                else
                {
                    sb.append(String.format(format, ""));
                }
                sb.append(padding);
            }
            sb.append("\n");
        }
        return sb.toString();
    }
}

对于骰子的示例,输出符合要求:

+-------+  +-------+  +-------+  +-------+  
|       |  | o   o |  | o   o |  | o   o |  
|   o   |  |       |  |   o   |  |       |  
|       |  | o   o |  | o   o |  | o   o |  
+-------+  +-------+  +-------+  +-------+  

作为附加测试,有一个示例,其中格式化其他字符串,具有不同数量的行和行长度:

AAA       BBBBBBBBBBBBBB     CCC      AAA       
AAAAAAAA  BBBBB                       AAAAAAAA  
AAAAA     BBBBBBBBBB         CCCCCCC  AAAAA     
          BBBBBBBBBBBBBBBBB  CCCC               
          BBBBB                                 

0
投票

我没有添加注释来减少长度。如果您有疑问,请询问:-)

我们的想法是为“眼睛场”设置一个布尔矩阵(3x3)。 DiceSide负责根据要显示的数字设置字段。不考虑两个字段(顶部中间,底部中间),因为它们总是空的。

createString方法将骰子打印为行(每个diceside有5行(标题,三个眼睛行和底部))。

import java.util.Arrays;
import java.util.List;

public class AsciiDice {
    private static class DiceSide {

        public DiceSide(final int nr) {
            setNr(nr);
        }

        public void setNr(final int nr) {
            if (nr <= 0 || nr > 6) return;

            fields[0][0] = nr == 2 || nr == 3 || nr == 4 || nr == 5 || nr == 6;
            fields[0][2] = nr == 4 || nr == 5 || nr == 6;
            fields[1][0] = nr == 6;
            fields[1][1] = nr == 1 || nr == 3 || nr == 5;
            fields[1][2] = nr == 6;
            fields[2][0] = nr == 4 || nr == 5 || nr == 6;
            fields[2][2] = nr == 2 || nr == 3 || nr == 4 || nr == 5 || nr == 6;
        }

        final boolean[][] fields = new boolean[3][3];
    }

    public static void main(final String[] args) {
        new AsciiDice();
    }

    public AsciiDice() {
        final List<DiceSide> diceSides = Arrays.asList(new DiceSide(5), new DiceSide(4), new DiceSide(3));
        final String str = createString(diceSides);
        System.out.println(str);
    }

    private String createString(final List<DiceSide> diceSides) {
        final StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 5; i++) {
            for (final DiceSide side : diceSides) {
                if (i == 0 || i == 4) {
                    sb.append("+-------+");
                } else {
                    sb.append("| ");
                    for (int c = 0; c < 3; c++) {
                        final boolean set = side.fields[i - 1][c];
                        if (set) {
                            sb.append("o ");
                        } else {
                            sb.append("  ");
                        }
                    }
                    sb.append("|");
                }

                sb.append("\t");
            }
            sb.append("\n");
        }
        return sb.toString();
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.