so i have JXButton[][] array (gridLayout) and each JXButton holds an icon, a piece,which player belongs to and has a mouseListener.
I am currently trying to make the Stratego Game(Two Players-I handle both).
I set up the icons,pieces and how a piece should move alright.
Now i wish to make it play by turn.
For example when is Player1 Turn i need all Players2' pieces to change icon to Hidden(hidden.png) and vice versa.
I have tried something like this.
tmp1, tmp2 are Icon arrays
pieceimgsB,R hold the Hidden Icon
allbuttons is my JXButton[][] array
public void makeHidden(int iD){
if(iD==1){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
tmp1[i][y]=allbuttons[i][y].getIcon();
allbuttons[i][y].setIcon(new ImageIcon(pieceimgsB[12]));
}
}
}
}
else if(iD==2){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
tmp2[i][y]=allbuttons[i][y].getIcon();
allbuttons[i][y].setIcon(new ImageIcon(pieceimgsR[12]));
}
}
}
}
}
public void restoreHidden(int iD){
if(iD==1){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
allbuttons[i][y].setIcon(tmp1[i][y]);
}
}
}
}
else if(iD==2){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
allbuttons[i][y].setIcon(tmp2[i][y]);
}
}
}
}
}
I my mind makeHidden Player2 pieces hidden when its Players1 turn.
And restoreHidden should change back the Icons when its Players2 turn.
If these two methods seem ok , where my problem lies is how to implement the turns.
I must say that (When i click on a JXButton and then click on another one, the
piece moves on the board as it should). I tried having a flag in my mouseListener that when one actually moves the turn changes, but i cant make it work by turns.
I have wrote this :
public void letsPlay(){
switch (turn){
case 1:
getsb().makeHidden(2);
//getsb().restoreHidden(1);
if(getsb().getPlayerMoved()==true){
setTurn(2);
}
break;
case 2:
getsb().makeHidden(1);
//getsb().restoreHidden(2);
if(getsb().getPlayerMoved()==true){
setTurn(1);
//;
}
break;
}
}
I need to know if these two methods seem ok according to what they should do and a little insight on how to get it to work by turns.
Should i have the getPlayerMoved() (which returns the flag in the mouseListener in a while outside the switch case)?
Maybe i am tired and i dont see it but any insight would be helpful.
If someone needs it i can provide my mouseListener Code too although its a bit messy.
This seems to be an XY problem, the main point is not to specialize your listener to manage such behavior (and other inherent behaviors) but how to design something that is modular and easily maintainable.
I'd suggest you to try to workaround your problem by thinking how you could design your game and UI structure. Let's make a simple example:
First of all you have a game piece which has a type and a player, so why don't you use a specific object type for this? Eg:
class PieceType {
String name;
String iconName;
}
class Player {
String name;
}
class Piece {
PieceType type;
Player owner;
class BoardCell {
Piece piece;
}
Then you surely need a Board class able to manage the game board, eg:
class Board {
private BoardCell [][] pieces = new Piece[10][10];
public BoardCell cellAtPiece(int x, int y) { return pieces[x][y]; }
/* other functions */
}
Finally you should have a Game class which manages the whole thing, eg:
class Game {
Board board;
Player[] players = new Player[2];
Player currentPlayer;
Player getCurrentPlayer() { return currentPlayer; }
/* other methods, eg turn advance, check for correct position, eat piece etc */
}
Now you reached a point in which you have the structure of the game, and you can think about the UI, which should rely on the Game instance without the need of additional inputs (and Game shouldn't even know about the UI). You could extend a JXButton and provide custom behavior, eg:
class BoardButton extends JXButton {
final private Game game;
final private BoardCell cell;
public BoardButton(Game game, int x, int y) {
this.game = game;
this.cell = game.cellAtPiece(x,y);
}
public void refreshIcon() {
if (cell.piece == null) { setIcon(null); }
else if (cell.piece.owner != game.getCurrentPlayer()) { setIcon(hidden); }
else setIcon(cell.piece.type.icon);
}
/* other utilities, like checking if a piece can be moved from here for current player and such */
Mind, I didn't answer directly to your question, but I explained some tools which would allow it to be solved easily together with all problems that you could find in implementation.
Related
I know everyone gets skeptical whenever people put homework on here but I've run out of options and could really use some direction. I have a project where I have to create a deck of cards and allow the user to pick the size of the hand and then fill that hand with random cards and display that to the user. I've found plenty of answers using ArrayLists but mine requires an array and I've tried everything I know and my code is either completely wrong or throws a bunch of errors.
So here are the problems I have:
1) The addCard method in the Hand class can be used to add one Card object at a time to the hand array until it is full. It should increment the cardsInHand counter each time a Card object is added to the Hand as long as there is room for the Card to fit into the Hand.
Here is the code for the Hand class:
public class Hand
{
private int handSize; //Holds the size of the hand
private int cardsInHand; //Holds the number of cards allowed in the hand
private Card[] hand; //Array of card objects
public Hand()
{
this.handSize = 5;
this.cardsInHand = 0;
this.hand = new Card[52];
}//end Default Constructor
public Hand(int handSize)
{
this.handSize = handSize;
}//end Parameterized Constructor
public Hand(Hand handIn)
{
this.handSize = handIn.handSize;
this.cardsInHand = handIn.cardsInHand;
this.hand = handIn.hand;
}//end Copy Constructor
public void addCard(Card card)
{
hand[card]; //--> throws a type mismatch exception (change card param to an int)
}//end addCard()
public int getHandSize()
{
return handSize;
}
public void setHandSize(int handSize)
{
this.handSize = handSize;
}
public int getCardsInHand()
{
return cardsInHand;
}
public void setCardsInHand(int cardsInHand)
{
this.cardsInHand = cardsInHand;
}
public Card[] getHand()
{
return hand;
}
public void setHand(Card[] hand)
{
this.hand = hand;
}
public String toString()
{
String msg = "";
return msg;
}//end toString()
}//end class
My addCard method is just all janky and I could really use some help trying to fill it so my program works. Any help or even a pointing in the right direction would be appreciated!
My addCard method is just all janky and I could really use some help trying to fill it so my program works. Any help or even a pointing in the right direction would be appreciated
Sometimes the best thing to do is stop, turn the screen off, get a pen and piece of paper and just nut it out without any code. Try to understand the problem and get the logic straight in your head.
Basically, you have a series of buckets into which you can put a Card. Before you can put a Card in a bucket, you need to know if you have any free buckets available.
If there are, you need to add the Card to the next available bucket (which should be pointed to by cardsInHand) and increment cardsInHand
Your error is because you're trying reference a "bucket" using a Card, but you can only reference a "bucket" by an index (number) so...
hand[card];
should be more like...
hand[cardsInHand] = card;
but only after you've determined if there is a free "bucket" available, and you should increment cardsInHand AFTER this statement
I'd also be worried about your constructors
public Hand(int handSize)
{
this.handSize = handSize;
}//end Parameterized Constructor
isn't initialising hand, so that's going to be null. A better solution might be to use existing constructors where possible to build a common "initialisation" path
public Hand() {
this(5);
}//end Default Constructor
public Hand(int handSize) {
this.handSize = handSize;
this.cardsInHand = cardsInHand;
this.hand = new Card[handSize];
}//end Parameterized Constructor
Also
public Hand(Hand handIn)
{
this.handSize = handIn.handSize;
this.cardsInHand = handIn.cardsInHand;
this.hand = handIn.hand;
}//end Copy Constructor
is worrying, as it's possible for some external class to make a change to handIn's hand and that change will be reflected by this instance as well (as they are pointing to the same array).
A "copy" constructor should be making a "copy" of the data. Realistically, this should probably be a "deep" copy, so any changes to Card don't mess with the Hand as well, but I'll start with a simple "shallow" copy to get you started
public Hand(Hand handIn) {
this.handSize = handIn.handSize;
this.cardsInHand = 0;
this.hand = new Card[this.handSize];
// Yes, I know there is a better way to do this, but
// I want the OP to learn something
for (int index = 0; index < handIn.hand.length; index++) {
Card card = handIn.hand[index];
if (card != null) {
hand[cardsInHand] = card;
cardsInHand++;
}
}
}//end Copy Constructor
#MadProgrammer already give better answer, I only want to chime a little. Knowing the OP project assignment using Java I want to comment a little about the Hand class design.
The task clearly said that user can pick hand with custom size, then the user will add card into the hand until the hand is full. Thus, I would propose the Hand class design like below.
public class Hand {
private int size; // Hold the amount of card can be hold by hand.
private int counter; // Count how many card added.
private Card[] cards; // The card on hand.
public Hand(int size) {
this.counter = 0;
this.size = size;
this.cards = new Card[size];
}
public void addCard(Card card) {
if (this.counter > this.size) {
throw new IllegalStateArgument("The hand is full of card!");
}
this.cards[this.counter] = card;
this.counter++;
}
public String show() {
StringBuilder result = new StringBuilder("The card on hand is: \n");
for (int i=0; i<this.size; i++) {
result.append(this.cards[i].toString()).append("\n");
}
return result.toString();
}
}
In my opinion the Hand class more easy to understand and achieve the goals of the Hand purpose from the task. However, just use this as reference and write code that you understand well.
public class Boss{
public void Attack1(){
int randomspace = (int )(Math.random() * 3 + 1);
System.out.println("Attacking space " + randomspace);
if(space == randomspace){
//Something right here to kill the player
}
}
}
But space is in a different class called Player
public class Player {
int space = 1;
}
I thought about making a separate space variable and change them at the same time, but how would the Boss class know when to increment/decrement at the same time as the Player class. it would be easier to just keep it in the one class for simplicity.
EDIT: I figured it out. public class Boss extends Player{ and that fixed my problem
Use parameters. (and lowercase your methods)
A boss will attack a space.
public void attack(int space){
if(space == randomspace){
//Something right here to kill the player
}
If you need the Player, then you should really be using some abstract class, say Unit, then use Hero to be the main piece.
Then you can have
public void attack(Unit unit){
if(unit.getSpace() == randomspace){
//Something right here to kill the player
}
And ideally unit.getSpace() could also come from some Board class that holds all information about the Unit types
Then, your logic elsewhere says boss.attack(player) or boss.attack(player.getSpace())
I've been learning Java by experimenting with a little "game" that started with just trying to make a ball jump. I've got 3 classes (JumpingBall3, BallSprite3, & Floor) and have achieved a gravity of some sorts, a jump that works consistently, and hit detection against floors to stop the ball falling infinitely. With this last point I've spotted a potential issue with future development. Right now I have two floors created by JumpingBall3 ("floor1" & "platform") and I detect collision within the BallSpite3 using the following code:
public boolean collision()
{
if (game.floor1.getBounds().intersects(getBounds()) || game.platform.getBounds().intersects(getBounds())) {
onFloor = true;
}
else
{
onFloor = false;
}
return onFloor;
}
If I were to keep adding more floors or platforms that "if" condition is quickly going to spiral out of control in terms of length. Is there a way to create a method that cycles through all visible Floor objects created in my JumpingBall3 class?
I've posted the full code online here, it seemed a bit lengthy to include within this post.
The simplest thing to do is to keep all the objects that you want to check in a Collection like for example a List, then iterate over this List.
So for example, here a good choice would be to use a collection of Floor, on which we iterate to check if we have a collision with one of them.
public boolean collision() {
boolean onFloor = false;
Rectangle rectangle = getBounds();
for (Floor floor : floors) {
if (floor.getBounds().intersects(rectangle)) {
onFloor = true;
break;
}
}
return onFloor;
}
Assuming that you use Java 8 , you could rely on the Stream API to do the same thing as next:
public boolean collision() {
Rectangle rectangle = getBounds();
return floors.stream().map(Floor::getBounds).anyMatch(rectangle::intersects);
}
An approachable solution to this problem is to have your "game world" contain a list of entities (where an entity can be a ball or wall or any other in game object), and have some mechanism that detects which entities are near which other entities. This would end up calling some type of entity.checkCollision(neighborEntity) method.
You still need to have different behaviors for colliding with different entities. You can do this by having the base Entity class have some common attributes you can turn off or on, or store behaviors that you can apply directly to the collided entity.
// within some game loop, check for collisions
for (Entity entity : collidableEntities)
{
ball.checkCollision(entity);
}
Your classes could look like this to have programmed behaviors.
public Entity
{
public void applyCollisionBehaviorTo(Ball ball) { // Override to do something}
public void onCollision() { // Override to do something }
public collidesWith(Entity neighbor) { // your collision math }
public void checkCollision(Entity neighbor)
{
if (collidesWith(neighbor))
{
onCollision()
}
}
}
public Wall extends Entity
{
#Overide
public void applyCollisionBehaviorTo(Ball ball)
{
ball.reverseDirection();
}
}
public Ball extends Entity
{
#Overide
public void onCollision(Entity collidingEntity)
{
collidingEntity.applyCollisionBehaviorTo(this);
}
}
create a list with all objects. then use a loop over all the object you want to detect (excepting the one that making the detection of course)
So I've been stuck on this issue for quite some time now and I just can't seem to figure out the solution. I'm currently working on a project that simulates a parking garage. The parking garage itself isn't the issue; it's the several types of customers that are supposed to be simulated. To make things a little easier I'll ask for the solution of one and with that I should be able to work out the others myself.
For starters it is a requirement to create a separate class for customers with a parking pass and integrate this in a way that shows which cars are parking pass holders and which aren't.
import java.util.Random;
/* creates a boolean called isPass that is randomly picked to be true or false. */
public interface ParkPass {
public Random rnd = new Random();
public boolean isPass = rnd.nextBoolean();
}
This is the class that allows me to randomly set a parking pass. Since the simulation happens through a different class, all I can do is create the method to set the Pass to true or false; I can't set the Pass itself in this class.
public abstract class Car {
private Location location;
private int minutesLeft;
public boolean isPaying;
public boolean isBlue;
public void setIsPaying(boolean isPaying) {
this.isPaying = isPaying;
}
// added a method to allow us to set the colour of the car to blue for when they have a parking pass.
public void setIsBlue(boolean isBlue) {
this.isBlue = isBlue;
}
This is a small snippet of the Car class that shows which booleans belong to it and might show you which direction I'm trying to go with this simulation.
public class AdHocCar extends Car implements ParkPass{
public AdHocCar() {
setIsBlue(isPass);
setIsPaying(!isPass);
}
}
This is the class that is called when simulating a car going in and out of the parking garage. Here you can see I tried implementing the ParkPass class in order to set the Isblue and IsPaying booleans in the Car class so that I can call upon these in the next bit of code which is the simulation view that I'm currently stuck on trying to fix.
import javax.swing.*;
import java.awt.*;
public class SimulatorView extends JFrame {
private CarParkView carParkView;
private int numberOfFloors;
private int numberOfRows;
private int numberOfPlaces;
private Car[][][] cars;
public void updateView() {
/* Create a new car park image if the size has changed.
added 2 colours to show the difference between the three different customer types.*/
if (!size.equals(getSize())) {
size = getSize();
carParkImage = createImage(size.width, size.height);
}
Graphics graphics = carParkImage.getGraphics();
for(int floor = 0; floor < getNumberOfFloors(); floor++) {
for(int row = 0; row < getNumberOfRows(); row++) {
for(int place = 0; place < getNumberOfPlaces(); place++) {
Location location = new Location(floor, row, place);
Car car = getCarAt(location);
Color color = car == null ? Color.white : Car.isBlue ? Color.blue /*: isReservation == true ? Color.green*/ :Color.red ;
drawPlace(graphics, location, color);
}
}
}
repaint();
}
And here we finally get to the problem I have been facing. If you look at it right now you'll probably notice quite a few things wrong. This is because after 10 hours of research and constant changing of the Color attribute I kind of lost track of the exact way I was trying to implement the booleans that were created earlier in order to show the difference between the two types of customer. I'm not extremely experienced with programming so after awhile I just gave in and decided to ask here.
Now for the question, with all these separate classes creating their own booleans how can I make sure that when I use the simulation the cars using a Parking Pass will be blue while the cars that have to pay normally are shown as red?
public interface ParkPass {
public Random rnd = new Random();
public boolean isPass = rnd.nextBoolean();
}
Problem is in the above part. You can not define instance variables in interfaces. These members becoming static final as default.
Move this members to Car class and it will work.
Im creating a simple bowling game using OOP, and i want to have a class for each bowl, a Frame class consisting of two bowls, and a Game class consisting of ten frames.
At the moment i have something like this
Bowl.java
public class Bowl {
int bowlScore = 0;
public Bowl(int pinsKnocked){
bowlScore = pinsKnocked;
}
}
Frame.java
public class Frame{
int firstScore;
int secondScore;
public Bowl firstBowl;
public Bowl secondBowl;
public Frame (){
firstBowl = new Bowl(0);
secondBowl = new Bowl(0);
}
public Frame (int firstScore, int secondScore){
firstBowl = new Bowl(firstScore);
secondBowl = new Bowl(secondScore);
}
Game.java
public class Game {
int totalScore;
public Frame firstFrame;
public Frame secondFrame;
...
public Frame tenthFrame;
public Game(){
firstFrame = new Frame();
}
public Game(Frame f){
firstFrame = f;
}
Is this the correct way of using OOP features or how would I be able to improve this?
There is not a 100% correct way for designing a Bowling game; there are many solutions which will work, and even more that won't work.
What you need is a solution that will work well for your, and your goals.
If you want to display a score, then I suggest you start with a getScore() method. If you want to display the Winners, start with a displayWinners() method.
Eventually you will find that these methods naturally bind to various nouns. For example, you might start off with getScore() being attached to a Game object, but then realize that this unnaturally means your game can only have one score. If this occurs, you would then move the getScore() to a Player object, and have the game maintain one or more players.
If you are working with a method that naturally belongs somewhere else, there are a number of hints in your code that will guide you. The most obvious hint is that a method seems to be particularly interested in another object's data, even over it's own data. In the above example, a getScore() in a game object is overly interested in a Player's frames, balls, etc.
To gain skills and direction in how to safely move code from one place to another, I recommend reading Martin Fowler's Refactoring Book.
An excellent example, using exactly your problem is demonstrated here.
Good luck, and after a while you will be able to skip some of this process due to acquired skill; however, when learning for the first time, it is a good idea to not skip such exploratory steps (start at the beginning).
PS. Remember that your code will only be certain to do what you test it to do, if you are not familiar with test driven development, it might be a good idea to look into it (hint, this is a massive understatement).
As Edwin has mentioned they are lot of ways to model Bowling game. However here I'll list possible corrections to your code to improve it.
There are lot of things to improve here
1. score attribute is applicable only to Bowl class. so remove score attributes from Frame and Game.
2. bowlScore in Bowl should be private and provide getter method for it. You will
3. now Frame class should be like:
public class Frame{
private Bowl firstBowl;
private Bowl secondBowl;
public Frame (int firstScore, int secondScore){
firstBowl = new Bowl(firstScore);
secondBowl = new Bowl(secondScore);
}
public int getFrameScore(){
return (firstBowl.getScore()+secondBowl.getScore());
}
}
4.In Game class, you have constructor where you are passing only one frame? One game by one player consist of 10 frames. Also its not good idea to use 10 variables for frames. We hav java collections for this purpose. You can use list.
public class Game {
private java.uti.List<Frame> frames;
public Game(List<Frame> frames){
this.frames = frames;
}
public getGameScore(){
// loop goes here to sum up scores from all frames
//sum = sum+frames.get(i);
}
}
}
5.Also this modeling is valid if you are assuming that this game will be played by only one player. For multiple players, above Game class actually becomes Player class and you will have to create new Game class.
I'd be inclined to drop the multiple instances of Bowl. If you find yourself in this situation, ask yourself - how would I deal with 100 instances of Bowl? Consider the ten instances of Frame that you would have to create and maintain during the lifespan of the game. Keeping multiple instances is not a good idea unless you need multiple instances for some business logic.
public class Bowl {
private int bowlScore;
// Use a no-argument constructor
public Bowl() {
this.bowlScore = 0;
}
public void setBowlScore( int score ) {
this.bowlScore = score;
}
public int getBowlScore() {
return this.bowlScore;
}
}
For the Frame class,
public class Frame {
private int frameScore;
private Bowl bowlArray[];
public Frame() {
this.frameScore = 0;
this.bowlArray = new Bowl[2];
}
public void setScoreForFirstBowl( int score ) {
this.bowlArray[0] = score;
this.frameScore += score;
}
public void setScoreForSecondBowl( int score ) {
this.bowlArray[1] = score;
this.frameScore += score;
}
public void setFrameScore( int score ) {
this.frameScore = score;
}
public int getFrameScore() {
return this.frameScore;
}
// this should not be used, left in for completeness
public Bowl[] getBowlArray() {
return this.bowlArray;
}
}
And for Game
public class Game {
private int gameScore;
private ArrayList<Frame> gameFrames;
public Game() {
this.gameScore = 0;
this.gameFrames = new ArrayList<Frame>();
}
/* There are many ways of implementing the game logic. Here is an example.
You will have to complete the rest :) */
// #frame frame object with bowl data that is appended to list
public void frameCompleted(Frame frame) {
this.gameScore += frame.getFrameScore; // I assume this is what you want to do. Change if not
this.gameFrames.add(frame);
}
/* The method written above can also be implemented by passing integer values
for the score, bowl number and frame number. However, this would not be very
OOP friendly. Essentially, this is 'Encapsulation' of the Frame data into the
Frame object. */
// Add getters and setters for gameScore and gameFrames
}
See the ArrayList documentation for examples on further use. You can replace it with an array if you don't want to use it. I included it simply to showcase the list ability.
Read more on Encapsulation here and here.
You will notice I have not taken 'strikes' into account in the Bowl or Frame classes. This is because it is a special case that needs to catered for and so I have left it for you to implement. My understanding is if you roll a strike on the first bowl you don't get a second bowl.