我正在制作一个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());
}
}
这听起来有点像家庭作业(如果我错了就道歉),所以我会让你开始朝着正确的方向而不是提供完整的解决方案。
考虑六种可能的骰子:
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+
| | | 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.
}
如果你想并排渲染它们,可以考虑如何安排几个数组,这样你就可以迭代每个模具一次打印一行。
这就是我想出来的。有一个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 |
+-------+ +-------+ +-------+ +-------+ +-------+
对于这样的情况,我倾向于创建一些通用的解决方案。对于问题的特定情况,这可能是“过度工程”。但我认为结果可能是应用案例的有用构建块。
\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
我没有添加注释来减少长度。如果您有疑问,请询问:-)
我们的想法是为“眼睛场”设置一个布尔矩阵(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();
}
}