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.
Related
Hi I having been trying to program an algorithm using breadth-first-search that finds the shortest path for the blue dot to exit in the game. I am new to java and having trouble running/understanding the algorithm for the class. I have a class called gameModel which stores the statuses of each dot. The algoirthm is meant to test the fastest way the blue dot can exit the board without going through an orange dot (SELECTED) and if no way out than the player wins. I keep running the program and getting compile errors which i dont know how to fix. I included the controller class where the short dot was ran.
import java.util.Random;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.*;
/**
* The class <b>GameController</b> is the controller of the game. It implements
* the interface ActionListener to be called back when the player makes a move. It computes
* the next step of the game, and then updates model and view.
*/
public class GameController implements ActionListener {
private int size;
private GameModel gameModel;
private GameView gameView;
private boolean click;
/**
* Constructor used for initializing the controller. It creates the game's view
* and the game's model instances
*
* #param size
* the size of the board on which the game will be played
*/
public GameController(int size) {
this.size = size;
this.gameModel = new GameModel(size);
this.gameView = new GameView (gameModel, this);
click = false;
}
/**
* Starts the game
*/
public void start(){
if (click){
List start = new List {gameModel.getCurrentDot().getX(), gameModel.getCurrentDot().getY()};
List<int> targets = new ArrayList<>();
List<int> blocked = nwq ArrayList<>();
for (int i = 0; i < size; i++){
targets.add(i, 0);
targets.add(i, size);
targets.add(1, size);
targets.add(1, 0);
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++)
if(gameModel.getstatus(i, j) == SELECTED){
blocked.add(i, j);
}
String path = Breadth-First-Start(start, targets, blocked);
gameView = new GameView(gameModel, this);
gameView.getBoardView().update();
}
}
public Breadth-First-Start(start, targets, blocked){ // Need help with
Queue queue = new LinkedList();
queue.add(start + "");
while(!queue.isEmpty()){
String p = queue.remove();
if (p != blocked){ //If p is not in blocked paths
if (p == targets){ //If p is in targets
return "q + {p}";
} else {
queue.add("q + {p}");
blocked.add(p);
}
}
}
You method public Breadth-First-Start(start, targets, blocked) is declared wrong. You cant have - in method name, also you need to specify the return type (only constructors dont have a return type to be defined). Also you need to specify parameter types. From what I understand targets and start look like of type String and blocked looks like a List, please try replace the method head by the following public void breadthFirstSearch(String start, String targets, List blocked) not sure what return type you want as you dont have any returns in the method. But in your case you probably want the path so maybe of type List, or a boolean to know if there is a path or not.
What you're wanting to do has to do with graph theory. If two nodes are connected, an edge between them is created. In this case the orange dots would not be connected to anything as a path cannot exist through them. Dijkstra's algorithm is very useful for doing what you want, although it's breadth first instead of depth first. I'd recommend starting there, I'm sure there are examples of that algorithm being implemented in java.
The edges of the graph have weights which are compared in order to find the shortest path between two nodes.
I see that your blocked list declaration has nwq in it instead of new. That may be your issue right there.
Hope this helps
What I need to do is storing different objects of an "Obstacle" super class in an array, and then perform the same actions as if I had one. So I need to be able to draw all the objects and also make them collide with the ball class.
So I tried to put all the instances of an object in an array in a for loop, and then I tried to paint them. But I can't figure out how to use the functions on the objects if they are stored in an array.
I tried to do this:
for(int i = 0;i<objects.length;i++){
objects[0].paint(g);
}
but the "paint(g)" part is just highlighted in red and it doesn't work.
If someone could help me I would be really happy! I haven't stored objects in arrays before, so I'm kind of clueless as what to do.
I also tried making the for loop like this:
if(i>=1 && i<15){
Obstacle star = new StarObstacle(rand.nextInt(400),rand.nextInt(400));
objects[i]= star;
star.paint(g);
}
Here they actually show up, but the stars are just flying all over the screen, so something must be changing x and y values all the time.
edit: sorry accidentally added the whole code instead of only the part I need help on.
It's the for loop in the Main(int x,int y){} scope
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class Main extends JPanel implements KeyListener {
Ball b;
TriangleObstacle o;
BorderObstacle border;
StarObstacle s;
Player player;
int bounceCount=0;
Object[] objects;
Random rand = new Random();
Main(int width, int height) {
//create a new black ball at the center of the screen
b = new Ball(width*0.5f, height*0.5f, 3, 0,0,0);
//make a border around the window
border = new BorderObstacle(width, height);
objects = new Object[30];
//setup a triangle obstacle
o = new TriangleObstacle(width*0.3f, height*0.7f, 200, 50);
s = new StarObstacle(400,300);
player = new Player();
this.addKeyListener(this);
this.setFocusable(true); //needed to make
for(int i = 0; i < objects.length;i++){
if(i==0){
objects[0]= new Player();
}
if(i>=1 && i<15){
objects[i]= new StarObstacle(rand.nextInt(400),rand.nextInt(400));
}
if(i>15){
objects[i]= new TriangleObstacle(30,30,rand.nextInt(400),rand.nextInt(400));
}
}
}
public void update() {
//move over all obstacles and check whether they should bounce the ball
border.bounceBall(b);
o.bounceBall(b);
s.bounceBall(b);
if(player.bounceBall(b)){
bounceCount++;
}
//move ball based on speed and location
b.move();
player.move(); //updates my player object.
this.repaint(); //runs the paint method on the object
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setFont(new Font("TimesRoman", Font.PLAIN, 20));
g.drawString("Amount of bounces on Player: " + bounceCount, 300, 100);
b.paint(g);
o.paint(g);
s.paint(g);
player.paint(g);
border.paint(g);
}
public static void main(String[] args) {
int width = 800;
int height = 600;
JFrame frame = new JFrame("Pinball"); //create a new window and set title on window
frame.setSize(width, height); //set size of window
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //set the window to close when the cross in the corner is pressed
Main m = new Main(width,height-22); //-22 to account for menubar height //create a new object and runs constructor for initial setup of the program
frame.add(m); //add the content of the object to the window
frame.setVisible(true); //make the window visible
while (true) { //keep running a loop
//each time the loop is run do
m.update(); //run the update method on the object
try {
Thread.sleep(10); //stops this part of the program for 10 milliseconds to avoid the loop locking everything. Now the screen has time to update content etc.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode(); //gets input as keycode.
if(code==KeyEvent.VK_RIGHT){
player.setRight(true); //sets the movement for right to true, making it move by 5 pixels in the positive direction, for each update.
player.setLeft(false);
}
if(code==KeyEvent.VK_LEFT){
player.setLeft(true);
player.setRight(false);
}
}
#Override
public void keyReleased(KeyEvent e) { //keyReleased setting them to false to prevent the object to keep moving.
int code = e.getKeyCode();
if(code==KeyEvent.VK_RIGHT){
player.setRight(false);
}
if(code==KeyEvent.VK_LEFT){
player.setLeft(false);
}
}
}
You need to write your own method paint(Graphic g) in your classes "Player", "StarObstacle", "TriangleObstacle".
something like this:
class TriangleObstacle extend Obstacle {
public paint(Graphics g) {
g.drawPolygon (...);
}
}
Also, avoid to use an array of Objects (Objects[]). Better use your superclass Obstacles for the array (Obstacle[] myObstacle = new Obstacle[30];
And don't put the Player object inside the array of Obstacle it wouldn't make sense.
At final you could have:
Obstacle[] myObstacles = new Obstacle[30];
Player player = new Player();
....
for (Obstacle obstacle : myObstacles) {
obstacle.paint(g);
}
player.paint(g);
This:
for(int i = 0;i<objects.length;i++){
objects[0].paint(g);
}
Doesn't achieve what you want because you are always accessing index 0.
Try this:
for(int i = 0;i<objects.length;i++){
objects[i].paint(g);
}
This allows you to access and paint each object present on the index represented by i. I can't guarantee that this will solve the problem, but it is a problem.
You need to cast the object and use the correct index so :
objects[0].paint(g);
should be
((Observer)objects[i]).paint(g);
However this is completely the wrong approach. Please read up on java generics. http://docs.oracle.com/javase/tutorial/java/generics/
You should be using a List or some other collection with an upper bound wildcard eg
List<? extends Observer>
Which will provide type safety.
You must create an array of Obstacles instead of objects, the in your Obstacles interface add a method definition called paint(). Then you have to override the paint() method in every implementation of Obstacles. And when you call paint method in objects of the array it will call the corresponding method.
Instead of an array, can you put the objects in a list? Something like...
List<Obstacle> someList = [however you populate your array, just populate the list instead];
for(int i = 0; i<somelist.length; i++) {
someList.get(i).paint(g);
}
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.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
For this program I want to implement an array of sorting and searching algorithms. The array will be filled with random numbers. Then I want to draw each array element as a bar (making something like a bar graph). I have a step and run button in the GUI the step is supposed to use selection sort. The problem I am having is: I only know how to do selection sort with a loop. However, I can not use a loop because I have to show the array being sorted step by step. Can anyone show me how to do selection sort without a loop? I will be adding all of the code I have so far because this is my first time posting anything, and I want to make sure I am specific.
ArrayViewer:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.util.Scanner;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ArrayViewer
{
static int[] array;
static int size;
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
//ask for the size of the array until the user enters a size in the right range
do
{
System.out.print("Enter the size of the array (should be between 10 and 80): ");
size=in.nextInt();
}
while (size<10 || size>80);
array= ArrayUtil.randomIntArray(size,100);//create a random array of given size and entries ranging from 0 to 100
final ArrayComponent arrayComp= new ArrayComponent(array); //construct an arrayComponent with the random array
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//I want the selection sort algorithm to go in here so I can just assign this to my stepButton.
}
}
final JFrame frame=new JFrame("Sorting"); //create and setup the frame
frame.setSize(1200,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel buttonPanel= new JPanel(); // panel to hold the buttons
JPanel panel=new JPanel(new BorderLayout()); // panel to hold the button panel and the array component; uses BorderLayout: read about it in the API
JButton stepButton=new JButton("Step"); //button to go through the algorithm step by step
JButton runButton=new JButton("Run"); //button to run the algorithm
ActionListener listener = new ButtonListener();
stepButton.addActionListener(listener);
buttonPanel.add(stepButton);
buttonPanel.add(runButton);
panel.add(buttonPanel,BorderLayout.PAGE_START); //add the buttonPanel at the top of the panel
panel.add(arrayComp,BorderLayout.CENTER); //add the arraycoponent object in the center of teh panel
frame.add(panel);
frame.setVisible(true);
//print the entries in the array
//System.out.println(arrayComp);
}
}
ArrayComponent:
import javax.swing.JComponent;
import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.Color;
public class ArrayComponent extends JComponent
{
private int[] theArray;
final int dx=6; //the width of thebars (as well as the with of the spaces between bars)
private int space=0;
int index1 =0;
int index2 =0;
public ArrayComponent(int[] a)
{
theArray=a;
space=600-12*theArray.length/2; //space amount on the horizontal axes to center the graph
//600 is the frame width in the viewer program
//For each bar 12 units on the horixzontal axis is used including the space following it.
//something.addActionListener(new ButtonListener());
}
public void setIndices(int i, int j)
{
index1 = i;
index2= j;
}
public void paintComponent(Graphics g)
{
Graphics2D pen= (Graphics2D) g;
for (int k=0;k<theArray.length;k++)
{
pen.drawRect(space+2*k*dx,5,dx,theArray[k]);
//space: initial space
//2*k*dx: the (horizontal) distance of te kth bar from the start of the graph
//5: bars are located on y=5
//dx: the width of the bars
//theArray[k]: height of the kth bar
}
pen.fillRect(space+2*index1*dx,5,dx,theArray[index1]);
pen.fillRect(space+2*index2*dx,5,dx,theArray[index2]);
}
public String toString()
{
String str=("array=[");
int k=0;
for (k=0;k<theArray.length-1;k++)
str=str+theArray[k]+", ";
str=str+theArray[k]+"]";
return str;
}
}
ArrayUtil(creates the random array):
import java.util.Random;
/**
This class contains utility methods for array manipulation.
*/
public class ArrayUtil
{
private static Random generator = new Random();
/**
Creates an array filled with random values.
#param length the length of the array
#param n the number of possible random values
#return an array filled with length numbers between
0 and n - 1
*/
public static int[] randomIntArray(int length, int n)
{
int[] a = new int[length];
for (int i = 0; i < a.length; i++)
a[i] = generator.nextInt(n);
return a;
}
}
Sorry if the post is lengthy. The program already draws the arrays, it just does not sort them. Thanks for the help.
Let activeIndex refer to the index of the array element to be sorted next (starting with value 0).
Write a method, say stepSelectionSort, which will execute only the one step of selection sort and return. The sorting begins at array[activeIndex].
{5,4,3,2,1} -> activeIndex=0 -> Step.click -> stepSelectionSort() sorts array element at 0 -> {1,4,3,2,5} -> draw() -> activeIndix=1 -> Step.click -> stepSelectionSort() sorts array element 1.
Temporarily write code to do full sort inside a loop
Take all code within the loop and put it in a method
Remove the loop & call the method once each time the user clicks "Step" GUI button
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.