I have two files PokerCards and Frame.
PokerCards is enumeration *my suits work fine*
enum Number {
Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King;
public static final Number[] numbers = Number.values();
public static Number getNumber(int n){
return Number.numbers[n];
}
}
private final Number number;
//constructor
public PokerCards(final Suit suit, final Number number){
this.suit = suit;
this.number = number;
}
public Number getNumber(){
return this.number;
}
Below is Frame which is to be my GUI. My error checking for suits work perfectly but my numbers...not so much. I am trying to use an enhanced for-loop to match the corresponding enumeration
//card1Num is the value of the card such as Ace, Three, King and is recorded via a TextField via the GUI.
card1Num = card1TextFieldNum.getText();
if (card1Suit.equalsIgnoreCase("Diamonds")){
for (PokerCards.Number n : PokerCards.Number.values()) { //GETS STUCK
if(n.name().equals(card1Num)) {
card1 = new PokerCards(PokerCards.Suit.Diamonds, PokerCards.Number.valueOf(card1Num));
System.out.println("Card 1 good to GO");
card1Good = true;
} else {
JFrame popUpError2 = new JFrame();
JOptionPane.showMessageDialog(popUpError2, "Incorrect Input, Number Input for First Card is incorrect! Please double check" +
" your input", "ERROR", JOptionPane.ERROR_MESSAGE);
break;
}
}
Everything works lovely except the enhanced for-loop. As i test other cards i get prompted by my error. It only accepts 'Ace', the first element. Why is my enhanced for-loop getting stuck?
The problem is that you should fail only if no cards match, not if only the first card doesn't, so you want to move the failing code to outside the loop like so:
for (PokerCards.Number n : PokerCards.Number.values()) {
if(n.name().equals(card1Num)) {
card1 = new PokerCards(PokerCards.Suit.Diamonds, PokerCards.Number.valueOf(card1Num));
System.out.println("Card 1 good to GO");
card1Good = true;
}
}
if (!card1Good)
{
JFrame popUpError2 = new JFrame();
JOptionPane.showMessageDialog(popUpError2, "Incorrect Input, Number Input for First Card is incorrect! Please double check" +
" your input", "ERROR", JOptionPane.ERROR_MESSAGE);
}
The for loop works fine, the if/else logic is the issue behind errors being thrown on cards other then 'Ace'.
As you mentioned yourself - if you use 'Ace' your code will work without error because 'Ace' is the first element in Number.values() and the check n.name().equals(card1Num) will be true, triggering the code in your if statement. All other cards will fail on this and throw an error because they will be first matched against 'Ace'. If I understand correctly what you want to do I think you should use findAny() instead of your for loop. The code would be something like this:
PokerCards.Number.values().stream().filter(number ->
number.name().equals(card1Num)).findAny().ifPresentOrElse(card ->
{your_if_logic_here},
{your_else_logic_here})
Related
I have a lab for class (we are allowed to seek outside help) creating klondike solitaire. I am a total noob when it comes to programming (this is my first ever class in programming). We just learned about enums, and I have to build a deck using them (I've reviewed other questions about this, but I haven't found a solution that matches what I need yet). We have two enums (rank and suit):
public enum Rank {
ACE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING;}
and
public enum Suit {
CLUBS,
SPADES,
HEARTS,
DIAMONDS;}
Now, I need to combine them into an array called Deck, which stands as such:
public Deck() {
cards = new Card[52];
}
To put the cards into the deck, I've been trying to use the ".values" but I can't get it right. There is a testing code with this lab and it says I'm not getting any of the points for this. What am I doing wrong?
public void fill() {
for (int i = 0; i<52;i++){
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
cards[i]= new Card(r,s);
}
}
}
}
Any help is much appreciated. Thanks!
You state,
Now, I need to combine them into an array called Deck, which stands as such:
No, you need to create a class Card that has one field of each of the enums. Only after doing that can you create a Deck of your Cards. So do that -- create a Card class, give it at least two fields, one for each enum, plus an appropriate constructor, plus getters, plus a decent toString() and then you're set.
Also, this is wrong:
public void fill() {
for (int i = 0; i<52;i++){ // get rid of this loop
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
cards[i]= new Card(r,s);
}
The code above will try to stuff 52 cards into each index spot. For instance, it will try to stuff all 52 cards into the cards[0] spot, same for the cards[1] item, and only the last Card will be added. You'll have an array of 52 King of Diamonds -- not what you want.
Instead, get rid of the outer loop, and instead increment the i inside your loop:
public void fill() {
int i = 0;
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
cards[i]= new Card(r,s);
i++; // increment i here
}
}
}
I'm in the process of writing a very simple quiz-style boardgame that moves players around the board based on if they answer the question correctly and what they roll on the dice. I'm attempting to create and pass an array mehtod that stores the scores of player 1 and player 2, but the array doesn't seem to actually keep track of the score. For example, a fragment of some of the code is as follows:
public static int[] scorearray
{
int scoreplayer1 = 0;
int scoreplayer2 = 0;
return new int[] = {scoreplayer1, scoreplayer2};
}
public static int questions(int diceroll, int[] score)
{
String textinput = input("What's 9+10?");
int ans = Integer.parseInt(textinput);
if (ans == 19)
{
output("Fantastic answer, that's correct!");
diceroll = dicethrow(diceroll); // rolls the dice
output("Move forward " + diceroll + " squares. You are on square " + score[0]);
//I need the output above to print position 0 in the above array
score[0] = score[0] + diceroll; //array stores the cumulative score
}
else
{
output("Sorry, the answer was 19. Next player's turn.")
//This is where I need the loop to switch between players
}
In addition, I need to come up with a way of switching between player 1 and 2 while also switching to the position 1 in the above array, that is, I need to add to player two's score instead of player one's. I've been combing through this code for ages now trying to figure out how to do this but I can only come up with the idea of using a for/while loop. Other than that I'm truly stumped.
Thanks.
EDIT: It appears that my array apparently still does not store the score when being used in the method questions.
Also I have now realised I can control whose turn it is by creating another method, for example public static void activePlayer() but I'm still not sure how to use a loop (or anything else for that matter) to switch between the two. Also my concern is where I use score[0] = score[0] + diceroll; in my questions method only keeps the score (or at least attempts to; see above problem) for player one. How would I switch it to keep score for score[1]? Please.
your options here seem to be either have your questions function output the score or change your score object to be a static object instead of a static function.
public static int[] scorearray = [0,0];
or
public static int[] questions(int diceroll, int[] score)
In the land of Puzzlevania, Aaron, Bob, and Charlie had an argument over which
one of them was the greatest puzzler of all time.
To end the argument once and
for all, they agreed on a duel to the death.
Aaron was a poor shooter and only hit
his target with a probability of 1>3.
Bob was a bit better and hit his target with a
probability of 1>2.
Charlie was an expert marksman and never missed. A hit means
a kill and the person hit drops out of the duel.
To compensate for the inequities in their marksmanship skills, the three decided
that they would fire in turns, starting with Aaron, followed by Bob, and then by
Charlie. The cycle would repeat until there was one man standing, and that man
would be the Greatest Puzzler of All Time.
An obvious and reasonable strategy is for each man to shoot at the most accurate
shooter still alive, on the grounds that this shooter is the deadliest and has the best
chance of hitting back.Write a program to simulate the duel using this strategy.
Your program should use
random numbers and the probabilities given in the problem to determine whether
a shooter hits the target.
Create a class named Duelist that contains the dueler’s
name and shooting accuracy, a Boolean indicating whether the dueler is still alive,
and a method ShootAtTarget ( Duelist target ) that sets the target to dead if
the dueler hits his target (using a random number and the shooting accuracy) and
does nothing otherwise.
Once you can simulate a single duel, add a loop to your program that simulates
10,000 duels. Count the number of times that each contestant wins and print the
probability of winning for each contestant (e.g., for Aaron your program might
output “Aaron won 3,595>10,000 duels or 35.95%”).
An alternate strategy is for Aaron to intentionally miss on his first shot. Modify the
program to accommodate this new strategy and output the probability of winning
for each contestant.
Which strategy is better for Aaron: to intentionally miss on the
first shot or to try and hit the best shooter? Who has the best chance of winning,
the best shooter or the worst shooter?
Ok so that the problem. Here is my code so far:
public class Duelist {
private String name;
private double probabilityOfHitting;
private boolean alive = true;
//Only declared instance variables. Must created setters and getters
public void setName(String newName){
name = newName;
}
//name setter created
public void setProbabilityOfHitting( double newProbabilityOfHitting){
probabilityOfHitting = newProbabilityOfHitting;
}
//probability of hitting setter created
public void setAlive(boolean newAlive){
alive = newAlive;
}
//name setter created
//now must create getters
public String getName(){
return name;
}
//created the name getter
public double getProbabilityOfHitting(){
return probabilityOfHitting;
}
//created the probability of hitting getter
public boolean getAlive(){
return alive;
}
//created the alive getter
//no constructors created before
public Duelist(String tempName, double tempProbability){
name = tempName;
probabilityOfHitting = tempProbability;
}
//constructor is now created
//need to create a method for the duelists to shoot at each other
public void shootAtTarget(Duelist target){
double randomNum = Math.random();
if (this.probabilityOfHitting ==1){
target.setAlive(false);
target.getAlive();
}
else if (randomNum <= this.probabilityOfHitting){
target.setAlive(false);
target.getAlive();
}
else {
target.getAlive();
}
}
}
public class Tester {
public static void main(String[] args) {
int winsA = 0;
int winsB = 0;
int winsC = 0;
Duelist aaron = new Duelist("Aaron",(1/3));
Duelist bob = new Duelist("Bob", (1/2));
Duelist charlie = new Duelist("Charlie", 1);
if(aaron.getAlive() == true){
if(charlie.getAlive()== true){
aaron.shootAtTarget(charlie);
}
else if(bob.getAlive() == true){
aaron.shootAtTarget(bob);
}
else{
winsA++;
}
}
else if(bob.getAlive() == true){
if(charlie.getAlive() == true){
bob.shootAtTarget(charlie);
}
else if(aaron.getAlive() == true){
bob.shootAtTarget(aaron);
}
else{
winsB++;
}
}
else{
if (bob.getAlive() == true){
charlie.shootAtTarget(bob);
}
else if(aaron.getAlive() == true){
charlie.shootAtTarget(aaron);
}
else{
winsC++;
}
}
System.out.println(winsA);
System.out.println(winsB);
System.out.println(winsC);
}
}
I know I haven't gotten close to finishing the problem yet. What I did in my tester class was to try and simulate one duel and once when I simulated one duel, I would be able to loop it so I can simulate more. The problem I'm having is that the when I run the code, the wins for Aaron, Bob, and Charlie all come up to 0 and I don't know why.
As the last parameter in the constructor calls, you wrote
Duelist aaron = new Duelist("Aaron",(1/3));
There you are dividing an int by another int, and the result will be 0 in this case. This has to be changed to
Duelist aaron = new Duelist("Aaron",(1.0/3.0));
so that double values are used (and the result will be 0.3333, as desired).
Most of your Duelist class does not seem to be "wrong", but the shootAtTarget method could be improved.
A general hint: I'd recommend you to never use Math.random(). This will deliver unpredictable results. Instead, you should use an instance of java.util.Random. This can be initialized with a certain random seed, so that it always provides the same sequence of random numbers. This makes debugging much easier.
Additonally, some tests have been redundant. When the probabilityOfHitting is 1.0, then there is no special test required: The random number will always be less-than-or-equal to 1.0. You are also occasionally calling target.getAlive() for no apparent reason.
So in the end, the method could look like this:
private static Random random = new Random(0);
//need to create a method for the duelists to shoot at each other
public void shootAtTarget(Duelist target)
{
double randomNum = random.nextDouble();
if (randomNum <= this.probabilityOfHitting)
{
target.setAlive(false);
}
}
However, the main problem was in your Test class. I'm not sure about general recommendations here. One could go very far in terms of abstraction. (A Java Enterprise Architect would probably end up with writing a AbstractDuelistStrategyFactory somewhere...). But to put it simply: At the moment, you are doing at most one shot. After one shot, nobody can have won. And you don't know how many shots have to be taken before there is only one duelist remaining.
Much of this could be made more elegant and flexible if you placed the Duelists into a List<Duelist>. But without that, an approach that is "structurally close to what you started" could look like this:
int alive = 3;
while (alive > 1)
{
System.out.println("Status: A:"+aaron.getAlive()+" B:"+bob.getAlive()+" C:"+charlie.getAlive());
if (aaron.getAlive())
{
if(charlie.getAlive())
{
System.out.println("A shoots at C");
aaron.shootAtTarget(charlie);
if (!charlie.getAlive())
{
System.out.println("A killed C");
alive--;
}
}
else if(bob.getAlive())
{
System.out.println("A shoots at B");
aaron.shootAtTarget(bob);
if (!bob.getAlive())
{
System.out.println("A killed B");
alive--;
}
}
}
// Other cases ...
}
if (aaron.getAlive())
{
winsA++;
}
if (bob.getAlive())
{
winsB++;
}
if (charlie.getAlive())
{
winsC++;
}
(Note that there are still cases missing!)
includes a pile of cards in a player’s hand and two actions: TAKE and DISCARD. TAKE puts a card on the top of a player’s pile of cards when that player receives a card from a dealer. DISCARD removes a card from the top of a player’s pile of cards when a player plays it against another player in the game. Each player receives 16 cards from the dealer at the
beginning of a game........
I tried my code like this which gives me nothing
public class play {
int noOfCards = 16;
static void TAKE(Stack st, int a) {
st.push(new Integer(a));
}
static void DISCARD(Stack st) {
Integer a = (Integer) st.pop();
}
public static void main(String args[]) {
for(int i=0; i<=16; i++) {
Stack st = new Stack();
st.take();
st.discard();
}
}
}
I am new to this concepts ....give me a path to solve this question
I'm sorry but I didn't fully understand the whole process you're trying to do. But I still gave it a shot.
public class Play
{
private static int noOfCards = 16;
private static Stack<Integer> player1 = new Stack<Integer>();
private static Stack<Integer> player2 = new Stack<Integer>();
static void takeCard(Stack<Integer> st,int cardValue){
st.push(cardValue);
}
static int discardCard(Stack<Integer> st){
return st.pop();
}
static int getRandomValue(int min, int max){
Random r = new Random();
return r.nextInt((max - min) + 1) + min;
}
//Filled card pile with random values from 1-13
public static void main(String[] args)
{
for(int i = 0 ; i < noOfCards; i++){
takeCard(player1,getRandomValue(1,13));
takeCard(player2,getRandomValue(1,13));
}
//player 1 takes a card!
//Size of player1's pile before and after taking card
System.out.println("Before:" + player1.size());
takeCard(player1, getRandomValue(1, 13));
System.out.println("After" + player1.size());
//player 2 discards a card and outputs the card's value
System.out.println("Player 2 discards: " + discardCard(player2));
}
}
Not sure what you want it to do. Are you just trying to implement TAKE and DISCARD? Despite not knowing exactly what you're trying to do, there are lots of issues with your code.
One immediate issue is the fact that your Stack initialization is inside your for loop meaning that every time you execute that loop, you create a brand new Stack, which will be empty. So, essentially, your main method does this:
Create a new Stack (it's empty)
Add a card to the stack
Remove a card from the stack
Repeat steps 1-3 16 times
Another issue is that Java is case sensitive so calling st.take() doesn't match up with TAKE().
Yet another issue is that st.take() is like saying "Call the 'take()' method on my instance of Stack". Stack doesn't define a method called take() - it has methods like push() and pop() (look here: http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html). Your take and discard methods are on the class Play, so you'd want to invoke them like this:
Play.TAKE(st, 3);
Play.DISCARD(st);
Another issue: when you try to invoke keep or discard, you don't send any parameters, but you've defined these methods to take parameters. See above.
Is discard supposed to return the value of the card being discarded? You retrieve that value and store it into the local variable "a" and then you don't do anything with it. If you're not going to return it, you don't need to create "a". If you are going to return it, your return type shouldn't be void.
Ok so i have looked about for an answer. I am using a random generator to generate numbers based on the user input. This will then select a random number from that and assign them a special position in the game. However the problem is i keep getting repeated values which isn't what i want. So could anyone help?
in
(blueprint class)
int getRoll()
{
roll=rand.nextInt(totalNum);
return roll;
}
(main class)
for(numberOfWerewolves=0;numberOfWerewolves!=wolves.werewolfNum;numberOfWerewolves++)
{
playerNumber++;
wolves.getRoll();
System.out.println(wolves.roll);
}
anyone can help me would be great thanks
It sounds like you want several random numbers within the same range, but you don't want any repeats. If so, what you want is called a "shuffle." Fill an array with the numbers from 1 to N (or 0 to N-1, or whatever), shuffle the array, and then start using the numbers from the beginning of the array.
A good description and implementation of shuffling is given here:
https://stackoverflow.com/a/1520212/1441122
Create a list to keep track of previous random numbers, and loop to keep recalculating the random number until it doesn't match any of them in the list:
public static boolean checkIfExists(ArrayList<Double> list, double x) {
for (double d : list) {
if (d == x) {
return false;
}
}
return true;
}
ArrayList<Double> list = new ArrayList<Double>();
int getRoll()
{
while (true) {
roll = rand.nextInt(totalNum);
if (checkIfExists(list, roll)) {
list.add(roll);
return roll;
}
}
return -100; // -100 means it couldn't generate a number
}
You should not keep the while condition to be true; you should modify it so that it only loops for until you're sure that a unique number can't be generated.