0

I am working on coding a program to roll dice. I am very new to java still as I am taking classes for schooling. I am using multiple classes in different packages for this program, what I am trying to figure out is, in one class, for my package pairOfDice, I have created objects in a class pairOfDice, die1 and die2. Now I have another package rollDice, adn my goal is to use the pairOfDice class to roll two die and display the rolls. what I am struggling with is how to exactly do that. When I am rolling the die my results display as if I am only rolling one die. I have made adjustments to display two die every roll, although feel as if I am not doing it in a more proficient sort of way.

package die;

import java.util.Scanner;

/**
 *
 * @author <a href= "mailto:adavi125@my.chemeketa.edu" >Aaron Davis</a>
 */
public class RollDice
{
    public static void main(String[] args)
    {


        Scanner scan = new Scanner(System.in);

        PairOfDice dice = new PairOfDice();

        // get amount of rolls from user
        System.out.print("How many rolls do you want? ");

        int numRolls = scan.nextInt();



        int diceOne, diceTwo;
        int boxCar, snakeEyes;
        int j = 0, k = 0;

        // rolls the dice the requested amount of times
        for (int i = 0; i < numRolls; i++)
        {
            // first die to roll
            diceOne = dice.roll();

            // second die to roll
            diceTwo = dice.roll();

            // display rolled dice
            System.out.println(diceOne + " " + diceTwo + "\n");

            // store and display pairs of 1 rolls
            if (diceOne == 1 && diceTwo == 1)
            {
                snakeEyes = ++j;

                System.out.println("\nThe number of snake eyes you have is: " 
                    + snakeEyes + "\n");
            }


            // store and display pairs of 6 rolls
            if (diceOne == 6 && diceTwo == 6)
            {
                boxCar = ++k;

                System.out.println("\nThe number of box cars you have is: " 
                    + boxCar + "\n");
            }



        }




    }    
}


******************************************************************************
/*
 the integers diceOne and diceTwo are my workarounds, my other package contains

public class PairOfDice extends Die
{
    Die die1, die2;

    public PairOfDice()
    {
        die1 = new Die();
        die2 = new Die();     
    }

    public PairOfDice(int face)
    {
        die1 = new Die(face);
        die2 = new Die(face);
    }
}

*/
******************************************************************************

// i am un-clear how to make "PairOfDice dice = new PairOfDice();" come out as two die
  • What does the `roll` method do, can you add implementation? With current code it’s unclear why do you need `PairOfDice` at all, you could roll each dice individually since you anyways call `roll` twice. – Igor Nikolaev Feb 03 '19 at 07:57
  • My roll method shows the face value of the die from the values of 1-6 using a random number generator. the pair of dice is part of my guidelines for the assignment for class. the goal was to create the pair of dice as one object, Im just not sure as how to roll the dice and display two values- one value per die... – chemeketaStudent Feb 03 '19 at 08:03

1 Answers1

0

The PairOfDice class does not represent your model, which is "a pair of dice". If you have a pair of dice, when you are rolling them, you get two different numbers, thus either:

  1. You are interested in both values separately, so roll method must return two values. You can use a RollResult bean containing the two values for instance
  2. You are NOT interested in both values, but just the sum. This way the roll method can return just an integer from 2 to 12 and you can speculate over the dice rolling based on the sum of them: in your case it is always possible because you get a sum of 2 if and only if your dices are 1, 1; similarily, if you get a sum of 12 if and only if your dices are 6, 6. It would not work, for instance, if you would test against the condition "dice 1=3, dice2=4", as there are many combinations of rollings returning 3+4=7

Hope this helps.

Based on the comments, we have to proceed with the first solution. Here it is an example that implements domain immutable objects and roll domain function that return the result of the roll action against a dice. Here in the example I show the possibilities of having multiple types of dices.

import java.util.*;
import java.util.stream.Collectors;

public class RollingDices {
    private static final Random RND = new Random();
    private static interface Dice {
        public int roll();
    }
    private static class UniformDice implements Dice {
        public int roll() {
            return RND.nextInt(6) + 1;
        }
    }
    private static class TrickyDice implements Dice {
        private final int value;
        public TrickyDice(int value) {
            this.value = value;
        }
        public int roll() {
            return value;
        }
    }
    private static class ProbabilityTableDice implements Dice {
        private final Double[] probabilities;
        public ProbabilityTableDice(Double ... probabilities) {
            if (Arrays.stream(probabilities).mapToDouble(Double::doubleValue).sum() != 1.0) {
                throw new RuntimeException();
            }
            this.probabilities = probabilities;
        }

