Avoid Overlapping components in Null Layout - java

I have a null layout in a class extending JComponent so that I can add components at my desired coordinate. But also I don't want some components to be overlapped. Any idea, how can I achieve this thing? By using any other Layout? Actually I want some of the functionality of FlowLayout. Is there any way?

You probably need to implement your own layout manager, e.g. like this one:
public class NonOverlappingLayout implements LayoutManager
{
#Override
public void addLayoutComponent (String name, Component comp)
{
// Do nothing
}
#Override
public void removeLayoutComponent (Component comp)
{
// Do nothing
}
#Override
public Dimension preferredLayoutSize (Container parent)
{
int count = parent.getComponentCount ();
Rectangle [] r = new Rectangle [count];
for (int i = 0; i < count; i++)
{
Component c = parent.getComponent (i);
if (c.isVisible ())
r [i] = c.getBounds ();
else r [i] = new Rectangle (0, 0, 0, 0);
}
r = doLayout (r);
Rectangle result = new Rectangle (0, 0, 0, 0);
for (int i = 0; i < count; i++)
{
result = result.union (r [i]);
}
return result.getSize ();
}
#Override
public Dimension minimumLayoutSize (Container parent)
{
return preferredLayoutSize (parent);
}
#Override
public void layoutContainer (Container parent)
{
int count = parent.getComponentCount ();
Rectangle [] r = new Rectangle [count];
for (int i = 0; i < count; i++)
{
Component c = parent.getComponent (i);
if (c.isVisible ())
r [i] = c.getBounds ();
else r [i] = new Rectangle (0, 0, 0, 0);
}
r = doLayout (r);
int minX = 0;
int minY = 0;
for (int i = 0; i < count; i++)
{
minX = Math.min (minX, r [i].x);
minY = Math.min (minY, r [i].y);
}
for (int i = 0; i < count; i++)
{
r [i].translate (-minX, -minY);
Component c = parent.getComponent (i);
if (c.isVisible ())
c.setBounds (r [i]);
}
}
public Rectangle [] doLayout (Rectangle [] initialPositions)
{
int count = initialPositions.length;
Rectangle [] result = new Rectangle [count];
for (int i = 0; i < count; i++)
result [i] = new Rectangle (initialPositions [i]);
boolean intersection;
do
{
intersection = false;
for (int i = 0; i < count; i++)
{
int xf = 0;
int yf = 0;
Rectangle r1 = result [i];
for (int j = 0; j < count; j++)
{
Rectangle r2 = result [j];
if (i != j && r1.intersects (r2))
{
if (r1.x * 2 + r1.width < r2.x * 2 + r2.width)
xf -= 1;
else
xf += 1;
if (r1.y * 2 + r1.height < r2.y * 2 + r2.height)
yf -= 1;
else
yf += 1;
intersection = true;
}
}
if (xf > 0) result [i].x += 1;
else if (xf < 0) result [i].x -= 1;
if (yf > 0) result [i].y += 1;
else if (yf < 0) result [i].y -= 1;
}
} while (intersection);
return result;
}
public static void main (String [] args)
{
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane ().setLayout (new NonOverlappingLayout ());
Random r = new Random ();
for (int i = 0; i < 100; i++)
{
JButton b = new JButton ();
b.setBounds (r.nextInt (780), r.nextInt (580), 20, 20);
frame.getContentPane ().add (b);
}
frame.getContentPane ();
frame.pack ();
frame.setVisible (true);
}
}

Related

What is the best way to build a Minesweeper Board in a JFrame?

