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.
Related
I am just wondering if my usage of recursion is correct. The code works for the intended purpose; however, I am not sure if it is actually doing recursion. I have tried tracing through my program, but I don't understand why my output is correct. Basically, the program takes in a data file of spaces and blobs of '*' and my program is supposed to recursively calculate the number of blobs given a certain row and column in the array of spaces and blobs. The problem is that I am not sure why exactly when I used variables like north, south, east, west, it would be able to successfully return the values to me, as it seems that during recursion, each variable just exists within that call. Also, I am not sure why exactly north = count(row,col+1) would give a value for north, since everytime I iterate through the recursion of count, it doesn't seem to stop at a definite value for north, as in like it doesn't seem to stop and say to return 1 as north.
public static int count(int row, int col) {
int north = 0, south = 0, east = 0, west = 0;
if (map[row][col] == BLOB) {
map[row][col] = MARKED;
if (map[row][col+1] == BLOB) {
north = count(row,col+1);
}
//Go South
if (map[row][col-1] == BLOB) {
south = count(row, col-1);
}
//Go East
if (map[row+1][col] == BLOB) {
east = count(row+1, col);
}
//Go West
if (map[row-1][col] == BLOB) {
west = count(row-1, col);
}
return (1 + north + south + east + west);
}
return 0;
Recursion is just having a method call its self. Therefore, this is recursion.
You are correct in that each variable only exists in the scope of each call. However, they are being defined based off of the other recursive calls.
It seems that this code is trying to fill in an array (and the end case is when the part of the array is filled in). This would be why it seems like it doesn't stop calling its self (as it would take many recursive calls before end cases are met).
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.
Good Evening. I am working on a program thats similar to the old game LiteBrite, where you place colored pegs on a panel and it lights up. In my program, it works similar in that when you click on the panel, it will create a new Ellipse (which ive named ColorEllipse that has specifications for location, size, and color) and that it will store it to be saved. Currently it is as an arraylist but i need it to be in a regular array. I am told the way that would be to make a new array, and copy all the contents of the old array into the new array. Now currently i use an arraylist, but unforutnately this program has specifications where we need to use a regular Array.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.lang.reflect.Array;
import java.util.ArrayList;
public class LiteBritePanel extends javax.swing.JPanel{
private final static int OFFSET = 5;
private static int LINE_WIDTH = 2;
private static int CELL_WIDTH = 25;
public ArrayList <Colorable> _circles; // where ColorEllipses will be stored
private ButtonPanel controlpanel; // used to set the color of peg that will be placed
public LiteBritePanel() {
this.setBackground(java.awt.Color.black);
_circles = new ArrayList<Colorable>();
controlpanel = new ButtonPanel(this);
this.addMouseListener(new MyMouseListener(this));
this.add(controlpanel);
}
public void paintComponent(java.awt.Graphics aPaintBrush) {
super.paintComponent(aPaintBrush);
java.awt.Graphics2D pen = (java.awt.Graphics2D) aPaintBrush;
java.awt.Color savedColor = pen.getColor();
pen.setColor(java.awt.Color.black);
for (int ball=0;ball<_circles.size();ball++)
if(_circles.get(ball).isEmpty())
return;
else
_circles.get(ball).fill(pen);
pen.setColor(savedColor);
this.repaint();
}
public void mouseClicked(java.awt.event.MouseEvent e){
boolean foundSquare = false;
for (int ball=0; ball < _circles.size() && !foundSquare; ball++){
if (_circles.get(ball).contains(e.getPoint()) == true){
foundSquare = true;
_circles.remove(ball);
this.repaint();
}
}
}
private class MyMouseListener extends java.awt.event.MouseAdapter {
private LiteBritePanel _this;
public MyMouseListener(LiteBritePanel apanel){
_this = apanel;
}
public void mouseClicked(java.awt.event.MouseEvent e){
_circles.add(new ColorEllipse(controlpanel.getColor(), e.getPoint().x - (e.getPoint().x%CELL_WIDTH), e.getPoint().y - (e.getPoint().y%CELL_WIDTH), CELL_WIDTH-3,_this));
_this.requestFocus();
boolean foundSquare = false;
for (int ball=0; ball < _circles.size() && !foundSquare; ball++){
if (_circles.get(ball).contains(e.getPoint()) == true){
foundSquare = true;
// code for removing ball if one is placed
_this.repaint();
}
}
}
}
}`
Now currently it is set as an Arraylist, but I need it to be in a regular array per this specification. then when the panel is clicked on, it adds a new ColorEllipse into that Array at that specific location (and repaints as necessary for it to show up). A later part of the program would be when i touch a peg thats already placed, it removes it, but thats for another time. right now I need to know how to increment sizes of the array and copy its contents into it. Would anyone be able to tell me what I should change?
To copy arrays, you could use the System.arraycopy(...) method (System API):
public static void arraycopy(
Object src,
int srcPos,
Object dest,
int destPos,
int length)
where you would first create a destination array, perhaps twice as big as the the source array, and pass the old array, the starting index (0), the new array, the destination starting index (0), the length (length of old array), and it should do the rest.
Also you don't want to call repaint inside of paintComponent, trust me. Use a Swing Timer instead. There's a good tutorial on this that Google can help you find.
Depending on how big your board is you can just create an array that has the same size as your board. Alternatively you can do as Hovercraft suggested but it all depends on whether you want to trade cpu for memory.
int MAX_POSSIBLE_ELEMENTS = ...
Colorable[] _circles = new Colorable[MAX_POSSIBLE_ELEMENTS];
....rest of code...
Notice that the maximum number depends on the height and width of the board so you should know this at compiletime.
This question already has answers here:
Calling Non-Static Method In Static Method In Java [duplicate]
(14 answers)
Closed 9 years ago.
I'm newer to programming and keep getting the non-static method cannot be referenced from a static context when calling my floor class from my ant class. I've removed all statics and am still getting this error, if someone could point me in the right direction or let me know what the issue is that would be great, thanks.
public class Ant {
public final int RED = 0, BLUE = 1, NORTH = 0,
EAST = 1, SOUTH = 2, WEST = 3;
public int color;
public Ant(int size, int dir) {
size = size;
dir = startDir;
floor floor = new floor(size);
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public void makeMoves(int numMoves, int dir) {
final int[][] offSet = {/* NORTH */ {-1, 0},
/* EAST */ {0, 1},
/* SOUTH */ {1, 0},
/* WEST */ {0,-1}};
final int[][] newDir = {/* NORTH */ {WEST, EAST},
/* EAST */ {NORTH, SOUTH},
/* SOUTH */ {EAST, WEST},
/* WEST */ {SOUTH, NORTH}};
//set start row, col, and direction
row = col = size/2;
for(int move = 1; move <= numMoves; move ++) {
//make a move based on direction
row = row + offSet[dir][0];
col = col + offSet[dir][1];
//turn based on color of new tile and direction
color = floor.getTileColor(row, col);
dir = newDir[dir][color];
//change color of current tile
floor.changeTileColor(row, col);
}
}//End of makeMoves
}//End Ant class
public class floor {
int [][] grid;
public floor(int size) {
grid = new int[size][size];
}
public int getTileColor(int row, int col) {
return grid[row][col];
}
public void changeTileColor(int row, int col) {
int color = grid[row][col];
}
}
That code doesn't compile for other reasons. For example, in this constructor, startDir isn't defined. And while size is defined, that doesn't do anything. It assigns the parameter size to itself. You really want this.size = size;
public Ant(int size, int dir)
{
size = size;
dir = startDir;
Also, row and col aren't defined anywhere. If you are getting errors about statics, I wonder if you are compiling old code.
public static void main() is a static context. There's only one of it, whereas there is technically one of makeMoves(), say, for each Ant object. Call them on an instance of Ant, or make them static also. That's the gist, simply look up keyword static, and/or context, scope to learn more.
As others have pointed out, the code you're compiling doesn't seem to match the code you posted, because the posted code contains other errors than just static accesses.
However, I think your basic problem (as it regards the question as posed, at least) is that you think you have defined an instance variable in the Ant class for the floor, while in fact you have not. You have just defined a local variable for it in the Ant constructor, which is discarded as soon as the constructor returns.
Then, since you have a naming conflict between the floor class itself and what you probably think is the variable that would hold the Ant's floor, you're trying to call floor.changeTileColor, thinking that it would be invoked on the Ant's instance of floor, but it compiles as if it were a reference to a static method. This is because floor, here, refers to the class floor itself rather than to a variable holding an instance to it.
To solve it, create a floor instance variable in the Ant class instead of just in the constructor (though, suggestedly, under another name, in order to avoid more naming conflicts).
So I'm just messing around learning to create a Space invaders type game. I can get the bad guys to move, Great!!. Hero moves, Great!! Bullets move, Great!! However I try to remove my bullets once they leave the screen as to not eat up all resources and it force closes on me once it gets rid of the bullet. It goes off the screen. Hits the int of -2 and then we use the remove() and boom. Force Close.
Here is my code. I'm wondering if they access the size() at the same time and just cause a force close because of it.
//I removed everything that doesn't pertane to the bullets.
public class GameScreen{
Bullet bullet = world.bullet;
public GameScreen(Game game) {
super(game);
world = new World();
}
//Draws our bullets.
int bulletLength = bullet.bullets.size();
for(int i = 0; i < bulletLength; i++) {
Placement part = bullet.bullets.get(i);
x = part.x * 32 + 11;
y = part.y * 32;
g.drawPixmap(Assets.bullet, x, y);
}
Class that holds my bullets.
public class Bullet {
public List<Placement> bullets = new ArrayList<Placement>();
public Bullet() {
}
public void shoot(int x, int y){
bullets.add(new Placement(x,y));
}
public void advance(){
int len = bullets.size(); // gets all bullets.
for(int i = 0; i < len; i++) {
bullets.get(i).y --;
if (bullets.get(i).y <= -2){//removes them once they are off the screen.
bullets.remove(i);
}
}
}
This is what I use to keep track of placement.
package com.learning.planecomander;
public class Placement {
public int x, y;
public Placement(int x, int y) {
this.x = x;
this.y = y;
}
}
When going through your list to remove bullets, you can remove bullets from a list but that affects the list immediately instead of after your loop is done. Since you are traversing to the length of the list at the start, you are going off the end of the list since you've removed elements. An example is probably more helpful than that description.
Let's say you have a list with three bullets (which I'll call a, b, c to make the example easier). On a pass through the list, a and c are fine but b needs to be removed.
i = 0;
bullets[0] = a;
bullets[1] = b;
bullets[2] = c;
First loop goes fine, second loop starts like this
i = 1;
bullets[0] = a;
bullets[1] = b;
bullets[2] = c;
We remove b, but the loop keeps going
i = 2;
bullets[0] = a;
bullets[1] = c;
OH CRAP ARRAYINDEXOUTOFBOUNDS! PROGRAM CRASHES!
The way to solve this is to use a temp list to store the bullets that need to be removed, and then once your update loop is finished, make a call to bullets.removeAll(temp)
Doing two passes is a good answer. It makes the loops simpler and easy to understand. If you'd like to do it in one pass though, iterate through the list in reverse order, and when you remove a bullet you can go to the next one and not worry about blasting past the end of the ArrayList.
Alternatively, you can keep your bullets in a linked list, and run through the list with an Iterator, which you can also use to remove items from the list with. Removing from the beginning middle or end of an linked list is always a constant time operation. Whereas removing from the beginning of an ArrayList can be more expensive. If you need random access to the elements in the list, then they can be inefficient. Keep in mind though, if you're only dealing with a handful of objects, then it doesn't really matter.
For bonus points, you might want to put all of your objects in a list, and then have your central loop process them all and have your game objects respond polymorphically to calls like dead?, think, move, draw or whatever you think is appropriate.