"If" statement alternatives - java

I'm doing my homework, and am stuck on some logic (I think I used that term correctly?). I'm writing an application that shows 12 buttons numbered 1-12, 2 pictures of dice, and a Roll button.
The player rolls the dice (2, 6 sided die) and whatever number(s) he gets, he can use to "cover" some of the twelve numbers. For example, let's say he rolls the dice and gets a 3 and a 5. He gets to choose whether to cover the 3 and the 5, or the total of the two numbers - 8 (Did I mention I'm a math wiz?).
The goal of the game is to cover all the numbers using the least amount of rolls.
The problem I'm having is with, what I believe to be, the if statements:
if (die1 == 3 && die2 == 5) {
player can cover 3 and 5, or 8, but not both
}
Now, I think this works, but if I wrote all this out it would be 36 if statements (give or take zero). Is there an easier way?

By your description I think the player can select die1, die2 or die1 + die2, so to see if the user selected a valid value you need just one if.
if (cover == die1 or cover == die2 or cover == ( die1 + die2)) {
//valid..
}

no if statement needed. player can cover die1 and die2 or die1+die2

This is a good example to use a switch case, IMO.
That'd be 2 switchs which have 6 cases each.

Don't check until the player tries to cover something. By only validating the input you simplify everything down to one if statement.
If you do need to know all possibilities (maybe to show the player possible moves), then ... you still don't need all those if statements. Simply highlight the buttons that match the dice roll and only accept those as input; you'll want to index them in an array or map by their value (e.g. "1") as a way to retrieve them.

You know with two dice you always have three covering options. Presumably elsewhere in code you're going to compare your covered options with numbers. Something like
int[] covered = { die1, die2, die1+die2 };
// ... other stuff
if (comparisonValue > 6) {
// maybe do special stuff since this uses both dice
if (comparisonValue == covered[2]) {
// covered/coverable behavior
} else {
// not
}
} else {
// maybe do special stuff since this only uses one die
if (comparisonValue == covered[0] || comparisonValue == covered[1]) {
// covered/coverable behavior
} else {
// not
}
}
gives you first what's covered, then simple use of it. You could also foreach over the array to do stuff for the covered numbers, ala
for (int c : covered) {
// do stuff with c because it's covered
}
That's fairly fragile, but the flexible answer (e.g., dumping the outcomes into Collection) is way overkill for 6-sided, integer face dice, and the really flexible answer (e.g., accommodating a variable number of dice, specialized combination of faces into outcomes) is like nuclear armageddon for this particular problem.
EDIT for your particular problem, I'd do something like
// start new turn, disable all buttons
// get rolls
int[] coverable = { die1, die2, die1+die2 };
for (int covered : coverable ) {
// enabled covered button
}
If the player can change which of the 1-12 are covered by previous rolls based on a new outcome, well, then you could be in for some fun depending on how much help you want to give them.

I would probably create 2 new objects and use them with a lookup table, like so:
class TossResult{
int firstDie;
int secondDie;
}
Class Coverage{
TossResult tossResult;
int getThirdNumber(){
return tossResult.firstDie + tossResult.secondDie;
}
}
Then on application start-up, populate your map:
HashMap<TossResult, Coverage> lookup = new HashMap<>();
for (int i = 0, i < SIDES_ON_DIE; i++){
for (int j = 0, j < SIDES_ON_DIE; j++){
TossResult tempResult = new TossResult(i,j);
Coverage tempCoverage = new Coverage(tempResult);
lookup.put(tempResult, tempCoverage);
}
}
After a user rolls the dice, create a new TossResult and do a lookup.get(tossResult)

You could also create an array of 12 ints or bools. Initialize all 12 elements (say to 0 or false). Then for each role you can do something lik:
if (false == myArray[die1Value] && false == myArray[die2Value]) {
myArray[die1Value] = true;
myArray[die2Value] = true;
} else if (false == myArray[die1Value + die2Value]) {
myArray[die1Value + die2Value]
} else if (false == myArray[die1Value] || false == myArray[die2Value]) {
if (false == myArray[die1Value]) {
myArray[die1Value] = true;
}
if (false == myArray[die2Value]) {
myArray[die2Value] = true;
}
} else {
// all 12 covered
}
And certainly you can refactor this code some more.
The stated goal "The goal of the game is to cover all the numbers using the least amount of rolls." is not doable, really. The best you can do is to use probabilities to know if, for instance, you should cover on a roll of 1 and 2, a 1 and 2, or 3 first:-)