I am just trying to construct a gameboard with tiles to work with. I got it to work by painting the tile into rows and columns with BufferedImage, but I am going to need to constantly update the GUI as the game is played.
So I tried to add the tile image to an ImageIcon, then to a JLabel array so that I could set the position. After that I would add the labels to the gui JPanel, but they had these default gaps between them.
Am I approaching this incorrectly? I am very new to Swing and Java
public static void main (String[] args) throws IOException{
int NUMROWS = 10;
int NUMCOLS = 10;
int NUMMINES = 10;
int[] mineList = GameBoard.setMines(NUMMINES, NUMROWS, NUMCOLS);
int[][] cellNums = GameBoard.setCellNum(NUMROWS, NUMCOLS);
boolean[][] mineField = GameBoard.getMineField(mineList, cellNums);
int[][] adjacentMineVals = GameBoard.getAdjacentMineVals(cellNums, mineField);
ImageIcon img = new ImageIcon(ImageIO.read(new File("GraphicFile\\Cell.png")));
JLabel[][] label = new JLabel[NUMROWS][NUMCOLS];
for (int i = 0; i < NUMROWS; i++){
for (int j = 0; j < NUMCOLS; j++){
label[i][j] = new JLabel();
label[i][j].setIcon(img);
label[i][j].setLocation(i*img.getIconHeight(), j*img.getIconWidth());
}
}
JFrame frame = buildFrame();
int fX = 2*frame.getInsets().left;
int fY = (frame.getInsets().top + frame.getInsets().bottom);
JPanel GUI = new JPanel();
GUI.setSize(NUMCOLS*img.getIconWidth(), NUMROWS*img.getIconHeight());
for (int i = 0; i < NUMCOLS; i++){
for (int j = 0; j < NUMROWS; j ++){
GUI.add(label[i][j]);
}
}
frame.setSize(NUMCOLS*img.getIconWidth() + fX, NUMROWS*img.getIconHeight() + fY);
frame.add(GUI);
}
public static JFrame buildFrame(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
return frame;
}
Here's what it gives me
https://i.stack.imgur.com/rX3yM.png
Update, to new version. Previous problem has been solved by using a grid and putting the images into the buttons as icons
Here is what I have. It is not putting the label with the text onto the button that has been pressed. I debugged, and its receiving input for coords and for text, but its just not painting it onto the panel
public MinesweeperGraphics() throws IOException {
GUI.setOpaque(false);
for (int i = 0; i < NUMROWS; i++){
for (int j = 0; j < NUMCOLS; j++){
buttons[i][j] = new JButton();
buttons[i][j].setIcon(tileUp);
buttons[i][j].setBorder(null);
buttons[i][j].addActionListener(this);
buttons[i][j].setPressedIcon(tilePressed);
GUI.add(buttons[i][j]);
}
}
frame.add(GUI, BorderLayout.CENTER);
frame.add(reset, BorderLayout.NORTH);
reset.addActionListener(this);
frame.setResizable(false);
frame.pack();
GUI.setLayout(null);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(reset)){
for (int i = 0; i < NUMROWS; i++){
for (int j = 0; j < NUMCOLS; j++){
buttons[i][j].setIcon(tileUp);
}
}
}else {
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons.length; j++) {
if (e.getSource().equals(buttons[i][j])){
if (mineField[i][j] == false){
buttons[i][j].setIcon(tileEmpty);
numberText.setOpaque(false);
numberText.setSize(buttons[i][j].getWidth(), buttons[i][j].getHeight());
numberText.setText("a");
numberText.setLocation(buttons[i][j].getLocation());
GUI.add(numberText);
} else if (mineField[i][j] == true){
buttons[i][j].setIcon(tileExplodedMine);
}
//isn't working here
buttons[i][j].setEnabled(false);
}
}
}
}
}
The best way to build a Mine Sweeper game would be to put buttons with an action listener into a grid layout. The buttons will respond to both keyboard and mouse input & can display icons. The grid layout can organise them on-screen.
Following is an MCVE of buttons in a GridLayout. Different to as described above is that it:
Does not add action listeners
Uses a MineFieldModel
Uses text instead of icons.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MineSweeper {
private JComponent ui = null;
private MineFieldModel mineFieldModel;
Color[] colors = {
Color.BLUE,
Color.CYAN.darker(),
Color.GREEN.darker(),
Color.YELLOW.darker(),
Color.ORANGE.darker(),
Color.PINK.darker(),
Color.MAGENTA,
Color.RED
};
public final static String BOMB = new String(Character.toChars(128163));
JButton[][] buttons;
int size = 16;
MineSweeper() {
initUI();
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
mineFieldModel = new MineFieldModel(16, 40);
JPanel mineFieldContainer = new JPanel(new GridLayout(
size, size));
ui.add(mineFieldContainer, BorderLayout.CENTER);
int in = 5;
Insets insets = new Insets(in, in, in, in);
Font f = getCompatibleFonts().firstElement().deriveFont(16f);
buttons = new JButton[size][size];
for (int ii = 0; ii < size; ii++) {
for (int jj = 0; jj < size; jj++) {
JButton b = new JButton();
b.setMargin(insets);
b.setFont(f);
b.setText("?");
if (mineFieldModel.isExposed(ii, jj)) {
if (mineFieldModel.isBomb(ii, jj)) {
b.setForeground(Color.red);
b.setForeground(Color.BLACK);
b.setText(BOMB);
} else if (mineFieldModel.countSurroundingMines(ii, jj) > 0) {
int count = mineFieldModel.countSurroundingMines(ii, jj);
if (count > 0) {
b.setForeground(colors[count - 1]);
b.setText("" + count);
}
} else {
b.setText("");
}
}
mineFieldContainer.add(b);
}
}
}
private static Vector<Font> getCompatibleFonts() {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Vector<Font> fontVector = new Vector<>();
for (Font font : fonts) {
if (font.canDisplayUpTo("12345678" + BOMB) < 0) {
fontVector.add(font);
}
}
return fontVector;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MineSweeper o = new MineSweeper();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
class MineFieldModel {
public int size;
/**
* Records bomb locations.
*/
boolean[][] mineField;
/**
* Records whether this location has been exposed.
*/
boolean[][] fieldPlaceExposed;
int numberMines;
Random r = new Random();
MineFieldModel(int size, int numberMines) {
this.size = size;
this.numberMines = numberMines;
mineField = new boolean[size][size];
fieldPlaceExposed = new boolean[size][size];
ArrayList<Point> locations = new ArrayList<>();
for (int ii = 0; ii < this.size; ii++) {
for (int jj = 0; jj < size; jj++) {
mineField[ii][jj] = false;
// must change this to false for the actual game.
fieldPlaceExposed[ii][jj] = true;
Point p = new Point(ii, jj);
locations.add(p);
}
}
Collections.shuffle(locations, r);
for (int ii = 0; ii < numberMines; ii++) {
Point p = locations.get(ii);
mineField[p.x][p.y] = true;
}
}
public boolean isBomb(int x, int y) {
return mineField[x][y];
}
public boolean isExposed(int x, int y) {
return fieldPlaceExposed[x][y];
}
public int getSize() {
return size;
}
public int countSurroundingMines(int x, int y) {
int lowX = x - 1;
lowX = lowX < 0 ? 0 : lowX;
int highX = x + 2;
highX = highX > size ? size : highX;
int lowY = y - 1;
lowY = lowY < 0 ? 0 : lowY;
int highY = y + 2;
highY = highY > size ? size : highY;
int count = 0;
for (int ii = lowX; ii < highX; ii++) {
for (int jj = lowY; jj < highY; jj++) {
if (ii != x || jj != y) {
if (mineField[ii][jj]) {
count++;
}
}
}
}
return count;
}
}

Transforming an Image to move diagnally

public void draw(Graphics g, Graphics g2d, double theta, int NEWY){
g.setColor(Color.orange);
int drawLocationX = character.x;
int drawLocationY = character.y-47;
double rotationRequired = Math.toRadians (theta);
double locationX = this.getWidth()/2;
double locationY = this.getHeight()/2;
AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g2d.drawImage(op.filter(image, null), drawLocationX, NEWY, null);
}
public int getHeightWorld(int x){
//meant to find height of land at specified location
int highest = 0;
int checked = 0;
for(int c = panel.HEIGHT-1; c >= 0; c--){
if(this.inColRange(x)&& this.inRowRange(c))
if(LandList[c][x] == 2){
highest = c;
checked++;
}
}
return (1000 - highest);
}
public double getAngleWorldT1(){
//meant to find angle tank needs to be rotated at
int g = this.getHeightWorld(tank1.getNEWX());
int h = this.getHeightWorld((tank1.getWidth()+ tank1.getNEWX()));
double trythis = this.NewEquation();
int newg = tank1.getWidth()+ tank1.getNEWX();
int newh = tank2.getWidth()+ tank2.getNEWX();
double newery = (trythis*newg);
double newery2 = (trythis*tank1.getNEWX());
double newval = newery - newery2;
double u = 5;
double width = tank1.getWidth();
if(Math.abs(h-g) > tank1.getWidth()){
u = width/(g-h);
}
else{
u = (g-h)/width;
}
double p = 57.6846779*Math.asin(Math.toRadians(u));
return p;
}
public double NewEquation(){
int dividethis = 0;
int subtractthis = 0;
int numnegative = 0;
for(int what = 0; what < tank1.getWidth(); what++){
if(Math.abs(this.getHeightWorld(what)-this.getHeightWorld(what-1)) < 2){
dividethis += this.getHeightWorld(what);
if(this.getHeightWorld(what)-this.getHeightWorld(what-1) < 0){
numnegative++;
}
}
else{
subtractthis++;
}
}
dividethis = dividethis/(tank1.getWidth()-subtractthis);
if((numnegative - tank1.getWidth()) > tank1.getWidth()/2){
dividethis = dividethis*-1;
}
return dividethis;
}
public void draw(Graphics g) {
//MOVE TO DIFF METHOD
int newy = this.getHeightWorld(tank1.getNEWX()) - tank1.getHeight();
int newy2 = this.getHeightWorld(tank2.getNEWX()) - tank2.getHeight();
if( LandList[newy][tank1.getNEWX()] == 2){
while (LandList[newy][tank1.getNEWX()] == 2){
newy--;
// System.out.println("FIRST HERE");
// System.out.println(newy);
}
// System.out.println("FIRST");
}
if( LandList[newy+1][tank1.getNEWX()] != 2){
while (LandList[newy+1][tank1.getNEWX()] != 2){
newy++;
// System.out.println("SECOND HERE");
}
// System.out.println("SECOND");
}
//System.out.println("YESSSSS" +Math.toDegrees(this.getAngleWorldT1()) );
tank1.draw(g, g, Math.toDegrees(this.getAngleWorldT1()), newy - tank1.getHeight()-50);
tank2.draw(g, g, Math.toDegrees(this.getAngleWorldT2()), newy2 - tank2.getHeight());
// System.out.println("2");
for(int x = 0; x < platforms.size(); x++){
platforms.get(x).draw(g);
}
}
}
(Sorry for the messy code.)
These are two classes I am using to design a tank shooter game. In this portion, I am attempting to make the image rotate according to the land it is over(to appear traveling uphill or downhill) and I don't want any piece inside of the land. "LandList" is a 2D array that has a value of 2 if there is land and 1 if there is no land. Two issues is A) rotating at incorrect heights and not rotating at all points
B)Image cuts off at a certain height
Thank you for your help.
BOTH CLASSES IN FULL
public class World {
Land[][] land;
List<Land> platforms = new ArrayList<Land>();
private GraphicsPanel panel;
int[][] LandList = new int[800][1500];
private int delay = 30;
private Timer timer;
private Random r;
Tank tank1;
Tank tank2;
public World(GraphicsPanel marioPanel) {
panel = marioPanel;
land = new Land[panel.WIDTH][panel.HEIGHT-500-3];
setUpWorld();
setUpTimer();
}
private void setUpWorld() {
for(int r = 0; r < panel.WIDTH; r++){
for(int c = 0; c < panel.HEIGHT; c++){
LandList[c][r] = 1;
}
}
//tank not displaying
//a lot of stuff copied over
tank1 = new Tank(25,442,100,60,1);
tank2 = new Tank(700,442,100,60,2);
r = new Random();
int w = 0;
int n = 0;
for(int x = 0; x < panel.WIDTH; x+=5){
if(x > 0 && x < panel.WIDTH/6 +1){
//for(int y = (int) (500+(-(100*Math.random())*((x%2)+1))); y < panel.HEIGHT; y+=5){
for(int y = 500; y < panel.HEIGHT; y+=5){
Land creating = new Land(x, y, 5, 5);
platforms.add(creating);
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
if(inRowRange(x+r) && inColRange(y+c))
LandList[y+r][x+c] = 2;
}
}
}
}
if(x > panel.WIDTH/6 && x < 2*panel.WIDTH/6 +1){
//for(int y = (int) (500+(-(100*Math.random())*((x%2)+1))); y < panel.HEIGHT; y+=5){
for(int y = 500+ 4*w; y < panel.HEIGHT; y+=5){
Land creating = new Land(x, y, 5, 5);
platforms.add(creating);
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
if(inRowRange(y+r) && inColRange(x+c))
LandList[y+r][x+c] = 2;
}
}
}
w--;
}
if(x > 2*panel.WIDTH/6 && x < 3*panel.WIDTH/6 +1){
//for(int y = (int) (500+(-(100*Math.random())*((x%2)+1))); y < panel.HEIGHT; y+=5){
for(int y = 500+ 4*w; y < panel.HEIGHT; y+=5){
Land creating = new Land(x, y, 5, 5);
platforms.add(creating);
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
if(inRowRange(y+r) && inColRange(x+c))
LandList[y+r][x+c] = 2;
}
}
}
w++;
}
if(x > 3*panel.WIDTH/6 && x < 4*panel.WIDTH/6 +1){
//for(int y = (int) (500+(-(100*Math.random())*((x%2)+1))); y < panel.HEIGHT; y+=5){
for(int y = 500+ 4*n; y < panel.HEIGHT; y+=5){
Land creating = new Land(x, y, 5, 5);
platforms.add(creating);
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
if(inRowRange(y+r) && inColRange(x+c))
LandList[y+r][x+c] = 2;
}
}
}
n--;
}
if(x > 4*panel.WIDTH/6 && x < 5*panel.WIDTH/6 +1){
//for(int y = (int) (500+(-(100*Math.random())*((x%2)+1))); y < panel.HEIGHT; y+=5){
for(int y = 500+ 4*n; y < panel.HEIGHT; y+=5){
Land creating = new Land(x, y, 5, 5);
platforms.add(creating);
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
if(inRowRange(y+r) && inColRange(x+c))
LandList[y+r][x+c] = 2;
}
}
}
n++;
}
if(x > 5*panel.WIDTH/6){
//for(int y = (int) (500+(-(100*Math.random())*((x%2)+1))); y < panel.HEIGHT; y+=5){
for(int y = 500; y < panel.HEIGHT; y+=5){
Land creating = new Land(x, y, 5, 5);
platforms.add(creating);
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
if(inRowRange(y+r) && inColRange(x+c))
LandList[y+r][x+c] = 2;
// System.out.println(LandList[x+r][y+c]);
}
}
}
}
// else{
// for(int y = 500; y < panel.HEIGHT; y+=5){
// Land creating = new Land(x, y, 5, 5);
// platforms.add(creating);
// }
//
// }
}
for(int r = 0; r < panel.WIDTH; r++){
for(int c = 0; c < panel.HEIGHT; c++){
//System.out.println(LandList[r][c]);
}
}
for(int checked = 0; checked < panel.WIDTH; checked++){
System.out.println(this.getHeightWorld(checked));
}
// System.out.println(LandList);
}
private boolean inColRange(int i) {
// TODO Auto-generated method stub
return i>=0 && i<LandList[0].length;
}
private boolean inRowRange(int i) {
// TODO Auto-generated method stub
return i>=0 && i<LandList.length;
}
private void setUpTimer() {
timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// what should happen each time the timer goes off?
panel.repaint();
moveStuff();
checkHitBoxes();
//System.out.println(mario.getY());
}
});
timer.start();
}
protected void checkHitBoxes() {
}
protected void moveStuff() {
tank1.move();
panel.repaint();
}
public int getHeightWorld(int x){
//meant to find height of land at specified location
int highest = 0;
int checked = 0;
for(int c = panel.HEIGHT-1; c >= 0; c--){
if(this.inColRange(x)&& this.inRowRange(c))
if(LandList[c][x] == 2){
highest = c;
checked++;
}
}
return (1000 - highest);
}
public double getAngleWorldT1(){
//meant to find angle tank needs to be rotated at
int g = this.getHeightWorld(tank1.getNEWX());
int h = this.getHeightWorld((tank1.getWidth()+ tank1.getNEWX()));
double trythis = this.NewEquation();
int newg = tank1.getWidth()+ tank1.getNEWX();
int newh = tank2.getWidth()+ tank2.getNEWX();
double newery = (trythis*newg);
double newery2 = (trythis*tank1.getNEWX());
double newval = newery - newery2;
double u = 5;
double width = tank1.getWidth();
if(Math.abs(h-g) > tank1.getWidth()){
u = width/(g-h);
}
else{
u = (g-h)/width;
}
double p = 57.6846779*Math.asin(Math.toRadians(u));
return p;
}
public double getAngleWorldT2(){
int a = this.getHeightWorld(tank2.getNEWX());
int s = this.getHeightWorld((tank2.getWidth() + tank2.getNEWX() + 100) );
// a = 100;
// s = 700;
int o = (a-s)/tank2.getWidth();
//System.out.println(o);
double p = -57.6846779*(Math.asin(Math.toRadians(o)));
//System.out.println(p);
return p;
}
public double NewEquation(){
int dividethis = 0;
int subtractthis = 0;
int numnegative = 0;
for(int what = 0; what < tank1.getWidth(); what++){
if(Math.abs(this.getHeightWorld(what)-this.getHeightWorld(what-1)) < 2){
dividethis += this.getHeightWorld(what);
if(this.getHeightWorld(what)-this.getHeightWorld(what-1) < 0){
numnegative++;
}
}
else{
subtractthis++;
}
}
dividethis = dividethis/(tank1.getWidth()-subtractthis);
if((numnegative - tank1.getWidth()) > tank1.getWidth()/2){
dividethis = dividethis*-1;
}
return dividethis;
}
public void draw(Graphics g) {
//MOVE TO DIFF METHOD
int newy = this.getHeightWorld(tank1.getNEWX()) - tank1.getHeight();
int newy2 = this.getHeightWorld(tank2.getNEWX()) - tank2.getHeight();
if( LandList[newy][tank1.getNEWX()] == 2){
while (LandList[newy][tank1.getNEWX()] == 2){
newy--;
// System.out.println("FIRST HERE");
// System.out.println(newy);
}
// System.out.println("FIRST");
}
if( LandList[newy+1][tank1.getNEWX()] != 2){
while (LandList[newy+1][tank1.getNEWX()] != 2){
newy++;
// System.out.println("SECOND HERE");
}
// System.out.println("SECOND");
}
//System.out.println("YESSSSS" +Math.toDegrees(this.getAngleWorldT1()) );
tank1.draw(g, g, Math.toDegrees(this.getAngleWorldT1()), newy - tank1.getHeight()-50);
tank2.draw(g, g, Math.toDegrees(this.getAngleWorldT2()), newy2 - tank2.getHeight());
// System.out.println("2");
for(int x = 0; x < platforms.size(); x++){
platforms.get(x).draw(g);
}
}
}
public class Tank extends Moveable{
private boolean moveRight,moveLeft;
private String direction = "NONE";
private int dx =5;
//graphics
BufferedImage image = null;
private URL file;
private Rectangle character;
private Rectangle hitBox;
JLabel label = new JLabel();
private int NEWX;
public Tank(int x, int y, int w, int h, int color){
character = new Rectangle(x,y,w,h);
this.create(null,x,y,w,h);
NEWX = character.x;
BufferedImage img =null;
if(color == 1){
// file= getClass().getResource("pictures\\green_tank1");
try {
img = ImageIO.read(new File("green_tank1.png"));
image = img;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
// file = getClass().getResource("pictures\\blue_tank1");
try {
img = ImageIO.read(new File("blue_tank1.png"));
image = img;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void draw(Graphics g, Graphics g2d, double theta, int NEWY){
g.setColor(Color.orange);
int drawLocationX = character.x;
int drawLocationY = character.y-47;
double rotationRequired = Math.toRadians (theta);
double locationX = this.getWidth()/2;
double locationY = this.getHeight()/2;
AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g2d.drawImage(op.filter(image, null), drawLocationX, NEWY, null);
//System.out.println("This is new X " + NEWX);
// label.setVisible(true);
// label.isOpaque();
// label.setBounds(character.x, character.y, character.width, character.height);
// label.repaint();
//g.drawImage(image, 0, 0, null);
// int centerx = character.x + character.width/2;
// int centery = character.y + character.height/2;
//
// int point1 = (int) (centerx + (character.width/2)*Math.cos(Math.toRadians(theta)) - (character.height/2)* Math.sin(Math.toRadians(theta)));
// int point2 = (int) (centery + (character.height/2)*Math.cos(Math.toRadians(theta))+(character.width/2)*Math.sin(Math.toRadians(theta)));
// int point3 =(int) (centerx - (character.width/2)*Math.cos(Math.toRadians(theta)) + (character.height/2)* Math.sin(Math.toRadians(theta)));
// int point4 = (int) (centery - (character.height/2)*Math.cos(Math.toRadians(theta))-(character.width/2)*Math.sin(Math.toRadians(theta)));
// //System.out.println(theta);
// g.drawImage(image, point1,point2,point3,point4, null);
//// System.out.println("3");
// Rotation information
// AffineTransform tx = AffineTransform.getRotateInstance(Math.toRadians (theta), character.x, character.y);
// AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
//
// // Drawing the rotated image at the required drawing locations
// g.drawImage(op.filter((BufferedImage) image, null), character.x, character.y, null);
// System.out.println(this.getX());
// System.out.println(this.getY());
// System.out.println(this.getWidth());
// System.out.println(this.getHeight());
// g.fillRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
// this.setBounds(this.getX(), this.getY(), this.getWidth(), this.getHeight());
//
}
public Rectangle getRect(){
return this.character;
}
public void move(){
if(moveLeft == true){
character.setBounds(character.x -2, character.y, character.width, character.height);
character.x = character.x -2;
NEWX += -2;
}
if(moveRight == true){
character.setBounds(character.x +2, character.y, character.width, character.height);
character.x = character.x +2;
NEWX += 2;
}
}
public void setDirection(String s){
this.direction = s;
String x = s.toUpperCase().substring(0, 1);
if(x.equals("L")){
//System.out.println(x);
moveLeft = true;
moveRight = false;
}
if(x.equals("R")){
moveRight = true;
moveLeft = false;
// System.out.println("im here");
}
else if(x.equals("N")){
moveRight = false;
moveLeft =false;
// System.out.println("I Got Here #2");
}
}
public String getDirection(){
return this.direction;
}
public int getNEWX(){
return this.NEWX;
}
}

My sorting algorithms are only going through once

I am writing a program that sorts 2 arrays of the same values by using two different algorithms. It loops through the arrays once each time a button is clicked. My problem is that it only sorts the first time you click the button. Every other time nothing happens. I put a count incrementer to see if the code was running and it was. I'm stumped. Any help will be appreciated.
I fixed the selection sort.
public class TwoSortsPanel extends JPanel
{
private int width = 10, gap = 3, x = 200, y = 50;
private int[] ranArr1 = new int[15], ranArr2 = new int[15];
private Color blue = Color.blue, red = Color.red, pink = Color.pink, gray = Color.gray;
public static int count = 0, indexSel = 0;
{
for(int i = 0; i < ranArr1.length-1; i++)
{
ranArr1[i] = (int) (Math.random() * 15);
ranArr2[i] = ranArr1[i];
}
}
public TwoSortsPanel()
{
printArray(ranArr1);
setBackground(pink);
setPreferredSize (new Dimension (400,300));
JButton sort = new JButton ("Sort");
sort.addActionListener(new ButtonListener());
add (sort);
}
public static void printArray(int[] c)
{
System.out.println(Arrays.toString(c));
}
public void paintComponent (Graphics page)
{
super.paintComponent(page);
page.drawString("" + count, 10, 12);
if (insertion() == false || selection() == false)
{
int yPlus = 50;
for(int i = 0; i < ranArr1.length; i++)
{
page.setColor(blue);
page.fillRect(x, yPlus, ranArr1[i]*10, width);
yPlus += width + gap;
}
yPlus = 50;
for(int i = 0; i < ranArr2.length; i++)
{
page.setColor(red);
page.fillRect(x, yPlus, -ranArr2[i]*10, width);
yPlus += width + gap;
}
}
else
{
int yPlus = 50;
for(int i = 0; i < ranArr1.length; i++)
{
page.setColor(gray);
page.fillRect(x, yPlus, ranArr1[i]*10, width);
yPlus += width + gap;
}
yPlus = 50;
for(int i = 0; i < ranArr2.length; i++)
{
page.setColor(gray);
page.fillRect(x, yPlus, -ranArr2[i]*10, width);
yPlus += width + gap;
}
}
}
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
displaySelection(ranArr1);
displayInsertion(ranArr2);
count++;
printArray(ranArr1);
repaint();
}
}
public static void displaySelection(int[] a)
{
int temp;
int min = indexSel;
for (int scan = indexSel+1; scan < a.length ; scan++)
if (a[scan] < a[min])
min = scan;
temp = a[min];
a[min] = a[indexSel];
a[indexSel] = temp;
count++;
indexSel++;
}
public static void displayInsertion(int[] b)
{
int index = 1;
int key = b[index];
int position = index;
while (position > 0 && b[position-1] > key )
{
b[position] = b[position-1];
position--;
}
b[position] = key;
}
public boolean selection()
{
for (int i = 0; i < ranArr1.length-1; i++)
{
if(ranArr1[i] > ranArr1[i+1])
{
return false;
}
}
return true;
}
public boolean insertion()
{
for (int i = 0; i < ranArr2.length-1; i++)
{
if(ranArr2[i] > ranArr2[i+1])
{
return false;
}
}
return true;
}
}
Sorry. I didn't want the post to look too busy and I guess it lost meaning.

Java Tetris - Confused on grid[row][col] and coordinates (x, y)

I'm making Tetris in java for fun... I pretty much had everything working... but later found out that when I wanted to change the dimensions so it was square ([10 row][10 col] matrix, but instead a [12 row][10 col] matrix), that I started getting Index Out of Bound exceptions... see here: Java Tetris - weird row clearing issue
So I tried fixing everything so that the rows and columns weren't flip flopped... But am now getting hung up on the fact that the grid takes [row][col], but I’m moving around the tiles as (x, y) coordinates…
What’s confusing me is that row = y and col = x… which is reversed… so when I pass in coordinates I’m not sure when to swap them.
I know it’s a simple thing, but it’s confusing the hell out of me and I keep getting out of bounds exceptions whenever I think I have it right.
I'm not sure where the exact issue is, so I'm posting a full Sscce of my program... I think the issue is in the Board class...
Here, the block should still be able to move down... but if it tries to go down further than this...
I get:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
at Board.getTileAt(Board.java:177)
at Tile.collision(Tile.java:31)
at Piece.isCollision(Piece.java:172)
at Board.collisionCheck(Board.java:192)
at Piece.movePieceCheck(Piece.java:87)
at Board.keyPressed(Board.java:160)
Sscce:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainSscce extends JPanel {
static MainSscce runMe;
BoardSscce gameBoard, scoreBoard;
public MainSscce() { //creates a new frame window and sets properties
JFrame f = new JFrame("Tetris");
//width (height), length, tilesize
gameBoard = new BoardSscce(12, 10, 35);
// scoreBoard = new BoardSscce(10, 10, 35);
f.add(gameBoard);
f.setSize(gameBoard.getWidth(), gameBoard.getHeight());
f.setVisible(true);
f.setResizable(false);
f.setVisible(true);
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
//set j frame location to appear in middle of screen
f.setLocation( (screensize.width - f.getWidth())/2,
(screensize.height - f.getHeight())/2-100 );
}
public static void main(String[] args) {
runMe = new MainSscce();
}
}
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.event.*; // for ActionListener and ActionEvent
import java.util.Random;
public class BoardSscce extends JPanel implements KeyListener {
private TileSscce grid[][];
private int totalRows, totalCols, tilesize, level, totalScore;
private final int changeLevelMultiplier;
private PieceSscce newPiece, nextPiece;
private String randomPiece;
private boolean gameLost;
public BoardSscce(int r, int c, int ts) {
totalRows = r;
totalCols = c;
tilesize = ts;
//set grid size to [# rows][# columns], aka [height][width]
grid = new TileSscce[totalRows][totalCols];
gameLost = false;
System.out.println("TotalRows: " + totalRows + ", " + "TotalCols: " + totalCols);
//multiplier to determine what score the level changes, which is:
//level * changeLevelMultiplier;
changeLevelMultiplier = 40;
//initialize score to 0
totalScore = 0;
//initialize level to 0
level = 0;
newPiece = new PieceSscce(this, randomPiece(), getColor());
addKeyListener(this);
setFocusable(true);
//getTranspose();
timer();
}
public String randomPiece() {
String[] Pieces = {"L", "O", "Z", "RevZ", "Bar", "T", "RevL"};
int rand = (int) (Math.random() * Pieces.length);
randomPiece = Pieces[rand];
return randomPiece;
}
public Color getColor() {
Color color;
if (randomPiece.equals("L"))
color = new Color(17, 255, 0);
else if(randomPiece.equals("O"))
color = new Color(117, 168, 255);
else if(randomPiece.equals("Z"))
color = new Color(255, 187, 82);
else if(randomPiece.equals("RevZ"))
color = new Color(206, 27, 72);
else if(randomPiece.equals("Bar"))
color = new Color(50, 216, 219);
else if(randomPiece.equals("T"))
color = new Color(252, 148, 240);
else
color = new Color(255, 255, 52);
//Random rand = new Random();
//float r = rand.nextFloat();
//float g = rand.nextFloat();
//float b = rand.nextFloat();
//Color randomColor = new Color(r, g, b);
return color;
}
//dimensions of board = width * tilesize
public int getWidth() {
return totalCols * tilesize;
}
public int getHeight() {
return totalRows * tilesize;
}
public int getTileSize() {
return tilesize;
}
public void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid[row].length; col++) {
//System.out.println(row + ", " + col);
g.drawString("[" + row + "][" + col + "]", col * tilesize, row * tilesize+10);
System.out.println(row + ", " + col);
//if there is a non-null space, that is a Tetris piece... fill it
if(grid[row][col] != null) {
g.setColor(grid[row][col].getColor());
g.fillRect(row * tilesize, col * tilesize, tilesize, tilesize);
g.setColor(Color.WHITE);
}
}
}
// g.drawString("Level: " + level, this.getWidth()/2, this.getHeight()/2-130);
// g.drawString("Score: " + totalScore, this.getWidth()/2, this.getHeight()/2-100);
if (gameLost == true) {
g.drawString("Way to go, loser...", this.getWidth()/2, this.getHeight()/2);
messageTimer();
}
}
//Auto move piece
public void timer () {
int interval;
switch (level) {
//each level increases drop speed by .10 seconds
case 1: interval = 800;
break;
case 2: interval = 700;
break;
case 3: interval = 600;
break;
case 4: interval = 500;
break;
default: interval = 1000;
break;
}
Timer t = new Timer(interval, new ActionListener() {
public void actionPerformed(ActionEvent e) {
//newPiece.autoMove();
//repaint();
}
});
t.start();
}
public void messageTimer() {
Timer t = new Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
gameLost = false;
}
});
t.start();
}
//move piece on key input
public void keyPressed(KeyEvent e) {
newPiece.movePieceCheck(e.getKeyCode());
repaint();
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}
// returns the tile at (x, y) or null if empty
public Tile getTileAt(int x, int y) {
if(isValidCoordinate(x, y))
return grid[x][y];
return null;
}
// sets the tile at (x, y) to tile
public void setTileAt(Tile tile, int x, int y) {
if(isValidCoordinate(x, y))
grid[x][y] = tile;
}
public boolean isOpen(int x, int y) {
return isValidCoordinate(x, y) && (getTileAt(x, y) == null);
}
public void collisionCheck() {
if (newPiece.isCollision()){
newPiece = new PieceSscce(this, randomPiece(), getColor());
}
}
public void changeLevel () {
int max = (level+1)*changeLevelMultiplier;
if (totalScore >= max) {
System.out.println(max + "reached... next level");
level++;
totalScore = 0;
timer();
}
}
public int tallyScore(int totalLines) {
int score = 0;
switch (totalLines) {
case 1: score = 40 * (level + 1);
break;
case 2: score = 100 * (level + 1);
break;
case 3: score = 300 * (level + 1);
break;
case 4: score = 1200 * (level + 1);
break;
default: break;
}
return score;
}
//loop through all rows starting at bottom (12 rows)
public void checkBottomFull() {
int lines = 0;
for(int row = 12; row > 0; row--) {
/* while (isFull(row)) {
lines++;
// clearRow(row);
}*/
}
totalScore += tallyScore(lines);
//check if level needs to be changed based on current score...
changeLevel();
//reset lines after score has been incremented
lines=0;
}
//loop through all columns in that row (10 columns)
public boolean isFull(int row) {
for (int col = 0; col <= 10; col++) {
System.out.println(row + ", " + col);
if(grid[row][col] == null) {
return false;
}
}
return true;
}
public void clearRow(int rowToClear) {
for(int row = rowToClear; row > 0; row--) {
for(int col = 0; col < grid[row].length; col++) {
grid[col][row] = grid[col][row-1];
}
}
}
public void checkEndGame(int x, int y) {
//if currPiece y location = 0 AND the space below is filled...
if (y <= 2 && !isOpen(x, y+1)) {
gameLost = true;
level = 0;
totalScore = 0;
//reset timer
timer();
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid[row].length; col++) {
grid[row][col] = null;
}
}
}
}
}
import java.awt.Color;
import java.awt.event.KeyEvent;
public class PieceSscce {
public int[] pieceCoordinates;
public String shape, currRotation;
public Color color;
public BoardSscce board;
public int rotationsCounter;
public TileSscce tile[];
public int[] newPositionX, newPositionY, currPositionX, currPositionY;
//don't need to pass in board because I'm already utilizing the Tiles class, which knows about the board
public Piece(Board b, String randomPiece, Color randomColor) {
shape = randomPiece;
color = randomColor;
board = b;
newPositionX = new int[4];
newPositionY = new int[4];
currPositionX = new int[4];
currPositionY = new int[4];
pieceCoordinates = new int[8];
//set pieceCoordinates global variable
getShape(shape);
tile = new TileSscce[4];
int counterX = 0, counterY = 1;
System.out.print("\"" + shape + "\" Coordinates: ");
//generate 4 new Tiles at specified coordinates that will compose the Piece
for (int i = 0; i < tile.length; i++) {
tile[i] = new TileSscce(board, pieceCoordinates[counterX], pieceCoordinates[counterY]);
System.out.print("(" + pieceCoordinates[counterX] + ", " + pieceCoordinates[counterY] + ") ");
//increment by 2 because x,y values are next to each other in array
counterX+=2;
counterY+=2;
}
System.out.println("\n");
for (int i = 0; i < tile.length; i++) {
tile[i].setColor(color);
}
}
public void calcNewPosition(int newX, int newY, int currTile) {
newPositionX[currTile] = newX;
newPositionY[currTile] = newY;
}
public void clearCurrPosition() {
for (int i = 0; i < tile.length; i++) {
currPositionX[i] = tile[i].getX();
currPositionY[i] = tile[i].getY();
board.setTileAt(null, currPositionX[i], currPositionY[i]);
}
}
public void autoMove() {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX(), tile[i].getY()+1, i);
}
clearCurrPosition();
for (int i = 0; i < tile.length; i++) {
board.checkEndGame(tile[i].getX(), tile[i].getY());
System.out.println("Checking..." + tile[i].getX() + ", " + tile[i].getY());
}
board.checkBottomFull();
board.collisionCheck();
move();
}
public void movePieceCheck(int keycode) {
if (keycode == KeyEvent.VK_DOWN) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX(), tile[i].getY()+1, i);
}
clearCurrPosition();
for (int i = 0; i < tile.length; i++) {
board.checkEndGame(tile[i].getX(), tile[i].getY());
System.out.println("Checking..." + tile[i].getX() + ", " + tile[i].getY());
}
board.checkBottomFull();
board.collisionCheck();
move();
}
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX()+1, tile[i].getY(), i);
}
clearCurrPosition();
move();
}
if (keycode == KeyEvent.VK_LEFT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX()-1, tile[i].getY(), i);
}
clearCurrPosition();
move();
}
//rotate left
if (keycode == KeyEvent.VK_A) {
int[] rotatedCoords = calcRotation("left");
clearCurrPosition();
rotate(rotatedCoords, "left");
}
//rotate right
if (keycode == KeyEvent.VK_D) {
int[] rotatedCoords = calcRotation("right");
clearCurrPosition();
rotate(rotatedCoords, "right");
}
}
public boolean movePieceValid() {
boolean valid = true;
for (int i = 0; i < tile.length; i++) {
if(!tile[i].checkNewLocation(newPositionX[i], newPositionY[i]))
valid = false;
}
return valid;
}
public boolean validRotation(int[] rotatedCoordinates) {
boolean valid = true;
int counterX = 0, counterY = 1;
for (int i = 0; i < tile.length; i++) {
if(!tile[i].checkNewLocation(rotatedCoordinates[counterX], rotatedCoordinates[counterY]))
valid = false;
counterX +=2;
counterY +=2;
}
return valid;
}
public void move() {
if (movePieceValid()) {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(newPositionX[i], newPositionY[i]);
}
} else {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(currPositionX[i], currPositionY[i]);
}
}
}
public void rotate(int[] rotatedCoordinates, String rotation) {
int counterX = 0, counterY = 1;
if (validRotation(rotatedCoordinates)) {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(rotatedCoordinates[counterX], rotatedCoordinates[counterY]);
counterX+=2;
counterY+=2;
}
//else, if not valid move set the original location
} else {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(currPositionX[i], currPositionY[i]);
}
}
}
public boolean isCollision() {
boolean collision = false;
for (int i = 0; i < tile.length; i++) {
if(tile[i].collision(newPositionX[i], newPositionY[i])) {
collision = true;
}
}
return collision;
}
//calc curr coordinates, send them to getRotation... which will create new piece based on coords
public int[] calcRotation(String direction) {
for (int i = 0; i < tile.length; i++) {
currPositionX[i] = tile[i].getX();
currPositionY[i] = tile[i].getY();
System.out.println("Current position: (" + currPositionX[i] + "," + currPositionY[i]+")");
}
return getRotation(currPositionX, currPositionY, direction);
}
public int[] getRotation (int coordinatesX[], int coordinatesY[], String direction) {
int[] rotationDirection;
int[] coordinates = new int[8];
int[] origin = new int[2];
int[] newCoordinates = new int[8];
int[] resultCoordinates = new int[8];
int[] finalCoordinates = new int[8];
int vectorMatrix[][] = new int[2][4];
//set either R(90) or R(-90) rotation matrix values:
if (direction.equals("right")) {
rotationDirection = new int[] {0, -1, 1, 0};
}
else {
rotationDirection = new int[] {0, 1, -1, 0};
}
int counterX = 0, counterY = 1, x = 0;
while (counterY < coordinates.length) {
//add arrays coordinatesX and coordinatesY into a single array: coordinates
coordinates[counterX] = coordinatesX[x];
coordinates[counterY] = coordinatesY[x];
counterX+=2;
counterY+=2;
x++;
}
//set origin so it rotates around center...
if (shape.equals("RevZ")) {
origin[0] = coordinates[6];
origin[1] = coordinates[7];
}
else if (shape.equals("T")) {
origin[0] = coordinates[4];
origin[1] = coordinates[5];
}
else {
origin[0] = coordinates[2];
origin[1] = coordinates[3];
}
//subtract origin from vectors
System.out.println();
counterX = 0;
counterY = 1;
while (counterY < newCoordinates.length) {
//System.out.println(coordinates[counterX] + ", " + coordinates[counterY]);
newCoordinates[counterX] = coordinates[counterX] - origin[0];
newCoordinates[counterY] = coordinates[counterY] - origin[1];
System.out.println("Translated coordinates: (" + newCoordinates[counterX] + ", " + newCoordinates[counterY] + ")");
counterX+=2;
counterY+=2;
}
System.out.println();
System.out.println("vector matrix:");
//fill up vectorMatrix with coordinates
int k = 0;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 2; row++) {
vectorMatrix[row][col] = newCoordinates[k++];
}
}
//print vectorMatrix:
for (int i = 0; i < vectorMatrix.length; i++) {
System.out.print("[");
for (int j = 0; j < vectorMatrix[i].length; j++) {
System.out.print(vectorMatrix[i][j]);
}
System.out.println("]");
}
int rotationMatrix[][] = new int[2][2];
//fill up rotationMatrix
System.out.println();
System.out.println("multiplicative matrix:");
k = 0;
for (int row = 0; row < 2; row++) {
System.out.print("[");
for (int col = 0; col < 2; col++) {
rotationMatrix[row][col] = rotationDirection[k++];
System.out.print(rotationMatrix[row][col]);
}
System.out.println("]");
}
//perform matrix multiplication
int[][] result = multiplyMatrices(rotationMatrix, vectorMatrix);
//print resulting matrix
System.out.println();
System.out.println("result matrix:");
for (int i = 0; i < result.length; i++) {
System.out.print("[");
for (int j = 0; j < result[i].length; j++) {
System.out.print(result[i][j]);
}
System.out.println("]");
}
//load new matrix coordinates back into array
k = 0;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 2; row++) {
resultCoordinates[k] = result[row][col];
k++;
}
}
System.out.println();
System.out.println("result coordinates:");
counterX = 0;
counterY = 1;
while (counterY < resultCoordinates.length) {
finalCoordinates[counterX] = resultCoordinates[counterX] + origin[0];
finalCoordinates[counterY] = resultCoordinates[counterY] + origin[1];
System.out.print("("+finalCoordinates[counterX] + ", " + finalCoordinates[counterY]+")");
counterX+=2;
counterY+=2;
}
return finalCoordinates;
}
public int[][] multiplyMatrices(int rotationMatrix[][], int vectorMatrix[][]) {
int mA = rotationMatrix.length;
int nA = rotationMatrix[0].length;
int mB = vectorMatrix.length;
int nB = vectorMatrix[0].length;
if (nA != mB) throw new RuntimeException("Illegal matrix dimensions.");
int[][] C = new int[mA][nB];
for (int i = 0; i < mA; i++) {
for (int j = 0; j < nB; j++) {
for (int k = 0; k < nA; k++) {
C[i][j] += (rotationMatrix[i][k] * vectorMatrix[k][j]);
}
}
}
return C;
}
public int[] getShape(String shape) {
if (shape.equals("L")) {
//pieceCoordinates = new int[] {0, 1, 0, 2, 1, 2, 2, 2};
pieceCoordinates = new int[] {4, 0, 4, 1, 5, 1, 6, 1};
}
else if (shape.equals("O")) {
pieceCoordinates = new int[] {0, 1, 1, 1, 0, 2, 1, 2};
}
else if (shape.equals("Z")) {
pieceCoordinates = new int[] {0, 1, 1, 1, 1, 2, 2, 2};
}
else if (shape.equals("RevZ")) {
pieceCoordinates = new int[] {1, 1, 2, 1, 0, 2, 1, 2};
}
else if (shape.equals("Bar")) {
//pieceCoordinates = new int[] {0, 1, 1, 1, 2, 1, 3, 1};
pieceCoordinates = new int[] {0, 1, 1, 1, 2, 1, 3, 1};
}
else if (shape.equals("T")) {
pieceCoordinates = new int[] {1, 1, 0, 2, 1, 2, 2, 2};
}
else if (shape.equals("RevL")) {
pieceCoordinates = new int[] {0, 2, 1, 2, 2, 2, 2, 1};
}
return pieceCoordinates;
}
}
import java.awt.Color;
import java.util.Random;
public class TileSscce {
private BoardSscce board;
private int currX, currY;
private Color color;
public TileSscce(BoardSscce b, int x, int y) {
board = b;
//when Tile is instantiated, set its position
setLocation(x, y);
}
public int getX() {
return currX;
}
public int getY() {
return currY;
}
public boolean checkNewLocation(int newX, int newY) {
boolean newLocationOK = board.isOpen(newX, newY);
return newLocationOK;
}
public boolean collision(int newX, int newY) {
boolean collision = this.getY() == ((board.getHeight()/board.getTileSize()))-2 || board.getTileAt(newX, newY) != null;
return collision;
}
public void setLocation(int newX, int newY) {
// board.setTileAt(null, currX, currY);
currX = newX;
currY = newY;
board.setTileAt(this, currX, currY);
}
public Color getColor() {
return setColor(color);
}
public Color setColor(Color myColor) {
color = myColor;
return color;
}
}
Thanks!
EDIT----------
I've tried implementing both ValarDohaeris and Svend Hansen's suggestions... Now the block is moving right when I press down, up when I press left, and down when I press right...
It seems to have to do with these methods in Board class which get and set tile locations...
// returns the tile at (x, y) or null if empty
public Tile getTileAt(int row, int col) {
System.out.println("getTileAt: " + row + ", " + col);
if(isValidCoordinate(row, col))
return grid[row][col];
return null;
}
// sets the tile at (x, y) to tile
public void setTileAt(Tile tile, int row, int col) {
System.out.println("setTileAt: " + row + ", " + col);
if(isValidCoordinate(row, col))
grid[row][col] = tile;
}
And in Piece class... movements are defined as:
public void movePieceCheck(int keycode) {
if (keycode == KeyEvent.VK_DOWN) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);
}
clearCurrPosition();
for (int i = 0; i < tile.length; i++) {
board.checkEndGame(tile[i].getRow(), tile[i].getCol());
}
board.checkBottomFull();
if (isCollision()) board.createNewPiece();
move();
}
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
}
clearCurrPosition();
move();
}
if (keycode == KeyEvent.VK_LEFT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()-1, i);
}
clearCurrPosition();
move();
}
You have
grid = new TileSscce[totalRows][totalCols];
So when you want to access grid[x][y], you should check
x >= 0 && y >= 0 && x < totalRows && y < totalCols
in isValidCoordinate(x, y).
Emm... Quite interesting question. So to find out where the problem(s) may be I'll try to analyze your code a little bit...
You paste stack trace as
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
at Board.getTileAt(Board.java:177)
...
and at the same time the getTileAt()
// returns the tile at (x, y) or null if empty
public Tile getTileAt(int row, int col) {
System.out.println("getTileAt: " + row + ", " + col);
if(isValidCoordinate(row, col))//isValidCoordinate()?
return grid[row][col];
return null;
}
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}
... so the isValidCoordinate method return terms as
x >= 0 && y >= 0 && x < totalCols && y < totalRows
...the method doesn't allow to avoid array out-of-bounds problems; Seems like you put wrong array element indexes.
A. As I can notice, you trying to put a classic math matrix on Java [][] arrays as
public void clearRow(int rowToClear) {
for(int row = rowToClear; row > 0; row--) {
for(int col = 0; col < grid[row].length; col++) {//<-- ?
grid[col][row] = grid[col][row-1];
}
}
}
... and here I must say that you should know that in [][] arrays x,y are backwards and it is y,x because :
y (or classic i) - sub-array index (vertical)
x (or classic j) - sub-array's element index (horizontal)
so you should use array index something this way grid[y][x] or grid[i][j]
As a useful tip, I recommend you to analyze your code for logic errors in this field...
B. According to your app screenshot as
... it seems like the x,y problem takes place here too because you trying to control y (vertical) coordinates but (in real) you control x (horizontal) coordinates only :S It is still because of the row,col instead of a classic Java (col,row or y,x) [][] array index positions.
C. And again concerning to the wrong directions...
...up when I press left, and down when I press right...
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
}
clearCurrPosition();
move();
}
Here I'll try to analyze the event as (you press right but move down)...
OK... according to one of your tasks you need to move by x coordinate (horizontally) but look closer... you make tile[i].getCol()+1 so it is newY and, of course, it moves vertically :S In your case it really moves down because you make increment as y++ ...
public void calcNewPosition(int newX, int newY, int currTile) {
newPositionX[currTile] = newX;
newPositionY[currTile] = newY;
}
public void clearCurrPosition() {
for (int i = 0; i < tile.length; i++) {
currPositionX[i] = tile[i].getX();
currPositionY[i] = tile[i].getY();
board.setTileAt(null, currPositionX[i], currPositionY[i]);
}
}
public void move() {
if (movePieceValid()) {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(newPositionX[i], newPositionY[i]);//<-- !
}
} else {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(currPositionX[i], currPositionY[i]);
}
}
}
...as a conclusion, I may recommend to change code (move right) something this way...
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);
}
clearCurrPosition();
move();
}
I hope my tips will help you to figure out what to look closer. Anyway, if you have some additional information please do comment my answer
Report if that helped you
This is based on x corresponds to columns and y corresponds to rows.
However grid is indexed by [row][col].
TileSscce grid[][] = new TileSscce[totalRows][totalCols]; // 12 => totalRows, 10 => totalCols
public int getWidth() {
return totalCols * tilesize;
}
public int getHeight() {
return totalRows * tilesize;
}
Following changes (based on your initial code - Sscce: - without later edits) will get rid of the exception and allow drawing till bottom of the board.
public void paintComponent(Graphics g) {
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
if (grid[row][col] != null) {
g.setColor(grid[row][col].getColor());
g.fillRect(col * tilesize, row * tilesize, tilesize, tilesize); // changed, check below snippet from fillRect documentation
g.setColor(Color.WHITE);
}
}
}
}
public TileSscce getTileAt(int x, int y) {
if (isValidCoordinate(x, y))
return grid[y][x]; // changed to [y][x] as grid is indexed by [row][col]
return null;
}
public void setTileAt(TileSscce tile, int x, int y) {
if (isValidCoordinate(x, y))
grid[y][x] = tile; // changed to [y][x] as grid is indexed by [row][col]
}
From fillRect documentation.
public abstract void fillRect(int x, int y, int width, int height)
The left and right edges of the rectangle are at x and x + width - 1.
The top and bottom edges are at y and y + height - 1.
This is correct.
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}

