Related
I am wondering if there is a bit of code or that can apply a method from a class to all of the objects in the ArrayList? I'm making a basic space invaders program and I am trying to implement a move method that will apply to all of enemies, so that they move in a group rather than individually.
I've created the items in the array list here:
for (int i = 0; i < 6; i++) {
venWidth = venWidth - 139;
enemyList.add(new Venusian("/venusian.jpg", venWidth, height));
}
for (int i = 6; i < 12; i++) {
merWidth = merWidth - 145;
enemyList.add(new Mercurian("/mercurian.jpg", merWidth, merHeight));
}
for (int i = 12; i < 18; i++) {
marWidth = marWidth - 125;
enemyList.add(new Martian("/martian.jpg", marWidth, marHeight));
}
Here is where I call the move method:
for (int i = 0; i < enemyList.size(); i++) {
Invader Invaders = (Invader) enemyList.get(i);
Invaders.draw(g);
Invaders.Move(1024);
This makes them move independently and overlap, at the moment I am just moving them right and left using the boundaries of my created window. So is there any way of moving them together at the same time? I have searched for a way to apply a class method to all of the lists items but I haven't found anything after a couple of hours.
Any material, sources or advice relating to this would be greatly appreciated.
You will have to come up with a solution that can decouple the Invaders you are moving from those you are displaying.
This is due to the fact that your individual Invaders will always be more or less sequentially moved - even if you are working with multiple threads, etc. Even if you would start using Java8 Lambdas to write your code like this:
ArrayList<Invader> badGuys;
//fill your List here
badGuys.forEach( badGuy -> badGuy.move());
This would also create intermediate states where some Invaders were moved, some were not.
So you have to make sure that you only draw a consistent set of Invaders to your screen. You could do this several ways:
Only draw to screen after all Invaders were moved
Make a copy of your invaders for drawing, while the Invaders are being moved. After all Invaders were moved, start displaying the Invaders from the moved List
...
1st Edit: How do you draw the Invaders to screen? Is this happening in separate threads?
3rd EDIT: Okay so maybe you can stop your timerThread before starting to move your Invaders. And when you are finished with moving them you can restart the timer again. Check what methods your timer offers It should have start() and stop() or maybe suspend() methods.
Do something like this:
timer.stop();
badGuys.moveAll();
timer.start();
2nd EDIT: Just looked over your code again. There is no need for you to start your for loop number 2 and 3 from indexes other than 0. Your code will be easier to read if for example you just say:
for (int i = 0; i < 6; i++) { // start from 0 (to 6) instead of 6 to 12
merWidth = merWidth - 145;
enemyList.add(new Mercurian("/mercurian.jpg", merWidth, merHeight));
}
create an interface like Moveable. and put Move method on it. then implement it on Venusian, Martian and Mercurian. and use this interface on arraylist
interface Moveable {
public void Move(int dist);
}
class Mercurian implements Moveable {
public void Move(int dist)
{
//do something
}
}
class Venusian implements Moveable {
public void Move(int dist)
{
//do something
}
}
class Martian implements Moveable {
public void Move(int dist)
{
//do something
}
}
ArrayList<Moveable> enemyList = new ArrayList<Moveable>();
OK, I'm in the process of making a simple java swing chess game. This question is more about OOP design then Java Swing.
I have the following:
I have a Panel class that implements JPanel.
I then have an abstract class Piece that extends from my Panel class
Then I have my classes for the different Pieces: Pawn, King, Bishop etc that extend from my Pieces class
In my main ChessGame Class:
I am using an array of Panel to store the layout of my board
So the array will store, Panel objects, for board places with no pieces on it.
And it will store, the subclasses such as Pawn, Queen, Bishop etc (board places with pieces)
So, the top left square (0,0) maps to myArray[0][0]
My problem is that, to check if the place is empty or has chess pieces in it I have to use:
if(panels[x][y] instanceof Piece){
((Piece)panels[x][y]).makeMove();
}
What I'm asking is this terrible design? I know I should try and stay away from instanceof.
What would be a better approach?
Thanks.
You shouldn't combine the Model code (Piece) with the view code (JPanels). If you ever want to change how the board is displayed you have to change how pieces are stored!
A better design might be to separate Piece from JPanels. Then you can use a single JPanel to display a matrix of Pieces : Pieces[8][8].
My problem is that, to check if the place is empty or has chess pieces in it I have to use:
If you use a matrix, you can just have a null cell or use the Null Object Pattern to have an "empty" piece.
EDIT
Each cell in the piece matrix is a square in the board so piece[0][0] would be the top corner of the board (A8).
To paint the board your paintComponent() method would have to iterate over this matrix and draw each cell appropriately. There are several ways to implement this:
You would need to do a similar instanceof check to draw each type of piece differently
Make a new intermediate "paint strategy" object using the strategy pattern. This may require a matrix of strategy objects instead of piece objects. You may still need to do instance of checks, but maybe only the once to create the strategy objects.
After considering your problem, and knowing the problem domain, I would actually suggest the following...
In your class Panel implement a function int hasMass() as follows...
public int hasMass() {
return 0;
}
In your class Piece override that function as follows...
public int hasMass() {
if (isWhite()) // white pieces are negative.
return -1;
return 1; // black pieces positive.
}
Now you can check if the square has a piece, whether another given piece could take it... (because they have opposite polarity)... e.g. mass + mass == 0 means a capture, != 0 means the panel was empty. And of course an absolute value of 2 (for mass) would mean the move was illegal.
OK, ill start by throwing away the option of setting null to indicate that place is empty (you can do it ofc but using the Empty class is just 'better' in a way).
So let's say you have array of Panels representing your game board:
Panel[][] board;
Now for ilustration, how your class hierarchy could look like:
abstract class Panel extends JPanel { ... }
class Empty extends Panel { ... }
abstract class Piece extends Panel { ... }
class Pawn extends Piece { ... }
...
My Panel class is my Empty class is it not?
Not sure if i understand you, but let's have a look on what extends means exactly: in the show nmodel every Piece is also a Panel or every Pawn is also a Piece, so every Pawn can do all the same things as Piece (for example, 4 is complex number as well as natural number or real number, so in a way, you could say that real numbers extend complex numbers, since every real number is also a complex number)
So now you can have some nice abstract getTexture() method declared in Panel implemenented in Empty class and in all Piece subclasses, and when drawing a Panel, you dont need to look if it is empty or not.
Instead of creating (I assume) almost identical classes for each piece (Rook, Pawn, Queen etc.), you could just keep the original Piece class, make it non abstract and add a PieceType field to it. PieceType is just an enum that tells what type of piece (if any) is placed there. Instead of using instanceof, now you can check using panels[i][j].getType() == PieceType.ROOK. At least that's what I'm doing in my implementation :)
I'm also using JLabel instead of JPanel for my 8x8 board.
Instead of splitting panel to 8x8 smaller panels, you must draw the board and the pieces on a canvas. Later the players will eventually be dragging to move pieces on board. Also you could look for Bitboard presentation in chess game, although this presentation is only required for chess engines which are able to "think" for fast calculations, it is still useful when you have to check if the move that player is trying to make is correct.
Posible Bitboard:
public class BitBoard
{
public static final int P = 0;
public static final int N = 2;
public static final int B = 4;
public static final int R = 6;
public static final int Q = 8;
public static final int K = 10;
public static final int p = 1;
public static final int n = 3;
public static final int b = 5;
public static final int r = 7;
public static final int q = 9;
public static final int k = 11;
// empty field
public static final int empty = 12;
// number of pieces , squares
public static final int nPieces = 12;
public static final int nSquares = 64;
public static final int whitePieces = 12;
public static final int blackPieces = 13;
public static final int nBoards = 14;
public static long squareBits[];
// static member initialization
static
{
squareBits = new long[64];
long square = 1;
square = square << 8 * 8 - 1;
for (int i = 0; i < 64; i++) {
squareBits[i] = square >>> i;
}
}
long bitBoards[];
public BitBoard() {
bitBoards = new long[nBoards];
}
public boolean initBoard()
{
// Put the pieces on the board
EmptyBoard();
addPiece(0, r);
addPiece(1, n);
addPiece(2, b);
addPiece(3, q);
addPiece(4, k);
addPiece(5, b);
addPiece(6, n);
addPiece(7, r);
for (int i = 8; i < 16; i++) {
addPiece(i, p);
}
for (int i = 48; i < 56; i++) {
addPiece(i, P);
}
addPiece(56, R);
addPiece(57, N);
addPiece(58, B);
addPiece(59, Q);
addPiece(60, K);
addPiece(61, B);
addPiece(62, N);
addPiece(63, R);
return true;
}
public boolean addPiece(int whichSquare, int whichPiece)
{
bitBoards[whichPiece] |= squareBits[whichSquare];
bitBoards[nPieces + (whichPiece % 2)] |= squareBits[whichSquare];
return true;
}
private boolean removePiece(int whichSquare, int whichPiece)
{
bitBoards[whichPiece] ^= squareBits[whichSquare];
bitBoards[nPieces + (whichPiece % 2)] ^= squareBits[whichSquare];
return true;
}
private boolean EmptyBoard()
{
for (int i = 0; i < nBoards; i++)
{
bitBoards[i] = 0;
}
return true;
}
}
I would keep a structure of the pieces separate from the rendered board.
For example, I would make the chess pieces pure models w/o knowledge of hit they're rendered.
Pieces (baseclass)
+- Pawn
+- Knight
+- King
+- Queen
+- ..etc
This will allow you to keep an array of Pieces only, where empty squares are null.
For simplicity sake, I'd just have a matrix of peices:
Peices[][] board = new Pieces[8][8];
(of course an initialization method to traverse your 'board' and populate the board w/ the initial positions)
I would then have a visible board constructed of JPanels; a class called "Chess" to manage game; and the actual rendering of the tile/panel in the move function. Imagine:
// what a move might look like when initializing your panels
piece = board [0][0];
Chess.move(piece, 0 ,0); //responsible for clearing the old panel and rendering the panel at target location.
When the user interacts w/ your game..they click your panels..which will give you the panel coordinates. You use the same coordinates w/ your 'board' to determine what the piece is..how it can move etc..
Something like that...
I would just represent the game board using objects...for simplicity. Easiest to understand..and besides..computers are plenty fast now.
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.
I am writing a simple chess-playing game. I won't post it all here, but I'll give you the necessary details.
I move by clicking a square with a piece on it, then the square becomes selected, and then clicking where I want to piece to move. Sometimes in chess, a move may fail to respond to check or create a check on one's own king and is therefore illegal. The best way, I've found, to decide whether a move is illegal is to make a move on an "ifBoard" (a clone of the board) and if I deem the move legal, set the real board equal to the ifBoard.
Here is a code snippet of me responding to mouse clicks (board is the real board, destination is the clicked square, selectedSquare is the square previously selected(if not null))
public void mousePressed(MouseEvent e){
Square selectedSquare = board.selectedSquare();
Square destination = board.getSquare(e.getX(), e.getY());
board.deselect();
if(destination == null){
repaint();
return;
}
if(selectedSquare == null){
System.out.println("SelectedSquare is null");
if(destination.occupiedByTeam(turn)){
System.out.println("destination is occupied by right team and is null");
board.select(destination);
}
}
else{
if(!selectedSquare.occupiedByTeam(turn)){
System.out.println("SelectedSquare not occupied by correct team");
repaint();
return;
}
if(destination.occupiedByTeam(turn)){
System.out.println("ChosenSquare occupied by same team");
board.select(destination);
repaint();
return;
}
//move on a dummy board and check for conflicts
Board ifBoard = (Board)board.clone();
System.out.println(ifBoard.toString());
System.out.println(board.toString());
//check if you can't move due to piece movement limitations
//.place() is a coordinate of the square on the tile system (A-H and 1-8)
if(
!ifBoard.move((int)selectedSquare.place().getX(), (int)selectedSquare.place().getY(), (int)destination.place().getX(), (int)destination.place().getY())
){
repaint();
return;
}
//if moving results in self-check
if(ifBoard.check(turn)){
//don't move
repaint();
return;
}
else{
//move
System.out.println("Board moved!");
board = new Board(ifBoard);
cycleTurns();
}
}
repaint();
}
The toString calls are registering differently, but I have narrowed the problem down to the ifBoard.move() call actually moving the real board.
Here is the board class, or part of it.
import java.awt.Color;
import java.lang.Cloneable;
import java.awt.geom.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class Board implements Cloneable{
private Square[][] squares;
private Rectangle2D squareWrap;
private Rectangle2D boardBorder;
private Square selectedSquare;
public Board(){
squares = new Square[8][8];
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
squares[i][j] = new Square(new Point2D.Double(i, j));
}
}
boardBorder = new Rectangle2D.Double(Constants.boardX,
Constants.boardY,
Constants.borderWidth * 2 + Constants.boardSide,
Constants.borderHeight * 2 + Constants.boardSide);
squareWrap = new Rectangle2D.Double(Constants.boardX + Constants.borderWidth,
Constants.boardY + Constants.borderHeight,
Constants.boardSide,
Constants.boardSide);
selectedSquare = null;
}
public Object clone() {
Board obj = new Board();
obj.setSquares(this.squares);
obj.setSelectedSquare(this.selectedSquare);
return obj;
}...
Am I cloning incorrectly? Is there a better way? Thank you in advance.
Am I cloning incorrectly? Is there a better way?
The clone method should always start by calling super.clone() for reasons that I won't go into in this post.
Also, you're not cloning the attributes of the object (you're doing a shallow copy instead of a deep copy). Thus a cloned Board would share the same reference to the squares structure. (Changing the cloned Board would change the original Board.)
(Many people argue that you should avoid clone and Cloneable all together though.)
If I were you, I would strongly consider making the Board class immutable and perhaps go with some copy-on-write mechanism. That would save you a lot of headache I believe.
Your Problem might be that your clone() implementation does not create a deep copy. The cloned object shares a least some state with the instance it is cloned from. By that, I mean they are referencing the same objects:
public Object clone() {
Board obj = new Board();
obj.setSquares(this.squares); // Square instances are the same for both boards
return obj;
}
If you change state on the clone - e.g. on a square - you also change it on the real board.
From what you've posted, you are calling ifBoard.move(). If that method affects part of the "shared state" then it will affect both board instances.
I am trying to replicate the applet found here as a part of an exercise. The applet is using Fortune's algorithm to generate both; a Voronoi diagram and Delaunay triangulation. I am just interested in generating the Delaunay Triangulation in a plane and thus, would be using the incremental algorithms i.e. adding 1 point at a time. I intend to show the triangles being generated at every stage when a sample point is added.
I am using a SwingWorker class to create an instance of the Triangulate class which contains the algorithm. I am calling the triangulate method inside a for loop which iterates through the set of sample points when the start button on the GUI is clicked.
Here's the code for that:
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
SwingWorker<List<Triangle>, Triangle> worker = new SwingWorker<List<Triangle>, Triangle>() {
#Override
protected List<Triangle> doInBackground() throws Exception {
Triangulate dt = new Triangulate(drawingPanel.pointsList());
dt.preTriangulate(); //Set-up a bounding triangle and obtain a random permutation of the points
List<PlanarPoint> pointsList = dt.pointsList();
for (int i = 0; i < pointsList.size(); i++) {
PlanarPoint sample = pointsList.get(i);
dt.triangulate(sample);
List<Triangle> list = dt.trianglesList(); //Obtaining the list of triangles at every stage. Good Idea??
for (int j = 0; j < list.size(); j++) {
publish(list.get(j));
}
Thread.sleep(500);
}
dt.removeTriangles(dt.trianglesList()); // Remove all the triangles containing bounding-triangle vertices
return dt.trianglesList();
}
protected void process(List<Triangle> triangles) {
for (Triangle triangle : triangles) {
g = drawingPanel.getGraphics();
PlanarPoint p1 = triangle.getVertex1();
PlanarPoint p2 = triangle.getVertex2();
PlanarPoint p3 = triangle.getVertex3();
g.drawLine((int) Math.ceil(p1.x), (int) Math.ceil(p1.y),
(int) Math.ceil(p2.x), (int) Math.ceil(p2.y));
g.drawLine((int) Math.ceil(p2.x),(int) Math.ceil(p2.y),
(int) Math.ceil(p3.x),(int) Math.ceil(p3.y));
g.drawLine((int) Math.ceil(p3.x),(int) Math.ceil(p3.y),
(int) Math.ceil(p1.x),(int) Math.ceil(p1.y));
}
}
};
worker.execute();
}
});
Here is the Triangulate class which computes a Delanuay Triangulation of a set of points:
public class Triangulate {
private List<PlanarPoint> pointsList;
private List<Triangle> triangleList;
private Triangle boundingTriangle;
private List<Edge> edgeList;
public Triangulate(List<PlanarPoint> pointsList) {
this.pointsList = pointsList;
this.triangleList = new ArrayList<Triangle>();
this.edgeList = new ArrayList<Edge>();
}
public List<Triangle> trianglesList() {
return triangleList;
}
public List<PlanarPoint> pointsList() {
return pointsList;
}
public void preTriangulate() {
boundingTriangle = getBoundingTriangle(pointsList);
triangleList.add(boundingTriangle);
randomPermutation(pointsList);
}
public void triangulate(PlanarPoint samplePoint) {
// A procedure implementing the Bowyer - Watson algorithm
// to calculate the DT of a set of points in a plane.
}
public void removeTriangles(List<Triangle> trianglesList) {
// A procedure to remove all triangles from the list sharing
// edges with the bounding-triangle
}
private Triangle getBoundingTriangle(List<PlanarPoint> pointsList) {
//Obtains a bounding-triangle for a set of points
}
public void randomPermutation(List<PlanarPoint> pointsList) {
//Obtains a random permutation of a set of points
}
}
I have 3 other classes
PlanarPoint - sub-class of Point2D.Double which implements Comparable to provide a y-co-ordinate based sorting
Triangle - A class which determines a circum-circle and circum-radius for the triangle and determines whether a point lies inside the circumcircle of the triangle
Edge - A class which represents Edge as the one having 2 PlanarPoints as its end-points.
DrawingPanel - A class which acts as the surface on which points are added at click events and drawn on the screen.
Now, here are a few concerns which I have
Is there a better way to show the triangles and possibly circum-circles by iterating over a set of points and then calling a function of the Triangulate class to get the existing circum-circles and triangles
Should all the drawing be restricted to the DrawingPanel class since in the code snippets above I am painting in the class which extends JApplet/JFrame and thus whenever the window is resized, the drawn triangles are lost? Is there a design pattern which I can follow?
Is the usage of SwingWorker over spawning another thread justified over here except for the fact that the time to compute the DT of a set of points is a time-consuming task?
If I have missed any details, please let me know
Thanks,
Chaitanya
Suggestions:
Don't use getGraphics() to get a Graphics object since the Graphics object obtained won't persist if any repaint is performed (something out of your control). Instead draw to a BufferedImage and have the JPanel or JComponent draw the BufferedImage in its paintComponent override, or add your image data to a Collection of some sort, and have the paintComponent override method iterate through the Collection using the information to draw your images.
Don't draw directly in a top level window such as a JFrame or JApplet, but instead in a component that derives from JComponent, often either JComponent itself or JPanel.
Read the Swing graphics tutorials as they will explain all of this and more.
SwingWorker is fully justified since you want to create a thread that is background to a Swing application yet interacts with the Swing application -- the very situation that SwingWorkers were created for.