Related

How to add a variable to another variable that's already set

My homework is to create a program that takes a list of numbers and prints out the highest number divisible by four.
List would look like this:
12
16
87
58
25
73
86
36
79
40
12
89
32
Input should be:
40 because it is the highest number there divisible by four.
Here is my code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int saved = 0;
int saved2 = 0;
for (int i = scanner.nextInt(); i % 4 == 0; i = scanner.nextInt()) {
for (boolean bull = true; bull == true; bull ^= true) {
if (i > saved) {
saved -= saved2;
saved += i;
saved2 += i;
}
}
System.out.println(saved);
}
}
}
The input of my code is
12
16
I don't really understand why this is doing it, but it seems to me that I'm adding the variables wrong. The homework page on adding variables does not specify how to add variables to each other.
Does anyone have a tip to improve the code in anyway, or find a way to make a fix my code? Thank you.
welcome to Java.
First you are saying you got input, but that is output. Input is what you enter, and output is what you get printed.
Then there is a mistake in your for loops. You have too much going on in one place. By the logic which is implemented, your program will exit first level for loop whenever your entered value is not divisable by 4.
Read on for loops if you want to learn more https://www.learnjavaonline.org/en/Loops.
I recommend to start from while loops instead. The logic whould be this:
1. create variable to hold the correct answer saved
2. create another one to hold the value read from console i
3. start the while loop with condition i = scanner.nextInt()
3.1 check if the value just entered i is divisable by 4
3.2 if it is, then compare if it's larger than the one was saved before (initially saved value will be 0)
3.3 if it is larger, then assign the read value i to the saved
4. At the end of the loop, you will have the highest number divisable by four in your saved variable. Print it.
I will provide some help, according to
How do I ask and answer homework questions?
for (int i = scanner.nextInt(); i % 4 == 0;i = scanner.nextInt())
This only reads as long as ALL inputs are divisible by 4, that is why it ends at 16, because 87 is not divisible by 4.
for (boolean bull = true; bull == true ;bull ^= true)
This needs explanation by you, but I am pretty sure that it unconditionally executes the body of the inner loop exactly once. (Not 100% sure, because the representation of true and false could be weird in your machine. Should 0 be the representation of true, i.e. really weird, then it is an endless loop, which does not match the output you describe...)
System.out.println(saved);
This executes exactly once per input, except the last one, which is not a multiple of 4.
The value of saved is identical to input, as long as it is increasing.
These hints explain the unexpected output.
If you inspect the details of what the problem is, you should be able to improve your coding attempt.
This is how I super-quickly fixed in your code.
Note that there are no statements about the possible minimum value and about how do you stop the input. Therefore the solution is pretty-straightforward, it just reads the input until integers are present there.
This article may be useful about handling the input from the Scanner.
I hope the comments in the code will help. Add comments if there are any questions. Good luck!
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int currentMax = Integer.MIN_VALUE; // you may set negative or 0 if you know that all the input is positive
// int saved2 = 0; // no need for this variable
while (scanner.hasNextInt()) { // you can make a better input handling, especially if you know when it should end the input. Now it will end on any non-integer input line
int i = scanner.nextInt();
// for (int i = scanner.nextInt(); i % 4 == 0; i = scanner.nextInt()) {
// for (boolean bull = true; bull == true; bull ^= true) {
if (((i % 4) == 0) && (i > currentMax)) {
currentMax = i;
// saved -= saved2;
// saved += i;
// saved2 += i;
// }
}
}
System.out.println(currentMax); // moved out of "for" or "while" cycles. Print the value after the input has ended.
}
}

Calculate Dice Roll from Text Field

