So my array currently assign 5 instances of a dice object. My issue is that I have another class that needs to lock a dice from use.
public class Yahtzee {
OneDice[] dice = new OneDice[5];
public Yahtzee() {
yahtzeeRoll(); //constructor
}
public void yahtzeeRoll() {
for (int i = 0; i != dice.length; i++) {
dice[i] = new OneDice();
}
public void lock(int which) {
dice[which - 1].lockDice();
}
}
however my dice[i] = new OneDice(); creates a whole new set of random numbers each time yahtzeeRoll is called.
here is the method passing the which parameter.
#Override
public void choose() {
int which;
Scanner sc = new Scanner(System.in);
System.out.println(getName() + " Rolling.");
hand.printYahtzee();
System.out.println("Would you like to lock dice 1? 1 for yes");
choice = sc.nextInt();
if (choice == 1) {
which = 1;
hand.lock(which);
}
how can I assign a random value to each dice index without creating a brand new set of rolls that negates the lock. At least that appears to be the issue to me?
It sounds like you need to just skip over entries which are locked:
for (int i = 0; i < dice.length; i++) {
if (dice[i] == null || !dice[i].isLocked()) {
dice[i] = new OneDice();
}
}
Either that, or change your code to initialize dice in the constructor with new instances, but make your yahtzeeRoll method just change the values within the existing unlocked instances, instead of creating new instances. For example:
public Yahtzee() {
for (int i = 0; i < dice.length; i++) {
dice[i] = new OneDice();
}
rollUnlocked();
}
public void rollUnlocked() { // Renamed from yahtzeeRoll for clarity
for (OneDice die : dice) {
die.rollIfUnlocked(); // Or whatever method you want
}
}
(where rollIfUnlocked would reroll the single die, only if it hadn't previously been locked).
Don't reinitialize the entire array each time you roll. In real life when playing yahtzee you don't go grab 5 new dice every time you roll.
create OneDice as follows:
class OneDice {
int value;
boolean locked;
void roll(){
if(!locked)
value = Math.nextInt(6);
}
int getValue(){
return value;
}
void setLock(boolean lock){
locked = lock;
}
boolean isLocked(){
return locked;
}
}
Related
Learning about Arrays. I am not able to figure out why a new number is not added to the back of my existing array. I read in two textfiles in file_1.txt are the numbers '1 2 3' and in file_2.txt is the number '91'. Basically without the method of Void addBack() the program does what I expect, however by adding the method it seems not make a new Array. Even when I go over the elements[i] = elements[i-1] it won't print it as a whole. I am expecting to print for the first part
The numbers are: 1 2 3 and the second part The numbers are: 1 2 3 91.
public class ExampleLecture {
IntRow readIntRow(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.add(input.nextInt());
}
return result;
}
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while(input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
void print(IntRow row) {
for (int i = 0; i < row.numberOfElements; i++) {
System.out.printf("%d ", row.elements[i]);
}
System.out.printf("\n");
}
void start() {
Scanner in = UIAuxiliaryMethods.askUserForInput().getScanner();
Scanner in2 =UIAuxiliaryMethods.askUserForInput().getScanner();
IntRow row = readIntRow(in);
IntRow row2 = setBack(in2);
System.out.printf("the numbers are: ");
print (row);
System.out.printf("the new numbers are: ");
print (row2);
}
public static void main(String[] args) {
new ExampleLecture().start();
}
}
package examplelecture;
class IntRow {
static final int MAX_NUMBER_OF_ELEMENTS = 250;
int[] elements;
int numberOfElements;
IntRow() {
elements = new int[MAX_NUMBER_OF_ELEMENTS];
numberOfElements = 0;
}
void add(int number) {
elements[numberOfElements] = number;
numberOfElements += 1;
}
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
elements[i] = number;
}
}
}
You have 2 successive assignments which write to the same position:
elements[i] = elements[i-1];
elements[i] = number;
The value is alway overwritten with number, so the first statement has no effect.
Also in your addBack method your for cycle:
for (int i = numberOfElements; i>0; i--) {
What happens if numberOfElements is 0?
You call it addBack but it looks like a better name for the method is addFirst. Usually index 0 is considered the front, not the back.
First off, both the readIntRow() and setBack() methods create new IntRow objects row and row2. If you want the result to be appended to the first IntRow object created i.e. to row , you should call:
IntRow row = readIntRow(in);
IntRow row2 = row.setBack(in2);
and setBack() needs to be modified to:
IntRow setBack(Scanner input) {
while(input.hasNext()) {
this.add(input.nextInt());
System.out.println("here");
}
return this;
}
Note that in setBack(), if you are trying to append numbers to the end of the IntRow object, you should call add() instead of addBack() as above. If you are trying to add to the front, you should call addBack() [and it might be better to call it addFront() instead].
Also, in the implementation of addBack(), if you are trying to add to the front of the IntRow object, the element[i] = number operation should take place only once, after the loop. Otherwise all the values in indices <= numberOfElements would be overwritten with number.
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
}
elements[0] = number;
}
Admittedly it is not entirely clear what you are trying to accomplish. But you may have several problems. The first is as follows:
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
IntRow has nothing in it since it is new. So all you are doing is iterating over the new file which has just 91 in it. Remember, result has no items. So it won't even iterate once in addBack.
So just do the following:
Change your addBack method to just add the numbers. Why use a loop to cascade down the elements since you are doing this within the same instance of IntRow? Just add it on to the end using the numberofElements as the next index.
void addBack(int number) {
elements[numberOfElements++] = number;
}
If you want to copy the contents of one IntRow object to another you would need another method in the IntRow class. Something like:
public void copy(IntRow r) {
for (int i = 0; i < r.numerOfElements; i++) {
elements[i] = r.elements[i];
}
numerOfElements = r.numberOfElements;
}
And keeping with good design it might be better to return numberOfElements in a method such as public int size();
I've got array. I've got an isFull method, which checks if the array is full, but I don't know how to use this to check if it's full, then if it's not full add to the array, otherwise disregard the add call.
The array should take 10 elements and then not accept any more. After 10 elements, it should 'be full' and disregard any addSpy calls.
How would you implement this?
public class ConcreteSubject extends AbstractSubject {
public int arySize;
private int i = 0;
private static AbstractSpy[] spies;
public ConcreteSubject(int a) {
arySize = a;
spies = new AbstractSpy[a];
}
#Override
public void addSpy(AbstractSpy spy) {
if (spies.length < 10) {
spies[i] = spy;
System.out.println("spy added at index " + i);
i++;
}
}
public void isFull() {
//1
boolean b = false;
for (int i = 0; i < spies.length; i++) {
if (spies[i] == null) {
b = true;
}
}
if (!b) {
System.out.println("Array is full");
} else {
System.out.println("Array not full");
}
}
public class TestSpies {
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject(10);
AbstractSpy spy = new ConcreteSpy();
AbstractSpy[] spies = new AbstractSpy[10];
cs.addSpy(spy);
cs.addSpy(spy);
cs.addSpy(spy);
cs.isFull();
}
}
spies.length < 10 isn't correct. It should be spies.length > 0 && i < spies.length to make sure that the following assignment spies[i] = spy; is always valid.
void isFull() should be boolean isFull(). Your implementation looks OK, just return b. full is a tricky word because technically an array is always "full". A better adjective would be populated, filled.
Since addSpy isn't filling null gaps but simply adds a spy to the end, isFull could be rewritten to return spies.length == i;.
The simplest way of doing it would be like that:
#Override
public void addSpy(AbstractSpy spy) {
if (!isFull())
{
spies[i] = spy;
System.out.println("spy added at index " + i);
i++;
}
}
To use that, you should change your isFull method to:
public boolean isFull() {
for (int i = 0; i < spies.length; i++) {
if (spies[i] == null) {
return false;
}
}
return true;
}
Keep a track of the number of filled cells of the array using a variable. And before inserting anything into it, check if the filled cells count strictly less than the size of the array (obviously you want to keep track of the array total size as well).
i'm new to programming and i'd like to ask that why is it that in my code i do not need to use a return function in the constructor and method?
Also why is it that after using the yearPasses function age is increased by 3 and not 1?
Apology for the lengthy code
public class Person
{
private int age;
public Person(int initialAge)
{
// Add some more code to run some checks on initialAge
if (initialAge<0)
{
System.out.println("Age is not valid, setting age to 0.");
initialAge = 0;
age = initialAge;
}
else
{
age = initialAge;
}
}
public void amIOld()
{
if (age<13)
{
System.out.println("You are young.");
}
else if (age>=13 && age<18)
{
System.out.println("You are a teenager.");
}
else
{
System.out.println("You are old.");
}
}
public void yearPasses()
{
age = age + 1;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int i = 0; i < T; i++)
{
int age = sc.nextInt();
Person p = new Person(age);
p.amIOld();
for (int j = 0; j < 3; j++)
{
p.yearPasses();
}
p.amIOld();
System.out.println();
}
sc.close();
}
}
You don't need a return in the constructor because a constructor's job is to create an object. The new operator returns that object for you, so it doesn't need to be in the constructor itself.
Your other methods are declared with a return type of void, which means they don't return anything, so you don't need return statements in those either.
You're calling yearPasses in a loop that executes three times.
Constructors create the object, the new keyword is where the object is returned.
All your other methods are labelled as void, meaning they do not return anything.
You could add a return to your yearPasses method, that will return the new age if you want, however it depends on what you need it to do. (This is just an example of using the return)
class TestSync {
public static void main(String[] args) throws InterruptedException {
Counter counter1 = new Counter();
Counter counter2 = new Counter();
Counter counter3 = new Counter();
Counter counter4 = new Counter();
counter1.start();
counter2.start();
counter3.start();
counter4.start();
counter1.join();
counter2.join();
counter3.join();
counter4.join();
for (int i = 1; i <= 100; i++) {
if (values[i] > 1) {
System.out.println(String.format("%d was visited %d times", i, values[i]));
} else if (values[i] == 0) {
System.out.println(String.format("%d wasn't visited", i));
}
}
}
public static Integer count = 0;
public static int[] values = new int[105];
static {
for (int i = 0; i < 105; i++) {
values[i] = 0;
}
}
public static void incrementCount() {
count++;
}
public static int getCount() {
return count;
}
public static class Counter extends Thread {
#Override
public void run() {
do {
synchronized (count) {
incrementCount();
values[getCount()]++;
}
} while (getCount() < 100);
}
}
}
That is a code from one online course. My task is to make this code visit each element of array only once (only for elements from 1 to 100). So I have added simple synchronized block to run method. In case of using values inside of that statement everything works. But with count it doesn't want to work.
What the difference? Both of this objects are static fields inside of the same class. Also I have tried to make count volatile but it hasn't helped me.
PS: a lot of elements are visited 2 times and some of them even 3 times. In case of using values in synchronized all elements are visited only once!!!
Integer is immutable. The moment you call increment method, You get a new object and reference of count variable gets changed and hence leads to an issue.
Exception in thread "main" java.lang.NullPointerException
at Game.main(Game.java:12)
Ive tried searching and this apparently means that im trying to assign a value to a null during
" machines[0].setPayoutRate(35); "
When I try and debug the program the array of objects doesn't show up as three objects. Just one with the value of " SlotMachine[3] " which doesn't make much sense to me. Any ideas?
import java.util.Scanner;
public class Game {
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
SlotMachine[] machines;
machines = new SlotMachine[3];
int cash = 0, totalPlays = 0;
machines[0].setPayoutRate(35);
machines[1].setPayoutRate(100);
machines[2].setPayoutRate(10);
machines[0].setPayoutAmount(30);
machines[1].setPayoutAmount(60);
machines[2].setPayoutAmount(11);
System.out.println("How many quarters do you have?");
cash = userInput.nextInt();
System.out.println("how many times has the first machine been played?");
machines[0].settimesPlayed(userInput.nextInt());
System.out
.println("how many times has the second machine been played?");
machines[1].settimesPlayed(userInput.nextInt());
System.out.println("how many times has the third machine been played?");
machines[2].settimesPlayed(userInput.nextInt());
while (cash >= 1) {
if (cash >= 1) {
cash = machines[0].play();
totalPlays++;
}
if (cash >= 1) {
cash = machines[0].play();
totalPlays++;
}
if (cash >= 1) {
cash = machines[0].play();
totalPlays++;
}
}
System.out.println("You played: " + totalPlays + " times.");
}
}
Main class is above^
Object class is below
public class SlotMachine {
private int timesPlayed;
private int payoutRate;
private int payoutAmount;
public SlotMachine(int timesPlayed, int payoutRate, int payoutAmount) {
this.timesPlayed = timesPlayed;
this.payoutRate = payoutRate;
this.payoutAmount = payoutAmount;
}
public int getTimesPlayed() {
return this.timesPlayed;
}
public void settimesPlayed(int timesPlayed) {
this.timesPlayed = timesPlayed;
}
public int getPayoutRate() {
return this.payoutRate;
}
public void setPayoutRate(int payoutRate) {
this.payoutRate = payoutRate;
}
public int getPayoutAmount() {
return this.payoutAmount;
}
public void setPayoutAmount(int payoutAmount) {
this.payoutAmount = payoutAmount;
}
public int play() {
int moneyExchange = 0;
timesPlayed++;
if (timesPlayed != payoutRate) {
moneyExchange = -1;
} else if (timesPlayed == payoutRate) {
moneyExchange = payoutAmount;
timesPlayed = 0;
}
return moneyExchange;
}
}
You declared your array of length 3, but it's not assigned any new SlotMachines, so all elements remain null, causing the NullPointerException. Initialize your array elements.
machines = new SlotMachine[3];
machines[0] = new SlotMachine(0, 35, 30);
machines[1] = new SlotMachine(0, 100, 60);
machines[2] = new SlotMachine(0, 10, 11);
Then you can access them through the array.
When you declare your array with a size of 3, the array is created with null for each slot.
Then, you try to call a method on null. This will return a Null Pointer Exception.
You need to add objects (in this case SlotMachine) in the array that can have setPayoutRate() called on them.
For example, you can declare your array as follow:
Assign SlotMachine objects to machines reference
machines = new SlotMachine[3];
for (int i = 0; i < machines.length; i++) {
int timesPlayed=000;
int payoutRate=000;
int payoutAmount=000;
machines[i] = new SlotMachine(timesPlayed,payoutRate,payoutAmount);
}
It's because your creating an instance of the array, but not of the objects it contains.
SlotMachine[] machines;
machines = new SlotMachine[3];
You need to add:
for (int i=0; i<3; i++) {
machines[i] = new SlotMachine();
}