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.
Related
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.
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
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.
So I have been studying Java for about 8 weeks and for class I had to design a shape guessing game. Yes it is Homework. So I have built my four shape classes with an example of one below.
public class square extends shape {
//square member variables
boolean equalSides = true;
// check if sides are equal
public boolean isEqual() {
return equalSides;
}
//constructor
public square(int numsides, String shapeName, boolean b, String shapehint) {
super(numsides, shapeName, shapehint);
}
}
I then created a shape.java class
public class shape {
int numSides;
String shapeName;
String shapeHint;
public shape(int numsides, String shapename, String shapehint) {
numSides = numsides;
shapename = shapeName;
shapehint = shapeHint;
}
//getter methods
public int getSides() {
return numSides;
}
public String getName(){
return shapeName;
}
public String getHint(){
return shapeHint;
}
}
It's now that I have reached the shapeGuesser class that I am starting to struggle just a little. I'm unsure how to incorporate a guard for my game and the JOptionPane side of it. I need shapeGuesser to run until the user guesses the correct shape.
I have been instructed to present the user with this option at the start.
What question shall I ask?
Enter Number:
1.How many sides?
2.Are your sides the same length?
3. Hint
Based on the number you enter 1, 2 or 3.That question will be asked of that
shape. So your Shape must have an appropriate response ready.
import javax.swing.JOptionPane;
import java.util.Random;
public class shapeGuesser {
public static void main(String[] args, Object Do) {
// TODO Auto-generated method stub
// the shape the program uses
int random;
shape shapeChoice;
// create shapes
square s = new
square(4, "Square", true, "Geeks were called this in the 80s");
Rectangle r = new Rectangle(4, "Rectangle", false, "Not Pentangle");
Triangle t = new Triangle(3, "Triangle",false, "Toblerone");
Circle c = new Circle(0, "Circle",true, "Circle Circle Circle");
//declare shape array
shape[] Shapes;
//create shape array
Shapes = new shape[4];
//put shape objects in shape array
Shapes[0] = s;
Shapes[1] = r;
Shapes[2] = t;
Shapes[3] = c;
// generate random number
random = (int) (1 + (Math.random() * 3));
//pick shape from shape array based on random number
shapeChoice = Shapes[random];
}
}
Anyone who read this far and might have the time to enlighten me in anyway. It would be much appreciated.
Thanks,
isEqual() needs an implementation in the base class, shape, as with all methods you want to call on all your shapes. Have the base shape return false. (Ideally shape should be abstract so you can't have a basic shape object, only squares, rectangles, etc. but its okay, you're new, and nobody else will use this. So you yourself can just never create a base shape. But for the future, that's what abstract is for ^^) Then, have all your other shapes override that base isEqual() the way your square already does.
You're doing good! You've selected a random shape, and created many shapes.
Now create a loop that prints the options,
system.out.println("Enter Number: 1.How many sides? 2.Are your sides the same length? 3. Hint");
Then take the user input, and parse it to an integer. Have an if/else/else or a switch/case using that integer. (alternatively, use if/else/else with the string as it is, but make sure to use .equals() not ==)
So now you've asked a question, and selected one. Now you print out
if(userInput.equals("1")){
system.outprintln("How many sides? " + shapeChoice.getSides());
}
Do the same thing for 2 and 3. You'll be dealing with a shapeChoice, so you have to call the base methods of shape. However, at runtime, if the object is a square or a rectangle, when you call shapeChoice.getSides() it will invoke the square or rectangle implementation, giving you the answer you want! :)
Then all you have to do is loop back, ask the question over and over again, and if the user wants to, let him guess, and check his answer! (compare .equals(shapeChoice.getName()))
so have a big while(true) forever loop, inside of which you can ask a question, and then check if they want to answer. If they answer right, you break out. Otherwise, you loop back around, and keep asking them which hint they'd like.
EDIT: Actually, now that I look at it, since you're practicing polymorphism, you should probably use it a little more. Right now, You have your separate classes, but you're passing in all your information when you construct them. Instead of:
square s = new square(4, "Square", true, "Geeks were called this in the 80s");
Rectangle r = new Rectangle(4, "Rectangle", false, "Not Pentangle");
Have it be more like
square s = new square();
and have part of square's definition inherently define
public class square extends shape {
//square member variables
boolean equalSides = true;
int numSides = 4;
//and so on
//OR even better, don't define them, since the base class already does!
//merely set the values in the constructor
public square(){
numSides = 4;
equalSides = true;
shapeHint = "Geeks were called this in the 80s";
}
}
EVERY square object is going to be this way, so there's no reason it should be a parameter. That is part of the definition of a square.
Sorry for wall of text, but currently stumped. I'm not asking to be "spoon feed" since I have the basic idea down for each piece, it's just I'm having a difficult time on how to finish determining my move logic. Allow me to further explain. I'll be posting my code as well for better reference.
I'm coding with a MVC structure. I have a Model which is a 2D array of BoardSquares. Which those BoardSquares keep track of it's location on the board, what piece is in it (if there is one), what color that piece is (if there is one), and if it's empty. Here's the code for it:
public class BoardSquare {
// Private information stored in each BoardSquare
private boolean isSquareEmpty;
private int row;
private int col;
private String space;
private String pColor;
// Constructor to make an empty space on the board
public BoardSquare(int row, int col) {
space = "";
pColor = "";
this.row = row;
this.col = col;
SquareEmpty();
}
//Constructor to get the information of a space with a piece
public BoardSquare(BoardPiece piece, int row, int col) {
this.space = piece.getModelName();
this.pColor = Character.toString((piece.getModelName().charAt(0)));
this.row = row;
this.col = col;
SquareNotEmpty();
}
public String getpColor() {
String temp = getPieceColor(pColor);
return temp;
}
//A bunch of auto generated getters/setters...
// Gets the correct color label for the piece
public String getPieceColor(String info){
String temp;
if(info.equalsIgnoreCase("b")){
temp = "Black";
}
else {
temp = "White";
}
return temp;
}
Currently all my Pieces extend an abstract BoardPiece class which has several abstract methods as well, but my piece knows of it's location on the board, it's name, it's color, and the 2D board array for the way I'm generating the valid moves.
I'm generating them by checking the spaces it can move to and seeing if they are empty and adding them to an ArrayList and comparing and seeing if that list contains the inputted destination.
However I'm having problems thinking of how to stop checking if say Black Rook was on the left side of the board and wanted to move all the way to the Right, but there was a Black Pawn to the right of the Rook preventing it from doing so. I'm trying to generically think of it to make my life easier and I can implement it in the other piece classes as well So here's the Rook's code:
public class Rook extends BoardPiece{
private String name = "Rook";
private String color;
private String modelName;
BoardSquare board[][];
// Both should remain 0 - 7
private int row;
private int col;
public Rook (String modelName, int row, int col, String color, BoardSquare[][] field) {
this.modelName = modelName;
this.row = row;
this.col = col;
this.color = color;
this.board = field;
}
#Override
void move(BoardSquare target) {
if(!getPossibleMove(board).contains(target)){
//Sysout false move
}
}
#Override
Collection<BoardSquare> getPossibleMove(BoardSquare[][] board) {
ArrayList<BoardSquare> validMoves = new ArrayList<BoardSquare>();
for(int i = 0; i < 8; i++){
// Checks every column of the row that the piece is on
if(moveValidator(board[row][i])){
validMoves.add(board[row][i]);
}
// Checks every row of the column that the piece is on
if(moveValidator(board[i][col])){
validMoves.add(board[i][col]);
}
}
return validMoves;
}
#Override
boolean moveValidator(BoardSquare space) {
// Removes the current square the piece is on as a valid move
if(space.getRow() == getRow() && space.getCol() == getCol()){
return false;
}
//Checks if the space is not empty and the piece in the spot is the same color as the piece itself
if(!space.isEmptySquare() && space.getpColor().equalsIgnoreCase(color)){
return false;
}
return true;
}
Like I said any help or push toward the right direction would be appreciated. Sorry for the wall of text but trying to be as clear as I can so that whoever wants to help can fully understand and see my logic.
EDIT: Forgot to note that the Rook has Auto-generated Getters and Setters as well.
I would approach it the most brute-force and intuitive way possible: think of moving the rook one square at a time as it takes its turn and see if it collides with anything. That is, hop it across every square until it gets to the desired spot and check if it's a valid move at each square.
This is a fine approach because
it's easy to understand
it's not expensive until your chess board gets massively huge, so brute force isn't a problem.
it generalizes to all pieces: rooks have to "slide" to their destination, but knights can "jump" or "teleport" over other pieces to their new location, so don't need the intermediate hops.
This sounds close to your current implementation, but you need to stop tracing when you collide. That is, if there is a black pawn in the way, the columns after that pawn are no longer valid spaces, right? In other words, think of the move as an action that the rook takes instead of an independent state space of possible moves, since some spaces are legal moves except that the rook was previously blocked. You need to know where the rook is from and where it is going to determine valid moves, not just if the space is in the same row.
So, reading your code (thanks for posting the context, by the way, it's quite helpful) really all you need to do is not iterate on each square, but iterate moving through each square, and stop the iteration when you get blocked.