QUESTION:
How can I read the string "d6+2-d4" so that each d# will randomly generate a number within the parameter of the dice roll?
CLARIFIER:
I want to read a string and have it so when a d# appears, it will randomly generate a number such as to simulate a dice roll. Then, add up all the rolls and numbers to get a total. Much like how Roll20 does with their /roll command for an example. If !clarifying {lstThen.add("look at the Roll20 and play with the /roll command to understand it")} else if !understandStill {lstThen.add("I do not know what to say, someone else could try explaining it better...")}
Info:
I was making a Java program for Dungeons and Dragons, only to find that I have come across a problem in figuring out how to calculate the user input: I do not know how to evaluate a string such as this.
I theorize that I may need Java's eval at the end. I do know what I want to happen/have a theory on how to execute (this is more so PseudoCode than Java):
Random rand = new Random();
int i = 0;
String toEval;
String char;
String roll = txtField.getText();
while (i<roll.length) {
check if character at i position is a d, then highlight the numbers
after d until it comes to a special character/!aNumber
// so if d was found before 100, it will then highlight 100 and stop
// if the character is a symbol or the end of the string
if d appears {
char = rand.nextInt(#);
i + #'s of places;
// so when i++ occurs, it will move past whatever d# was in case
// d# was something like d100, d12, or d5291
} else {
char = roll.length[i];
}
toEval = toEval + char;
i++;
}
perform evaluation method on toEval to get a resulting number
list.add(roll + " = " + evaluated toEval);
EDIT:
With weston's help, I have honed in on what is likely needed, using a splitter with an array, it can detect certain symbols and add it into a list. However, it is my fault for not clarifying on what else was needed. The pseudocode above doesn't helpfully so this is what else I need to figure out.
roll.split("(+-/*^)");
As this part is what is also tripping me up. Should I make splits where there are numbers too? So an equation like:
String[] numbers = roll.split("(+-/*^)");
String[] symbols = roll.split("1234567890d")
// Rough idea for long way
loop statement {
loop to check for parentheses {
set operation to be done first
}
if symbol {
loop for symbol check {
perform operations
}}} // ending this since it looks like a bad way to do it...
// Better idea, originally thought up today (5/11/15)
int val[];
int re = 1;
loop {
if (list[i].containsIgnoreCase(d)) {
val[]=list[i].splitIgnoreCase("d");
list[i] = 0;
while (re <= val[0]) {
list[i] = list[i] + (rand.nextInt(val[1]) + 1);
re++;
}
}
}
// then create a string out of list[]/numbers[] and put together with
// symbols[] and use Java's evaluator for the String
wenton had it, it just seemed like it wasn't doing it for me (until I realised I wasn't specific on what I wanted) so basically to update, the string I want evaluated is (I know it's a little unorthodox, but it's to make a point; I also hope this clarifies even further of what is needed to make it work):
(3d12^d2-2)+d4(2*d4/d2)
From reading this, you may see the spots that I do not know how to perform very well... But that is why I am asking all you lovely, smart programmers out there! I hope I asked this clearly enough and thank you for your time :3
The trick with any programming problem is to break it up and write a method for each part, so below I have a method for rolling one dice, which is called by the one for rolling many.
private Random rand = new Random();
/**
* #param roll can be a multipart roll which is run and added up. e.g. d6+2-d4
*/
public int multiPartRoll(String roll) {
String[] parts = roll.split("(?=[+-])"); //split by +-, keeping them
int total = 0;
for (String partOfRoll : parts) { //roll each dice specified
total += singleRoll(partOfRoll);
}
return total;
}
/**
* #param roll can be fixed value, examples -1, +2, 15 or a dice to roll
* d6, +d20 -d100
*/
public int singleRoll(String roll) {
int di = roll.indexOf('d');
if (di == -1) //case where has no 'd'
return Integer.parseInt(roll);
int diceSize = Integer.parseInt(roll.substring(di + 1)); //value of string after 'd'
int result = rand.nextInt(diceSize) + 1; //roll the dice
if (roll.startsWith("-")) //negate if nessasary
result = -result;
return result;
}