Scrolling through JPanel clears its graphics

I am a beginner with Java Programming and I have a problem. I am using a JPanel in a JScrollPane all contained in a JFrame.
I am using paintComponent() method to draw a certain curve and that's done correctly. The problem is that when I scroll through my panel I see that the image is being cleared. I've searched and learned about flickering but I'm not quiet sure yet what it means and whether that's the problem I am having. I did notice also that when repaint is called the image is cleared.
Here is my code, can anyone let me know if I am doing something wrong?
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.QuadCurve2D;
import javax.swing.JFrame;
import java.lang.Math;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class DrawCurve extends JPanel {
class MyAdjustmentListener implements AdjustmentListener {
public MyAdjustmentListener() {
}
public void adjustmentValueChanged(AdjustmentEvent evt) {
setFocusable(true);
jScroll.setFocusable(false);
//repaint();
//revalidate();
}
}
Graphics gr;
Stroke drawingStroke = new BasicStroke(0.5f);
double x;
int y = 0;
static String seq = "AAGTCGACCTGTAGCTAGATCGGATCATAGCTCGATCCAGAGATT";
QuadCurve2D curve;
char s;
int a = 0;
int c = 0;
int g = 0;
int t = 0;
int af = 0;
int cf = 0;
int gf = 0;
int tf = 0;
int h = 0;
int flag = 0;
final JScrollPane jScroll = new JScrollPane();
final JFrame parFrame;
Vector<Double> xrand = new Vector<Double>();
public DrawCurve() {
super();
parFrame = new JFrame();
parFrame.pack();
jScroll.setFocusable(false);
setFocusable(true);
parFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
jScroll.setViewportView(this);
jScroll.getHorizontalScrollBar().addAdjustmentListener(new MyAdjustmentListener());
jScroll.getVerticalScrollBar().addAdjustmentListener(new MyAdjustmentListener());
if (checkSequence(seq) == 0) {
jScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
jScroll.setViewportBorder(new LineBorder(Color.WHITE));
setFocusable(true);
setPreferredSize(new Dimension(1000, 300));
setBackground(Color.magenta);
parFrame.add(jScroll, BorderLayout.CENTER);
parFrame.setSize(600, 320);
parFrame.setVisible(true);
} else {
JOptionPane.showMessageDialog(null, "invalid input", "Warning!", JOptionPane.PLAIN_MESSAGE);
}
}
public int checkSequence(String sequ) {
int f = 0;
for (int i = 0; i < sequ.length(); i++) {
if (sequ.charAt(i) != "A".charAt(0) && sequ.charAt(i) != "C".charAt(0) && sequ.charAt(i) != "G".charAt(0) && sequ.charAt(i) != "T".charAt(0)) {
f = 1;
break;
}
xrand.add(Math.random() * 300 - 200);
}
return f;
}
public void paintComponent(Graphics gr) {
super.paintComponent(gr);
Graphics2D ga = (Graphics2D) gr;
System.out.println("in");
ga.setStroke(drawingStroke);
for (int i = 0; i < seq.length(); i++) {
s = seq.charAt(i);
if (s == "A".charAt(0)) {
ga.setColor(Color.RED);
a = 1;
af = 1;
cf = 0;
gf = 0;
tf = 0;
h = -1;
} else if (s == "C".charAt(0)) {
ga.setColor(Color.YELLOW);
c = 1;
af = 0;
cf = 1;
gf = 0;
tf = 0;
h = -3;
} else if (s == "G".charAt(0)) {
ga.setColor(Color.GREEN);
g = 1;
af = 0;
cf = 0;
gf = 1;
tf = 0;
h = 1;
} else if (s == "T".charAt(0)) {
ga.setColor(Color.BLUE);
t = 1;
af = 0;
cf = 0;
gf = 0;
tf = 1;
h = 3;
} else {
af = 0;
cf = 0;
gf = 0;
tf = 0;
h = 0;
}
x = Math.random() * 300 - 200;
curve = new QuadCurve2D.Double(y, 250 + h, y + 10, xrand.elementAt(i), y + 20, 250 + h);
ga.draw(curve);
if (a == 1 && af == 0) {
ga.setColor(Color.RED);
h = -1;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
if (c == 1 && cf == 0) {
ga.setColor(Color.YELLOW);
h = -3;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
if (g == 1 && gf == 0) {
ga.setColor(Color.GREEN);
h = 1;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
if (t == 1 && tf == 0) {
ga.setColor(Color.BLUE);
h = 3;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
y += 20;
}
}
public static void main(String[] args) {
final DrawCurve panel = new DrawCurve();
}
}
I figured out what's wrong with that code, it turned out that in my loop I forgot to initialize where the curve should start every time the paintComponent is called. Adding y=0; at the start of paintComponent would solve it

Categories

Resources