I am currently working on a tic tac toe program for an assignment. The issue I am having is when I count my player (either the 'X' player or the 'Y' player), it seems to be counting both players as the same. For instance, after the third play, it sees three plays and counts it as a winner, even though only two plays of one player and one play of the other have been completed.
public class TicTacToeApp
{
public static void main(String[] args)
{
TicTacToeView view = new TicTacToeView();
TicTacToeModel model = new TicTacToeModel();
TicTacToeViewController controller = new
TicTacToeViewController(view,model);
view.setVisible(true);
}
}
public class TicTacToeModel
{
double xpos,ypos,xr,yr;
char[][] position = {{' ',' ',' '},
{' ',' ',' '},
{' ',' ',' '}};
public void computePos(int row, int col, int h, int w)
{
xpos=(col+0.5)*w/3.0;
ypos=(row+0.5)*h/3.0;
xr=w/8.0;
yr=h/8.0;
}
public boolean isEmpty(int xpos, int ypos)
{
if(position[xpos][ypos]==' ')
return true;
return false;
}
public void placeO(int xpos, int ypos)
{
position[xpos][ypos]='O';
}
public int putX(){
for(int i=0; i<3;i++){
for(int j = 0;j<3;j++) {
if(position[i][j]==' ') {
position[i][j]='X';
return 0;
}
}
}
return -1; //some error occurred. This is odd. No cells were free.
}
public void printBoard(){
for(int i=0;i<3;i++)
System.out.println(position[i][0]+"|"+position[i][1]+"|"+position[i][2]);
}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.ArrayList;
public class TicTacToeView extends JFrame{
private JButton oButton, xButton;
public JPanel board;
public ArrayList<Shape> shapes;
public TicTacToeView(){
shapes = new ArrayList<Shape>();
JPanel topPanel=new JPanel();
topPanel.setLayout(new FlowLayout());
add(topPanel, BorderLayout.NORTH);
add(board=new Board(), BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
}
private class Board extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w=getWidth();
int h=getHeight();
Graphics2D g2d = (Graphics2D) g;
// Draw the grid
g2d.setPaint(Color.WHITE);
g2d.fill(new Rectangle2D.Double(0, 0, w, h));
g2d.setPaint(Color.BLACK);
g2d.setStroke(new BasicStroke(4));
g2d.draw(new Line2D.Double(0, h/3, w, h/3));
g2d.draw(new Line2D.Double(0, h*2/3, w, h*2/3));
g2d.draw(new Line2D.Double(w/3, 0, w/3, h));
g2d.draw(new Line2D.Double(w*2/3, 0, w*2/3, h));
//draw circles and xs by visiting elements in the array List.
for(Shape shape : shapes){
g2d.setPaint(Color.BLUE);
g2d.draw(shape);
}
}
}
public void addMouseListener(MouseListener ml){
board.addMouseListener(ml);
}
public static void main(String[] args) {
TicTacToeView ttv = new TicTacToeView();
ttv.setVisible(true);
}
}
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.Graphics2D;
import java.awt.Color;
import javax.swing.JOptionPane;
public class TicTacToeViewController implements MouseListener{
TicTacToeView view;
TicTacToeModel model;
Color oColor=Color.BLUE, xColor=Color.RED;
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public TicTacToeViewController(TicTacToeView view, TicTacToeModel model) {
this.view = view;
this.model = model;
view.addMouseListener(this);
}
public void play(int xpos, int ypos) {
if (model.isEmpty(xpos,ypos)) {
model.placeO(xpos, ypos);
drawBoard();
view.repaint();
model.putX();
if(didWin("X")){
JOptionPane.showMessageDialog(null,"X Wins","Winner", JOptionPane.INFORMATION_MESSAGE);
}
if(didWin("O"))
JOptionPane.showMessageDialog(null,"O Wins","Winner",JOptionPane.INFORMATION_MESSAGE);
}
}
public void drawBoard() {
Graphics2D g2d = (Graphics2D)view.board.getGraphics();
for (int i=0; i<3; i++)
for(int j=0; j<3;j++) {
model.computePos(i,j,view.board.getHeight(),view.board.getWidth());
double xpos = model.xpos;
double xr = model.xr;
double ypos = model.ypos;
double yr = model.yr;
if (model.position[i][j]=='O') {
view.shapes.add(new Ellipse2D.Double(xpos-xr, ypos-yr, xr*2, yr*2));
}
else if (model.position[i][j]=='X') {
view.shapes.add(new Line2D.Double(xpos-xr, ypos-yr, xpos+xr, ypos+yr));
view.shapes.add(new Line2D.Double(xpos-xr, ypos+yr, xpos+xr, ypos-yr));
}
System.out.println("Coords: xpos:"+xpos+", ypos:"+ypos+", xr"+xr+", yr"+yr);
}
}
public void mouseClicked(MouseEvent e) {
int ypos=e.getX()*3/view.getWidth();
int xpos=e.getY()*3/view.getHeight();
//System.out.println("Play "+xpos+","+ypos);
play(xpos,ypos);
}
public boolean didWin(char player) {
int count = 0;
int count2 = 0;
for(int i = 0; i<3; i++)
{
for(int j= 0; j<3; j++)
{
if(model.position[i][j]==player)
{
count++;
if(count ==2)
return true;
}
}
count=0;
}
for(int k = 0; k<3; k++)
{
for(int l= 0; l<3; l++)
{
if(model.position[l][k]==player)
{
count2++;
if(count2 ==2)
return true;
}
}
count2=0;
}
if(model.position[0][0]==player && model.position[1][1]==player && model.position[2][2]==player)
return true;
if(model.position[0][2]==player && model.position[1][1]==player && model.position[2][0]==player)
return true;
return false;
}
}
My question is if someone can look over my logic and see why the game only allows three moves. In other words, the O goes, the X goes, then the O goes, and the game announces a winner. Also, I am not looking for a code answer, but rather which part I should inspect to fix my code.
It sounds like the error is in the didWin () method if everything else works.
I think when you call the didWin I only used one ' ' don't think it really changes anything tho
For starters, you want your count to see if it's == 3 or at least > 2, not == 2.
Related
So my university uses the book Java programming from problem analysis to program design by DS Malik(ISBN: 978-1-111-53053-2) and in one of the examples I copied the code word for word. It runs but doesn't work the way its supposed too. What you're supposed to do is be able to click and drag circles that populate the screen in an applet. If anyone is interested in the programming example its 12-10. I have provided the code from eclipse. Any and all help is appreciated.
import javax.swing.*;
import java.awt.event.*;
import java.applet.*;
import java.awt.*;
public class FreeDrawApplet extends JApplet implements MouseMotionListener
{
//instance variables
ColorCircle[] myGraph;
final int NUM_CIRCLES = 7;
final int WIDTH = 400;
final int HEIGHT = 400;
public class ColorCircle
{
private int x;
private int y;
public void setx(int iNewX)
{
x = iNewX;
}
public void sety(int iNewY)
{
x = iNewY;
}
public void paint (Graphics g)
{
g.fillOval(x-10, y-10, 20, 20);
}
public boolean selected(int iXcoord, int iYcoord)
{
if ((iXcoord >= x-10) && (iXcoord <= x+10) && (iYcoord >= y-10) && (iYcoord <= y+10))
return true;
else
return false;
}
}//end of public class circle
public void init ()
{
addMouseMotionListener(this);
myGraph = new ColorCircle[NUM_CIRCLES];
for(int i = 0; i < NUM_CIRCLES; i++)
{
ColorCircle myVertex = new ColorCircle();
myVertex.setx((int)(Math.random() * (WIDTH-50)));
myVertex.sety((int)(Math.random() * (HEIGHT-100)));
myGraph[i] = myVertex;
}
JOptionPane.showMessageDialog(null, "Try to drag any one of the colored circles ", "Information", JOptionPane.PLAIN_MESSAGE);
}//end of method
public void paint(Graphics g)
{
Color[] myColor = {Color.black, Color.red, Color.blue, Color.green, Color.cyan, Color.orange, Color.yellow};
if(NUM_CIRCLES > 0)
for(int i =0; i < NUM_CIRCLES; i++)
{
g.setColor(myColor[i]);
myGraph[i].paint(g);
}
}//end of paint method
public void mouseDragged(MouseEvent event)
{
int iX = event.getX();
int iY = event.getY();
for(int i = 0; i < NUM_CIRCLES; i++)
{
if(myGraph[i].selected(iX, iY))
{
myGraph[i].setx(iX);
myGraph[i].sety(iY);
break;
}
}
repaint();
}
public void mouseMoved(MouseEvent p1)
{
}
}
I have a very strange problem.
I am making a simple 2d platformer using Java.
The collision detection with the player and a platform, doesn't work.
But the strange thing is, when I print something to the screen to see if the collision if-statement is executed, the collision works o_O
Maybe it's a bit confusing, please see my code.
The Main class(which is good I think):
import javax.swing.*;
public class Main extends JFrame{
private static final long serialVersionUID = 1L;
GameClass gc = new GameClass();
public Main(){
setSize(gc.WIDTH,gc.HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Flying GoatZ!");
add(new GameClass());
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
GameClass class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
public class GameClass extends JPanel implements ActionListener, KeyListener, MouseListener{
//OBJECTS
Text text = new Text();
openImages open_img = new openImages();
Random ran = new Random();
//VARIABLES
static final long serialVersionUID = 1L;
final int WIDTH = 800;
final int HEIGHT = 600;
int goatx = WIDTH/2;
int goaty = 350;
int goatspeed = 0;
int fallspeed = 15;
int maxy = 150;
boolean up = false;
boolean flying = true;
ArrayList<Integer> xes = new ArrayList<Integer>();
ArrayList<Integer> yes = new ArrayList<Integer>();
//FPS SETTER AND KEYLISTENERS
public GameClass(){
Timer time = new Timer(15, this);
time.start();
this.addKeyListener(this);
this.setFocusable(true);
open_img.openImage();
}
public void update(){
Collision();
goatx += goatspeed;
if(up){
if(goaty > maxy){
goaty -= 5;
}else{
up = false;
}
}else
if(goaty < 350)
goaty += fallspeed;
}
public void print(String msg){
System.out.println(msg);
}
public void platformDrawing(Graphics g,int x,int y,int x1,int y1, int x2, int y2){
g.setColor(Color.RED);
g.drawImage(open_img.block,x, y, null);
g.drawImage(open_img.block,x1, y1, null);
g.drawImage(open_img.block,x2, y2, null);
xes.addAll(Arrays.asList(x,x1,x2));
yes.addAll(Arrays.asList(y,y1,y2));
}
//HERE IS THE COLLISION METHOD(I NEED THE PLAYER TO STAND STILL WHEN IT IS ON THE PLATFORM.
public void Collision(){
for(int x : xes){
for(int y : yes){
if( ( (goatx > x-20) && (goatx < (x + 150)) ) && ( (goaty+open_img.goat.getHeight(null)) <= y ) ){
//print("TEST");
fallspeed = 0;
}else{
fallspeed = 10;
}
}
}
}
//ALL TEH DRAWING
public void paintComponent(Graphics g){
//MAP
g.setColor(Color.CYAN);
g.fillRect(0,0,WIDTH,HEIGHT);
g.setColor(Color.ORANGE);
g.fillRect(0, HEIGHT-100, WIDTH, 100);
g.setColor(Color.GREEN);
g.fillRect(0, HEIGHT-125, WIDTH, 25);
//PLAYER & PLATFORMS
platformDrawing(g,50,350,300,350,600,350);
g.drawImage(open_img.goat, goatx, goaty, null);
g.dispose();
}
//THIS IS EXECUTED EVERYTIME
public void actionPerformed(ActionEvent e){
update();
repaint();
}
//KEY DETECTION
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
goatspeed = -5;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
goatspeed = 5;
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
if(flying){
flying = false;
up = true;
}
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
goatspeed = 0;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
goatspeed = 0;
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
flying = true;
}
}
//SOME STUFF THAT YOU HAVE TO IGNORE LEL
public void keyTyped(KeyEvent e){}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
}
I don't understand why a print statement can make the difference...
Any help is appreaciated, thanks!
Oh, and sorry for bad English or unclear question.
I am writing a code of game bean machine(Galton box), its mechanism that one ball fall and move randomly until it get to one of the slots (randomly) and then another ball comes doing the same thing and so on, the problem is that all balls fall at the same time which something I do not want, I want each ball to fall when the current one finishes its travel..can anyone helps me ! Thanks..
here is the code:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.Scanner;
import java.lang.Iterable;
import javax.swing.*;
public class BallPanel extends JPanel {
int x=1, y=1;
Collection <Ball> ball;
public static void main(String [] args){
// create the list
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame= new JFrame("Bean game");
frame.add(new BallPanel());
frame.setSize(300,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
public BallPanel() {
JPanel panel = new JPanel();
ball=new ArrayList<>();
for(int i=1;i<=4;i++){
ball.add(new Ball(x,y));
x++;
y++;
}
Timer timer = new Timer(400, new ActionListener()
{
public void actionPerformed(ActionEvent e) {
for (Ball b: ball) {
b.move();repaint();
}
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int raduis=10;
int i=0;
int width=(getWidth()/8);
int space=(getWidth()-8*30)/2;
g.setColor(Color.BLACK);
for(i=0;i<=8;i++){
g.drawLine(space+(30*i),getHeight()-5*(raduis) ,space+(30*i) ,getHeight() );
if(i!=0 && i!=8)
g.fillOval(space+(30*i)-5, getHeight()-5*(raduis)-5, 10, 10);
if(i==0){
g.drawLine(space,getHeight()-5*(raduis) , space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
g.drawLine(space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)-(raduis/2)-15 , getHeight()/2-8*8);//vertical line
}
if(i==8){
g.drawLine(space+(30*i), getHeight()-5*(raduis), space+((8)*15)+(raduis/2)+15, getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
g.drawLine(space+((8)*15)+(raduis/2)+15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)+(raduis/2)+15 , getHeight()/2-8*8);//vertical line
}
}
int o=1;
for(i=1;i<=8-2;i++){
int k=2;
for(int j=i;j<=8-2;j++){
g.fillOval(space+((i+k)*15)-raduis/2, getHeight()-(5*raduis)-(30*o)-raduis/2, raduis, raduis);
k=k+2;
}o++;
}
for (Ball b : ball) {
b.draw(g);
}
}
public class Ball {
Random rand=new Random();
private int n;
private int raduis = 10;
private int moveRaduis=12;
private int L = 0;
private int R = 0;
private int D = 0;
int x, y;
public Ball(int x, int y){
this.x=x;
this.y=y;
}
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillOval(getWidth()/2 -raduis/2 + R + L, 0 + D , moveRaduis, moveRaduis);
}
public void move() {
n=1+rand.nextInt(100);
if(n<=51){
D+=15;
if(D<=(getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2))
L=0;
else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
{
D+=15;
L-=15;
}
else if(D>=getHeight()-5*(raduis))
{
if(D==31*15)D-=15;
D=D;
}
}
else if (n>=51 && n<=100){
D+=15;
if(D<=getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2)
R=0;
else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
{
D+=15;
R+=15;
}
else if(D>=getHeight()-5*(raduis)){
if(D==31*15)D-=15;
D=D;
}
}
}
}
}
So, your movement code moves all the balls on each iteration, what you need to do is have an "active" ball, for example...
private Ball activeBall;
Timer timer = new Timer(400, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (activeBall != null && activeBall.hasCompleted()) {
activeBall = null;
}
if (activeBall == null && ball.size() > 0) {
activeBall = ball.remove(0);
}
if (activeBall != null) {
activeBall.move();
repaint();
}
}
});
You'll need to add in some kind of check to determine the ball has completed it's run though
I am attempting to create a game of life simulator:
My code basically consists of a JFrame holding a grid of JPanels, and a corresponding sized 2d boolean array where each JPanel is specifically an instance of a class that extends JPanel
This class:
initializes the JPAnel to a set Size, makes it opaque, sets its background color (this all works) and adds a mouseListener to it which changes the color of the JPanel based on the value of the 2d boolean array in corresponding location before switching the value of the array.
I also pass the boolean array as a reference so that way each tile is carrying the same boolean array and they all can flip its values.
For some reason, the only background color the JPanel holds is the one I set during initialization. After that the JPanel does not change its background color, despite the mouseListener registering that it has been pressed, and furthermore despite the successful call of a repaint() method. Can someone please explain what on earth is going on? I don't have anything to go off of for debugging since everything seems to be right in place.
(the individual Conway Tile)
package conweezy;
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
public class TheTile extends JPanel implements MouseListener
{
boolean[][] thearray;
int xindex;
int yindex;
public TheTile(double width, double height, int xloc, int yloc, boolean[][] inputworld, int i, int j)
{
super();
setSize((int)width, (int)height); setLocation(xloc, yloc);
thearray = inputworld; xindex = i; yindex = j; setLayout(null);
setOpaque(true);
if(!thearray[xindex][yindex])
{
setBackground(Color.BLACK);
}
if(thearray[xindex][yindex])
{
setBackground(Color.WHITE);
}
setVisible(true);
//addMouseListener(this);
}
public void mousePressed(MouseEvent e)
{
if(!thearray[xindex][yindex])
{
setBackground(Color.WHITE);
System.out.println(xindex + " " + yindex);
repaint();
}
if(!thearray[xindex][yindex])
{
setBackground(Color.BLACK);
repaint();
}
thearray[xindex][yindex] = !thearray[xindex][yindex];
repaint();
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
.
(The Conway Grid):
package conweezy;
import java.awt.Event.*;
import java.awt.event.*;
import javax.swing.*;
public class TheUniverseFrame extends JFrame implements ActionListener
{
public static boolean[][] universalframe;
public TheTile[][] universaltiles;
boolean threadstate = false;
TheUniverseFrame(double xsize, double ysize, int tilexcount, int tileycount)
{
//set constants
setTitle("Welcome to the Game of Life: Datatronic Existence");
universalframe = new boolean[tilexcount][tileycount];
universaltiles = new TheTile[tilexcount][tileycount];
setSize((int)xsize+100, (int)ysize);
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//initialize tiles and boolean array
int i = 0;
int j;
setVisible(true);
while(i < tilexcount)
{
j = 0;
while(j < tileycount)
{
universalframe[i][j] = false;
universaltiles[i][j] = new TheTile(xsize/((double)tilexcount), //tile width
ysize/((double)tileycount), //tile height
(int)(xsize/((double)tilexcount))*i, //tile x position
(int)(ysize/((double)tileycount))*j, //tile y position
universalframe, //boolean array
i, j); //tile position on array
try
{
Thread.sleep(0);
}
catch(InterruptedException e)
{
}
//universaltiles[i][j].addMouseListener(universaltiles[i][j]);
add(universaltiles[i][j]);
repaint();
j++;
}
i++;
}
setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
}
}
The Main Class:
package conweezy;
public class Conweezy
{
public static void main(String[] args)
{
TheUniverseFrame theGame = new TheUniverseFrame(500,500,20,20);
}
}
Here's a working variation of your example that toggles a pixel's background color when clicked. Note,
Use invokeLater() to run on the EDT.
Remember to pack() the enclosing frame.
Call setVisible() once.
Override getPreferredSize() to establish a tile's size.
As tested:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;
public class Conweezy {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TheUniverseFrame theGame = new TheUniverseFrame(500, 500, 20, 20);
}
});
}
private static class TheUniverseFrame extends JFrame {
public static boolean[][] universalframe;
public TheTile[][] universaltiles;
boolean threadstate = false;
TheUniverseFrame(double xsize, double ysize, int tilexcount, int tileycount) {
//set constants
setTitle("Welcome to the Game of Life: Datatronic Existence");
universalframe = new boolean[tilexcount][tileycount];
universaltiles = new TheTile[tilexcount][tileycount];
setLayout(new GridLayout(tilexcount, tileycount));
setDefaultCloseOperation(EXIT_ON_CLOSE);
//initialize tiles and boolean array
int i = 0;
int j;
while (i < tilexcount) {
j = 0;
while (j < tileycount) {
universalframe[i][j] = false;
universaltiles[i][j] = new TheTile(xsize / ((double) tilexcount), //tile width
ysize / ((double) tileycount), //tile height
(int) (xsize / ((double) tilexcount)) * i, //tile x position
(int) (ysize / ((double) tileycount)) * j, //tile y position
universalframe, //boolean array
i, j); //tile position on array
add(universaltiles[i][j]);
j++;
}
i++;
}
pack();
setVisible(true);
}
}
private static class TheTile extends JPanel {
boolean[][] thearray;
int xindex;
int yindex;
#Override
public Dimension getPreferredSize() {
return new Dimension(25, 25);
}
public TheTile(double width, double height, int xloc, int yloc, boolean[][] inputworld, int i, int j) {
thearray = inputworld;
xindex = i;
yindex = j;
setOpaque(true);
setBackground(Color.BLACK);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
thearray[xindex][yindex] = !thearray[xindex][yindex];
if (thearray[xindex][yindex]) {
setBackground(Color.WHITE);
} else {
setBackground(Color.BLACK);
}
repaint();
System.out.println(xindex + " " + yindex);
}
});
}
}
}
Hi, I'm developing a snake game. To create the snake I'm using ArrayList. While moving the snake I'm getting the following error: "java.lang.IndexOutOfBoundsException: Index: 3, Size: 3". Below is my program. In Snake.update() method I have problem.
Game.java:
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Game extends JFrame {
public Game(){
add(new GamePanel());
setTitle("Game Test3");
setVisible(true);
setAlwaysOnTop(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
public static void main(String[] args) {
new Game();
}
}
GamePanel.java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class GamePanel extends JPanel implements Runnable, KeyListener {
public static int width = 300;
public static int height = 400;
private Thread thread;
private Image image;
private Graphics2D g;
private Food food;
private Snake snake;
public GamePanel() {
setPreferredSize(new Dimension(width, height));
setFocusable(true);
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
addKeyListener(this);
}
public void run() {
image = createImage(width, height);
g = (Graphics2D) image.getGraphics();
RenderingHints reneringHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHints(reneringHints);
food = new Food();
snake = new Snake();
while (true) {
gameRender();
gameUpdate();
gameDraw();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void gameDraw() {
Graphics2D g2 = (Graphics2D) getGraphics();
g2.drawImage(image, 0, 0, this);
g2.dispose();
}
private void gameRender() {
g.setColor(Color.black);
g.fillRect(0, 0, width, height);
// food drawing
food.draw(g);
// snake drawing
snake.draw(g);
}
private void gameUpdate() {
food.update();
snake.update();
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
snake.setLeft(true);
}
if (key == KeyEvent.VK_RIGHT) {
snake.setRight(true);
}
if (key == KeyEvent.VK_UP) {
snake.setUp(true);
}
if (key == KeyEvent.VK_DOWN) {
snake.setDown(true);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
snake.setLeft(false);
}
if (key == KeyEvent.VK_RIGHT) {
snake.setRight(false);
}
if (key == KeyEvent.VK_UP) {
snake.setUp(false);
}
if (key == KeyEvent.VK_DOWN) {
snake.setDown(false);
}
}
public void keyTyped(KeyEvent e) {
}
}
//snake body
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;
public class Snake {
private int x;
private int y;
private int r;
int body;
Rectangle rectangle;
ArrayList<Rectangle> rc = new ArrayList<Rectangle>();
private boolean left;
private boolean right;
private boolean up;
private boolean down;
public Snake() {
x = 150;
y = 150;
r = 4;
body = 3;
for (int i = 0; i < body; i++) {
rc.add(new Rectangle(x - i * r * 3, y, r * 3, r * 3));
}
}
public void draw(Graphics2D g) {
for (int i = 0; i < body; i++) {
if (i == 0) {
g.setColor(Color.red);
} else {
g.setColor(Color.green);
}
g.fillOval(rc.get(i).x, rc.get(i).y, rc.get(i).width,
rc.get(i).height);
}
}
public void update() {
for (int i = body; i > 0; i--) {
rc.set(i, rc.get(i - 1));
}
if (left) {
rc.get(0).x -= 1;
System.out.println("vbnv");
}
if (right) {
rc.get(0).x += 1;
}
if (up) {
rc.get(0).y -= 1;
}
if (down) {
rc.get(0).y += 1;
}
}
public void setLeft(boolean b) {
left = b;
}
public void setRight(boolean b) {
right = b;
}
public void setUp(boolean b) {
up = b;
}
public void setDown(boolean b) {
down = b;
}
}
Without reading the code I can tell that somewhere you are trying to get non-existent element. Read the message of exception, it tells you that your ArrayList consist of three elements (which means that the last element has index of 2) while you try to get the element with index of 3.
Update: yes, the problem is here:
for (int i = body; i > 0; i--) {
rc.set(i, rc.get(i - 1));
}
body equals to 3, and rc after the constructor invocation has the size of 3. set method replaces already existing element with the specified index (see the documentation), but element with index of 3 doesn't exist. That's the cause of an exception.
Your problem is in this loop:
for (int i = body; i > 0; i--) {
rc.set(i, rc.get(i - 1));
}
During the first iteration around this loop, you will be calling:
rc.set(3, <someValue>);
3 is not a valid index in a list of length 3. The largest valid index is 2.
for (int i = body; i > 0; i--)
In this for, i is assigned with the value of body(which is 3) and it looks like your ArrayList rc has only 3 elements in it. Therefore, when you try to access the index 3 using rc.set(3, something), its giving the IndexOutOfBoundsException.
Always remember, whether it is Arrays or ArrayList, the max possible index accessible in them is always array.length - 1 and ArrayList.size() - 1.