Fill squares in Sudoku board using recursion

I'm trying to create a program that reads a sudoku board from a txt file and finds possible solution(s) to the board.
I've created objects of each square and added them to a 2d-array:
(This board have 28 different solutions)
001003
000000
000020
260000
000300
300102
I have successfully added the squares to corresponding column, row and box. But I'm having trouble with my recursive method that tries to find possible solution(s) of the board and add each solutions to a container in a different class that uses nodes to keep track of all the solutions. The method in my container class should take Square[][] squares as parameters.
I start the recursive method off with:
squares[0][0].fillInRemainingOfBoard();
from another class called Board.
My recursive method that is supposed to check all the squares looks like this:
protected void fillInRemainingOfBoard() {
// If Square is not '0' in the txt file it goes in here
if(this instanceof SquareDone) {
// If next != null it goes in here.
if(next != null) {
next.fillInRemainingOfBoard();
}
// If the square is empty it goes in here
} else if(this instanceof SquareEmpty) {
if(next != null) {
// Searching for possible numbers for square
// Rows, Column and Box have the same length;
//thats why row.getLength() in for-loop
for(int i=1; i<=row.getLength(); i++) {
// Set new value to square if this is true,
// then move on to next square
if(row.getLegal(i) && column.getLegal(i) && box.getLegal(i)) {
setNewValue(i);
next.fillInRemainingOfBoard();
}
}
} else {
for(int i=1; i<=row.get(); i++) {
if(row.getLegal(i) && column.getLegal(i) && box.getLegal(i)) {
setNewValue(i);
// No next.fillInRemainingOfBoard() here because it's the last square
}
}
}
}
}
I have a super-class for the rows, columns and boxes which holds the variables and methods for the subclasses. The method that checks for legal values looks like this:
public boolean getLegal(int square) {
for(int i=0; i<rkb.length; i++) {
if(rute == rkb[i].getVerdi()) {
return false;
}
}
return true;
}
My output of this looks like this
4 2 1 5 6 3
5 3 6 2 1 4
1 4 3 6 2 5
2 6 5 4 3 1
6 1 4 3 5 0
3 0 0 1 0 2
So my question is: Why is my code not adding values to each square and how can I save a solution and send them to another class, then start over and check for more solutions?
The reason why its not adding value to each square, is because the algorithm is incorrect. As you can see from position [5][4] of your array, value by line 2 and value by column should be 6. Meaning the algorithm messed up previous values and cannot find further ones.
I suspect this happens because in part of your code bellow, setNewValue(i) is set for the last solution found, but the if statement may find multiple solutions in the beginning of the program, as not many squares are filled, and not always the last solution is the good one.
if(next != null) {
for(int i=1; i<=row.getLength(); i++) {
if(row.getLegal(i) && column.getLegal(i) && box.getLegal(i)) {
setNewValue(i);
next.fillInRemainingOfBoard();
}
}
To solve this, you should store all values that match the if statement and figure out how to use them later. (maybe skip the current cell if it has more then 1 solution and come back to it later)
This is just my hypothesis, but you can use a debugger to see if this is truly the problem
Here is a fast implementation of Sudoku Solver which I implemented a couple of years back.
https://gist.github.com/dapurv5/e636c85a5a85cd848ca2
You might want to read about Minimum Remaining Value heuristic. This is one of the standard ways to solve a CSP (Constraint Satisfaction Problem)

Can I manipulate the way that variables change in Java?

If the die shows a 6, the player doesn't move at all on this turn and also forfeits the next turn.
To accomplish this, I have tried an integer type warning marker variable for the player and an integer type time counter variable.
If the die shows 6, I want to increment the warning marker variable by 1 during the first run(and have the while loop do nothing), then keep the value at 1 during the second run (while loop will not work), then lower it back down to 0 for the third run of the while loop (so the while loop will work). The marker will stay at zero unless the die shows a 6 again, after which the same process will repeat.
I have a while loop like this:
while the warning marker is equal to 0 {
Do Stuff
if the die shows a 6, the warning marker increases by 1.
the time counter also increases by 1.
}
How do I manipulate the variables to get the result that I need? Or is my partially complete method absolutely off in terms of logic?
Thanks.
Can u tell me if this works for you?
flag=true;
while condition{
if flag==true{
if die == 6
{
flag=false;
continue;}
}
else { Do STUFF }
} else
{
flag==true;
}
}
I think you want to reword this problem.
This is what I understood. You have a warning marker.
You have a loop that checks whether the marker is 0, if it is then you do something.
If the die is a six, you will increase the warning marker. If its new value is 3, then you will reset it to 0. Meanwhile, the time counter is always increasing.
If this is correct, I think you want something like:
int warningMarker = 0;
int timeMarker = 0;
while (true) {
if (die == 6) {
++warningMarker;
if (warningMarker == 3) {
warningMarker = 0;
}
}
if (warningMarker == 0) {
doSomething();
}
++timeMarker;
}
Java is Object-Oriented Pragramming language. Use this feature.
See following pseudocode and let me know if you have problem in undestanding it.
Create a class Player as following:
class Player
{
boolean skipChance = false;
... // Other fields
... //
}
Change your while as following:
while(isGameOn())
{
Player p = getCurrentPlayer();
if( ! p.skipChance)
{
int val = p.throwDice();
if(val == 6)
{
p.skipChance = true;
continue; // control moves to while.
}
// Do stuff
}
else
{
p.skipChance = false;
}
}

