Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Formatting a java dice rolling program?

Tags:

java

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());
    }
}
like image 759
darkangel1283 Avatar asked Mar 02 '18 19:03

darkangel1283


3 Answers

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.

like image 153
Brian Avatar answered Oct 24 '22 18:10

Brian


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 |   
+-------+   +-------+   +-------+   +-------+   +-------+  
like image 26
Charles Spencer Avatar answered Oct 24 '22 20:10

Charles Spencer


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.

  • There is a set of strings that is supposed to be formatted "nicely"
  • The number of strings is not known.
  • The strings can contain multiple lines (i.e. they may contain line breaks, \n or \r\n).
  • The number of line breaks is not known.
  • The line lengths are not known.

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                                 
like image 30
Marco13 Avatar answered Oct 24 '22 19:10

Marco13