I'm making a java program where a random dice face is selected and displayed. Ultimately, I want to show five dice side by side in the console. I have made some strings that are ascii representations of the 6 dice faces.
Here is an example of one:
+-------+
| o o |
| o |
| o o |
+-------+
My question is: how would I display five of these ascii dice side by side in the console? I want the console output to look something like this:
+-------+ +-------+ +-------+ +-------+ +-------+
| 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 |
+-------+ +-------+ +-------+ +-------+ +-------+
Here is my code:
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());
}
}
This sounds a bit like homework (apologies if I'm wrong), so I'll get you started in the right direction instead of providing a full solution.
Consider the six possible dice:
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+
| | | o | | o | | o o | | o o | | o o |
| o | | | | o | | | | o | | o o |
| | | o | | o | | o o | | o o | | o o |
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+
How unique are the pieces of these, really? You can break it down into 6 strings:
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 |";
Every die face can be represented by combining these strings together along with newlines, e.g.:
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.
}
If you wanted to render them side-by-side, think about how could you arrange a couple of arrays such that you're iterating over each die to print one line at a time.
Here's what I came up with. There's a Die
class that lets you create an Iterator
through the different lines, and then we get a list of these Iterator
's and print out the first line for each of the dice, then the second line, etc.
Here is the Die
class:
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();
}
}
Here is the class with the main method that collects the lines in a StringBuilder
and prints them:
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);
}
}
The output of this code is the following:
+-------+ +-------+ +-------+ +-------+ +-------+
| | | o | | o | | o o | | o o |
| o | | | | o | | | | o |
| | | o | | o | | o o | | o o |
+-------+ +-------+ +-------+ +-------+ +-------+
For cases like this, I tend to create somewhat generic solutions. This may be "overengineering" for the particular case of the question. But I think that the result may be a useful building block for application cases.
\n
or \r\n
). One approach here would be to break the strings into multiple lines, and consider them as "blocks" that should be concatenated horizontally.
The format
method in the example below does exactly this:
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();
}
}
For the example of the dice, the output is as desired:
+-------+ +-------+ +-------+ +-------+
| | | o o | | o o | | o o |
| o | | | | o | | |
| | | o o | | o o | | o o |
+-------+ +-------+ +-------+ +-------+
As an additional test, there is an example where other strings are formatted, with different numbers of lines and line lengths:
AAA BBBBBBBBBBBBBB CCC AAA
AAAAAAAA BBBBB AAAAAAAA
AAAAA BBBBBBBBBB CCCCCCC AAAAA
BBBBBBBBBBBBBBBBB CCCC
BBBBB
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With