Scalable solution for Rock-Paper-Scissor

Just went through a variant of the game : Rock-Paper-Scissor-Lizard-Spock
I have written a Java code for traditional R-P-S problem, but when I tried extending my code for the newer version of the game (R-P-S-L-S)..I felt my code is terribly bad. Here is a snippet :
if (player1.equals("ROCK") &&
player2.equals("SCISSORS")) {
winner = 1;
}
// Paper covers rock...
else if (player1.equals("PAPER") &&
player2.equals("ROCK")) {
winner = 1;
}
// Scissors cut paper...
else if (player1.equals("SCISSORS") &&
player2.equals("PAPER")) {
winner = 1;
}
else {
winner = 2;
}
I realized the code cant be extended easily for the newer version - as well as for more than 2 players. This is mainly because of multiple if/else or switch/cases. I need some help re-designing my code for achieving the 2 objectives :
Further modification as per R-P-C-L-S problem.
Support for more than 2 players.
I don't need code, just some guidelines should help.
Thanks !!
EDIT : Seems like I was wrong in thinking that this game can be played by more than 2 players. I am sorry for this mistake, please ignore the second requirement.
In, Rock-Paper-Scissor games, it is easy to decide if move a wins against move b using their index at a cycle. So you don't have to manually decide in your code the result of every combination as other answers here suggest.
For the Rock-Paper-Scissor-Spock-Lizard version:
Let's assign a number to each move (0, 1, 2, 3, 4).
Notice that every move beats two moves:
The move previous to it in the cycle (or four cases ahead)
The move two cases ahead in the cycle
So let d = (5 + a - b) % 5. Then:
d = 1 or d = 3 => a wins
d = 2 or d = 4 => b wins
d = 0 => tie
For the Rock-Paper-Scissor version:
let d = (3 + a - b) % 3. Then:
d = 1 => a wins
d = 2 => b wins
d = 0 => tie
Generalization For n >= 3 and n odd:
Let d = (n + a - b) % n. Then:
If d = 0 => tie
If d % 2 = 1 => a wins
If d % 2 = 0 => b wins
The nature of Rock-Paper-Scissors is such that you have to explicitly handle the case for every possible combination of states. So the number of cases you have to cover increases exponentially with the number of players, and polynomially (with the order of the polynomial being the number of players) with the number of options.
Having said that, Java's enums are good for this kind of thing.
Here's my stab at it:
import java.util.Arrays;
import java.util.List;
enum Result {
WIN, LOSE, DRAW;
}
enum Option {
ROCK(SCISSORS),
PAPER(ROCK),
SCISSORS(PAPER);
private List<Option> beats;
private Option(Option... beats) {
this.beats = Arrays.asList(beats);
}
Result play(Option other) {
if beats.contains(other) {
return Result.WIN;
} else if other.beats.contains(this) {
return Result.LOSE;
} else {
return Result.DRAW;
}
}
}
Adding more cases (Lizard and Spock) is consequently relatively simple. Adding more players would be more complicated; among other things, you'd have to determine what the rules of three-player Rock-Paper-Scissors even are, because I have no idea.
i think: 1 beats 2 or 5 loses to the rest. 2 beats 3 or 1 loses to the rest. 3 beats 4 or 2 loses to rest. 4 beats 5 or 3 loses to the rest. 5 beast 1 or 3 loses to the rest. For 3 players, compare the values of 2 players, then compare the winner vs player 3.
Design an enum Choice (ROCK, PAPER, SCISSORS), where each enum has a Set<Choice> which it wins against.
Have each of your players choose one of the choices.
Iterate through your players, and for each one, iterate over all the other players that are after him in the list of players (for player 0, iterate through players 1, 2, 3, etc; for player 1, iterate through players 2, 3, etc.; ...).
For each match, you have three possibilities:
A beats B (the choice of B is in the set of choices that A beats): increment A's score
A and B have the same choice: do nothing
A doesn't beat B: increment B's score
I suggested a better design in an answer to another post. Have a single switch, and switch over a single encoding of every possible combination of moves, and for an encoding use a positional number system with a base that's a power of 2, so that each digit will map directly to a number of bits, and so that bitwise manipulations are intuitive.
Three bits are sufficient for five choices, and although octal would be ideal, the syntax sucks, so use hex. Each hexadecimal digit then represents one of your five moves, with room to spare. A byte is large enough two encode the simultaneous moves of two players, an int for eight, a long for sixteen. It's straightforward. Follow the link for a code example.
This is a basic logic problem. It is small enough you can do a manual truth table ( or skip ahead to a k-map), minimize and get a solution.
So basically, you need to evaluate first, if it is a draw. Then, you need to evaluate winning relative to other players. Doing this without needing to compare against each user can be a confusing task. Since this only has 5 variables, you can find a minimized solution with a K-map.
You will need to evaluate each user, based on which item they chose with a specific algorithm to determine if they win. Note that with more than 2 players, there can be more than one winner if two people choose the same thing but both beat a 3rd player. Or you can consider that a tie, whatever. I'll assume the former. You should check also that all players didn't choose the same item.
So I've done the first part of the algorithm for you when the user you are evaluating has chosen "rock".
In code, this would look like:
rock=0, paper=0, scissors=0, lizard=0, spock=0, win=0, tie=0
if ( someone chose rock ) rock=1
if ( someone chose paper ) paper=1
if ( someone chose scissors ) scissors=1
if ( someone chose lizard ) lizard=1
if ( someone chose spock ) spock=1
// Check if tie / draw, double check these, but I think I got them all
tie=rock && !paper && spock && lizard || rock && paper && scissors ||
rock && paper && lizard || spock && paper && scissors ||
spock && !rock && paper && lizard || !spock && scissors && lizard && paper
if ( tie ) die()
CheckIfUserWins() {
if ( user chose rock ) {
win=rock && !paper && !spock
if ( user chose paper) {
// .... calculate using k-map and fill in
}
return win
Notice that win=rock && !paper && !spock is exactly what would be expected based on the graphic of what beats what at the link you provided. So you can go to that graphic and pretty quickly fill in the rest of the equations.
This solution is not dependent on any number of players other than to say "someone chose X". So it should scale to > 5 players, etc.
The shortest way:
var n = 5; // Rock, Paper, Scissors, Lizard-Spock
function calculate(x, y, n) {
return 1 - ((n + x - y) % n) % 2;
}
function getWinner(p1Gestrure, p2Guesture) {
if(p1Gestrure === p2Guesture) {
return - 1; // tie
}
return this.calculate(p1Gestrure, p2Guesture); // 0: win for p1. 1: win for p2.
}
I've created a cli game, please feel free to take a look there.
https://github.com/julianusti/rpc-es6

Categories

Resources