        public int roll() {
            final double randomValue = RND.nextDouble();
            double curValue = 0.0;
            for (int i = 0; i < this.probabilities.length; i++) {
                curValue += this.probabilities[i];
                if (curValue >= randomValue) {
                    return i + 1;
                }
            }
            throw new RuntimeException();
        }
    }
    private static class CollectionOfDices {
        private final Dice[] dices;

        public CollectionOfDices(Dice ... dices) {
            this.dices = dices;
        }

        public List<Integer> roll() {
            return Arrays.stream(dices).map(Dice::roll).collect(Collectors.toList());
        }
    }
    private static class DicesFactory {
        private static final DicesFactory INSTANCE = new DicesFactory();

        public static DicesFactory instance() {
            return INSTANCE;
        }

        private DicesFactory() {}

        private final Dice uniformDice = new UniformDice();
        public Dice createUniformDice() {
            return this.uniformDice;
        }
        public Dice createTrickyDice(int fixedValue) {
            return new TrickyDice(fixedValue);
        }
        public Dice createProbabilityTableDice(Double ... probabilities) {
            return new ProbabilityTableDice(probabilities);
        }
    }

    public static void main(String ... args) {
        final Scanner scan = new Scanner(System.in);

        final CollectionOfDices dice = new CollectionOfDices(
                DicesFactory.instance().createUniformDice(),
                DicesFactory.instance().createProbabilityTableDice(
                        0.15, 0.2, 0.3, 0.1, 0.25
                )
        );

        // get amount of rolls from user
        System.out.print("How many rolls do you want? ");

        int numRolls = scan.nextInt();



        int diceOne, diceTwo;
        int boxCar, snakeEyes;
        int j = 0, k = 0;

        // rolls the dice the requested amount of times
        for (int i = 0; i < numRolls; i++)
        {
            final List<Integer> rolls = dice.roll();
            // first die to roll
            diceOne = rolls.get(0);

            // second die to roll
            diceTwo = rolls.get(1);

            // display rolled dice
            System.out.println(diceOne + " " + diceTwo + "\n");

            // store and display pairs of 1 rolls
            if (diceOne == 1 && diceTwo == 1)
            {
                snakeEyes = ++j;

                System.out.println("\nThe number of snake eyes you have is: "
                        + snakeEyes + "\n");
            }


            // store and display pairs of 6 rolls
            if (diceOne == 6 && diceTwo == 6)
            {
                boxCar = ++k;

                System.out.println("\nThe number of box cars you have is: "
                        + boxCar + "\n");
            }

        }

    }
}
fcracker79
  • 1,118
  • 13
  • 26
  • This kind of helps. So being interested in both values separately, using the roll method with the pairOfDice method with two instances of dice created would not have any chance of producing two separate values? – chemeketaStudent Feb 03 '19 at 08:44
  • I think your `roll` method should return an instance of `PairOfDice` - after all this is why it is called this way. – Igor Nikolaev Feb 03 '19 at 08:51
  • Maybe it would be better to return a result of rolling. By domain, a pair of dice is... well, a pair of dice. By returning an instance of `PairOfDice` you are assuming a mutable object. Just create a rolling result, which is compatible with your domain description. E.g. your `Die` could return a rolling result and the `PairOfDice` could return the pair of rolling as a `java.util.Collection`. Here we assume that your dices are not distinguishable. – fcracker79 Feb 03 '19 at 08:53
  • `PairOfDice` doesn’t have to be mutable, it possible to return a new instance on every `roll`, but to make it truly immutable, all instance fields have to be `final`. I will try to write a more in the evening. – Igor Nikolaev Feb 03 '19 at 11:07
  • @IgorNikolaev I have attached a snippet of code to describe the proposed implementation. An alternative could be having the state of a rolling dice in the Dice instances, but this would imply the existence of many instances of Dice when just a dice exist, independently of how many times I want to roll it. – fcracker79 Feb 03 '19 at 18:33
  • 1
    This new solution looks pretty good in my opinion! I'd neat pick on `CollectionOfDices` where you should copy `dices` array, instead of just assigning it, since array is still mutable if reference to it is shared. You can probably think about how to encapsulate the logic which checks different dice combinations (snake eyes, box car and etc), so that instead of adding more `if`s, you'd just maintain a list of checks to execute on every roll. – Igor Nikolaev Feb 04 '19 at 20:51