I'm developing a card game, based on higher wins.
From my first question here assign int value to image for compare I've rewritten my code but now I'm stuck on randomization of cards and assignment to ImageView.
I have a class card.
public class Card{
private int cardValue;
#DrawableRes
private int image;
public Card(int cardValue, #DrawableRes int image){
this.cardValue = cardValue;
this.image = image;
}
public int getCardValue()
{
return cardValue;
}
#DrawableRes
public int getCardImage()
{
return image;
}
//Cards
Card ash = new Card(20, R.drawable.ash_card);
Card atlas = new Card(23, R.drawable.atlas_card);
Card banshee = new Card(14, R.drawable.banshee_card);
and so on....
In MainActivity:
I have array of this cards:
//Creating array of the cards
ArrayList<Card> cards = new ArrayList<>();
Now I need to randomize four cards from this array and assign each one to IV.
final Random random1 = new Random();
//Generate random indexes for cards
int RandomCard1 = random1.nextInt(cards.size());
int RandomCard2 = random1.nextInt(cards.size());
int RandomCard3 = random1.nextInt(cards.size());
int RandomCard4 = random1.nextInt(cards.size());
//Generate the card from RandomCard
Card drawableCard1 = cards.get(RandomCard1);
Card drawableCard2 = cards.get(RandomCard2);
Card drawableCard3 = cards.get(RandomCard3);
Card drawableCard4 = cards.get(RandomCard4);
I'm using this, because I have flip animation for each card (maybe there is a better way to do it, but it works for me). So now I just need to assign a card to IV, but this won't work.
//Deal my cards
card1.setImageResource(drawableCard1);
card2.setImageResource(drawableCard2);
card3.setImageResource(drawableCard3);
card4.setImageResource(drawableCard4);
I can't use setImageResource for class object. I've been stuck here for days, trying to figure it out but with no luck. Should I do randomizing differently (f.e. with Collections.shuffle?). Or is there any way how to do it?
Thank you.
You actually have two different problems:
the simplest is that your cards are not showing since setImageResource requires the int representing the resource id as parameter, you'll just need to call:
//Deal my cards
card1.setImageResource(drawableCard1.getCardImage());
card2.setImageResource(drawableCard2.getCardImage());
card3.setImageResource(drawableCard3.getCardImage());
card4.setImageResource(drawableCard4.getCardImage());
Now if the UI is correctly set up you'll see the images.
The second problem (I don't know if it's intended behavior) is that some cards could be given repeatedly, since the algorithm just generates a number within the bound and repetitions could occur.
A possible solution is, as you suggested, using Collections.shuffle() on the deck at the beginning so that it would simulate the initial deck shuffling and start dealing the cards in the exact order in which they are contained in your shuffled deck.
How to deal cards
Currently, if we consider our deck to be the entire List of Card objects, the way in which the dealer is picking the next card to give is by choosing a random card in any position of the deck (list) and put it on the table (for example). This idea could be extended by removing the picked card from the deck (which is something that at the moment is not implemented), but the dealing style wouldn't represent what happens in reality.
Solution
The solution would be shuffling the cards at the beginning of the game (Collections.shuffle()) and start picking the card in the exact order in which they are contained in the list. In fact, since it's already shuffled, the dealer can pick the 0-th, 1-st, 2-nd
etc. card and put them on the table (or give them to the players). The Random object, in this case, wouldn't be needed. A simple cycle could be implemented to select the next card the dealer will pick.
Related
I'm developing a card game. From some of my previous questions (Assign int value to image fro compare and Assign random class object image to imageview I'm finally stuck on the main part - compare logic.
I have two classes - Card and EnemyCard.
public class Card{
private int cardValue;
#DrawableRes
private int image;
public Card(int cardValue, #DrawableRes int image){
this.cardValue = cardValue;
this.image = image;
}
public int getCardValue()
{
return cardValue;
}
#DrawableRes
public int getCardImage()
{
return image;
}
EnemyCard class is the same, only it's name is different.
In MainActivity I have objects, arrays, and random dealing.
//Creating objects
Card ash = new Card(20, R.drawable.ash_card);
Card atlas = new Card(23, R.drawable.atlas_card);
Card banshee = new Card(14, R.drawable.banshee_card);
...
//Creating array of my the cards
cards = new ArrayList<>();
cards.add(ash);
cards.add(atlas);
cards.add(banshee);
...
final Random random2 = new Random();
//Generate random indexes for my cards
int RandomCard5 = random2.nextInt(cards.size());
int RandomCard6 = random2.nextInt(cards.size());
int RandomCard7 = random2.nextInt(cards.size());
int RandomCard8 = random2.nextInt(cards.size());
//Generate my cards from RandomCard
Card drawableCard5 = cards.get(RandomCard5);
Card drawableCard6 = cards.get(RandomCard6);
Card drawableCard7 = cards.get(RandomCard7);
Card drawableCard8 = cards.get(RandomCard8);
Again it's the same for the EnemyCard class, only with some slight differences in the cards' names.
Then I assign the cards to IV.
//Deal my cards
card1.setImageResource(drawableCard5.getCardImage());
card2.setImageResource(drawableCard6.getCardImage());
card3.setImageResource(drawableCard7.getCardImage());
card4.setImageResource(drawableCard8.getCardImage());
Again the same for enemy cards. After this comes my clumsy design.
When you click on the IV (f.e. card1), the card is "transferred to other IV called expanded_card (this simulates larger view of the card), and a confirm button appears. If you confirm the card, it's transferred to the last IV called fight_card (this is the clumsy part).
After this is also chosen random enemy card. I did this creating array of those four enemy cards and then using switch-case and Collections.shuffle() to assign one random enemy card to an IV called fight_card2 (yeah, this is totally clumsy)
//Enemy fight cards
enemy_deck_cards = new ArrayList<>();
enemy_deck_cards.add(10);
enemy_deck_cards.add(11);
enemy_deck_cards.add(12);
enemy_deck_cards.add(13);
//Logic for enemy card for fight
public void assignImage(int card, ImageView image){
switch (card){
case 10:
image.setImageDrawable(enemy_card1.getDrawable());
enemy_card1.setVisibility(View.INVISIBLE);
enemy_card2.setVisibility(View.VISIBLE);
enemy_card3.setVisibility(View.VISIBLE);
enemy_card4.setVisibility(View.VISIBLE);
break;
case 11:
image.setImageDrawable(enemy_card2.getDrawable());
enemy_card2.setVisibility(View.INVISIBLE);
enemy_card1.setVisibility(View.VISIBLE);
enemy_card3.setVisibility(View.VISIBLE);
enemy_card4.setVisibility(View.VISIBLE);
break;
case 12:
image.setImageDrawable(enemy_card3.getDrawable());
enemy_card3.setVisibility(View.INVISIBLE);
enemy_card1.setVisibility(View.VISIBLE);
enemy_card2.setVisibility(View.VISIBLE);
enemy_card4.setVisibility(View.VISIBLE);
break;
case 13:
image.setImageDrawable(enemy_card4.getDrawable());
enemy_card4.setVisibility(View.INVISIBLE);
enemy_card1.setVisibility(View.VISIBLE);
enemy_card2.setVisibility(View.VISIBLE);
enemy_card3.setVisibility(View.VISIBLE);
break;
}
}
Setting visibility is for simulating that a card is chosen from the deck.
Lastly, there is the confirm button, where are the main parts (and some other, not so important stuff).
//Assign cards to fight
assignImage(enemy_deck_cards.get(0),fight_card2);
fight_card.setImageDrawable(expanded_card.getDrawable());
If you made it this far and haven't fainted from this horror code, I admire you. Now comes the logic and I'm stuck here.
How to achieve that the chosen cards in IVs (fight_card and fight_card2) are compared?
I tried something like this:
public void fightLogic(Card fightCard, EnemyCard fightCard2, TextView message){
if (fightCard.getCardValue() > fightCard2.getCardValue()){
message.findViewById(R.id.message);
message.setText(R.string.YOUWIN);
} else
if (fightCard.getCardValue() < fightCard2.getCardValue()){
message.findViewById(R.id.message);
message.setText(R.string.YOULOST);
} else
if (fightCard.getCardValue() == fightCard2.getCardValue()){
message.findViewById(R.id.message);
message.setText(R.string.DRAW);
}
}
But this obviously won't work. I don't see any way how to do this, if it's even possible with my horror code. If anybody has any piece of advice (and critique for sure) regarding the logic or even design, I'd be truly grateful.
Thanks.
I'm trying to create random items in a libgdx project.I'm relatively new to Java,but here is the code I've come up with for the method.
I've been at this for a week now,and figured I'd ask here for an answer.
I've been trying to come up with something that works first.So please do forgive the shabby code.
The number parameter of the method is the number of items that will be created.
The item just needs to have a random x positon,which is generated within the constraints of the width of the container.
The game is as bottom up scroller,with different platforms being generated.
private Item[] generateRandomItems(int number){
Money[] items=new Money[number];
for(int i=0;i<number;i++){
Random r=new Random();
int x =r.nextInt(120)+3;//136 is the width of the container to which the item is to be generated
Money tempitem=generateMoney(x);//generateMoney() just returns a new instance of the Money class with the created x passed in as a param.
if(i!=0) {
for (int j=0;j<i;j++) {
boolean failed=true;
while (failed) {
//getItem() returns the bounding rectangle/circle f the item
if (!Intersector.overlaps(tempitem.getItem(), items[j].getItem())) {
failed = false;
items[i] = tempitem;
}else{
Random random= new Random();
int newX=random.nextInt(120)+3;
tempitem=generateMoney(newX);
}
}
}
}else{
items[i]=tempitem;
}
}
return items;
}
I don't know if this is a correct way to do it or not,but the created Items do collide sometimes.I've been trying to find what's wrong with the code for sometime now.Any suggestions to improve the code are also appreciated.
Edit::I Know that the code is unnecessarily complicated.This is my first attempt at procedural generation.So please do forgive me.
Instead of generating a new random position if there is a collision, you should move it deliberately left or right until there is no collision. To illustrate the problem reusing random generation after each collision, if you have 10 slots and 9 slots are already filled, it could take a long time to find that open slot using random generation as you would be almost certain to hit the same object numerous times. However, if you keep track of where you’ve checked and deliberately move to a new location each time, then the worst case scenario is you’d hit each object one time before finding the empty slot.
You can check how much of an overlap there is and move the object by that amount to clear the object, then check to make sure it didn’t collide with another object next to it, if it did then keep moving it over until there is a free spot. If you hit the edge of the screen, move to the opposite side and keep moving until you find a free spot.
Also, as good coding practice you should avoid hard coding numbers (like 120+3) into method calls. Since you use the same value in multiple places, if you decide to change the width of your container to 500, then you have to change it in all those places...and if you forget to change one you’re opening yourself up for a nightmare of bug hunting. Instead you can either set an integer such as containerWidth=120 or set the container width directly using container.setWidth(120) and then use container.getWidth() each time you call your random method to get the width of the container the random value is being constrained too. Either way will work fine, whichever is better for your workflow. And I know you said this was quick and sloppy code just to get it going, so you may already be aware of this.
Thanks for the answers.I now know that checking each generated item for collision without saving the previously generated item is bad.
But I got the previous code working after some help,and wanted to share it with anyone who would need it in the future.
I moved the checking part into a new method,and added a new flag to see if the item was generated correctly,after checking for collision from all the items before it.
private Item[] generateRandomItems(int number){
Money[] items=new Money[number];
for(int i=0;i<number;i++){
Random r=new Random();
int x =r.nextInt(120)+3;
Money tempitem=generateMoney(x);
if(i>0) {
boolean generated=false;
while (!generated) {
boolean f = checkIfItemOverlapsWithPrevious(items, tempitem);
if (!f) {
items[i] = tempitem;
generated = true;
} else {
Random random = new Random();
int newX = random.nextInt(120) + 3;
System.out.println("Collided");
tempitem = generateMoney(newX);
}
}
}else{
items[i]=tempitem;
}
}
return items;
}
private boolean checkIfItemOverlapsWithPrevious(Money[] items, Money tempitem) {
for(Money item :items){
if(item!=null) {
if (Intersector.overlaps(tempitem.getItem(), item.getItem())) {
return true;
}
}
}
return false;
}
I am creating the player class for a monopoly board game. I am not exactly sure how to make the player move around the board and then store that players position. I have created an array with 40 places using
BoardSquare[] square = new BoardSquare[40];
and i have created two die using
diceOne=1+(int)(Math.random()*6);
diceTwo=1+(int)(Math.random()*6);
roll=diceOne+diceTwo;
this is the code for my player class so far
class Player
{
private String name;
private String token;
private int location;
private int balance;
public Player()
{
name = "";
token = "";
location = 0;
balance = 1500;
player = (name+token+location+balance);
}
public Player(String name, String token, int location, int balance)
{
this.name = name;
this.token = token;
this.location = location;
this.balance = balance;
}
i realize i need to initialize a player to zero and then add the value of the rolled die to give the plahyer a position on the board. However, i am really not sure what happens when space runs out, how to properly develop the for loop, etc. I have looked at some examples but i am not really sure how to properly develop the logic for a board game. Any suggestions about board game development that are outside of the scope of this question are most welcome. thx.
You can use the modulo operator to wrap positions around, e.g.:
int newPosition = (oldPosition + diceRoll) % 40;
As for passing Go you have many options. It's simplest if you define Go as index 0. You can compute the position before modulo 40 and check if its greater than 40 (meaning its about to wrap around). You can also check to see if the new position is less than the old position (which works presuming you can never have a dice roll >= 40).
Just before updating the new position of the player ,do the following check:
if(position>40)
{
position=position-40
}
update the changed position with the specifics of money
For my group project we are doing a fairly standard Hangman GUI game.
I have created a series of .png files depicting a flower that wilts as the game progresses with wrong guesses.
I have got the code to insert the ImageIcon into a JLabel, and that works fine. But I don't know how to code for the image changing when a wrong answer is guessed.
I am thinking I should create an array of the series of images and iterate through it according to the guessesLeft variable that keeps track of the number of guesses a user still has to correctly guess the puzzle.
Any ideas?
I'd recommend you to link each image to the number of guesses.
Then make method updateScore that will update user score (or guesses left) and work with images. Something like:
public class ImagedScore {
private final int guessesLeft;
private final Image image;
//getters&constructor
}
public class MainClass {
ImagedScore[] imagedScoreArray;
//constructors, other methods and data, etc.
updateScore(int score) {
ImagedScore imagedScore = imagedScoreArray[score];
//checks or other way to find proper ImagedScore object
this.score = score;
this.image = imagedScore.getImage;
}
}
I wrongly worded my last question so I'm going to retry this. I am making a card game in java, and currently I have the code to print 4 random cards in an arraylist for x number of players. I am using slick 2d and currently have a menu and a play state. I currently have 2 variables connected to each card, a ranging from 0-3, and b ranging from 0-12.
How can I display an image in the play state that will relate back properly to these 2 variables? (ex. instead of displaying ace of spades, it displays a picture of the ace of spades)
Code:
Deck ()
{
cards = new ArrayList < > ();
for (int a = 0 ; a <= 3 ; a++)
{
for (int b = 0 ; b <= 12 ; b++)
{
cards.add (new Card (a, b));
}
}
}
This is the function to draw a card from a deck
public Card PlayerCardDraw ()
{
Random generator = new Random ();
int index = generator.nextInt (cards.size ());
return cards.remove (index);
}
and this is the function that uses the above function to add a card to player 1's hand. I made this to separate each player's hand of cards.
public ArrayList <Card> p1Hand;
public ArrayList <Card> P1CardDraw ()
{
p1Hand = new ArrayList < > ();
p1Hand.add (PlayerCardDraw ());
return p1Hand;
}
I mentioned I'm using slick 2d, so I assume I won't have to post any of that code.
If I were you, I would rewrite/append the Card class to attach an image on initialisation. Create an image in a common directory, and encode it a-bb.* for an example, and create a public image constant for that particular card. then it would be as simple as calling a simple getter to display the image.