7 Replies - 8031 Views - Last Post: 21 February 2011 - 11:01 AM Rate Topic: -----

#1 finalfantasyfreak15  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 13
  • Joined: 19-February 11

snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 09:29 PM

Hi,

I'm trying to make a simple snake game applet in Java, but I'm having trouble storing coordinates in my arraylist. I have two arraylists; one for x and one for y. Every time the snake eats an apple, I add the x and y coordinate of the snake to the lists. However, since I'm using global variables to send into the lists, the values of the indexed locations are constantly changing; also, it will save the same coordinates for every piece of the snake's body in every indexed location. Anyone have any ideas in how to store the coordinates in the list so they will be different coordinates? I've pasted my code below in case it makes more sense to look at that.

package assignment04;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JApplet;

/**
 * A simple snake game.  The program opens with a welcome message and after
 * the user clicks the screen with the mouse, it will initiate the game.
 * The snake will start moving immediately to the left, but when if the arrow
 * keys are pressed then the direction of the snake will change.  If the
 * snake eats the red apple, then snake will grow and a new apple will be
 * generated in a new random location.  If the snake crashes into itself or
 * the walls then the animation stops and a game over message is displayed.
 * The user can then press Enter to exit the program.
 *
 *
 */
public class snake extends JApplet implements MouseListener, KeyListener, Runnable, ComponentListener
{
	//Holds the coordinates for the snake and the apple.
	int snakeX, snakeY, appleX, appleY;
	
	//Holds the values for the width and height of the snake.
	int snakeW, snakeH;
	
	//Holds the value of the direction (0, 1, 2, 3)
	int dir;
	
	//Keeps track of the score.
	int score;
	
	//Keeps track of how many pieces there are in the snake's body.
	int pieces;
	
	//Used to determine if the mouse is clicked to clear away the welcome
	//message to initiate the game.
	boolean notClicked = true;
	
	//Used to update the loop for the thread if the game is still running.
	boolean animating = true;
	
	//Holds the x coordinate of each piece of the snake.
	ArrayList xList = new ArrayList();
	//Holds the y coordinate of each piece of the snake.
	ArrayList yList = new ArrayList();
	
	//the surface we're going to draw to
	private Image m_RenderTarget = null;
	//the graphics object belonging to the surface we'll draw to
	private Graphics m_BufferedGraphics = null;	
		
	public void init() 
	{
		this.addMouseListener(this);
		this.addKeyListener(this);
		this.setFocusable(true);
		
		//making the window a little bigger than the default
		setSize(600,600);
		//this will notify us when the component is resized (in our case it's the applet window)
		addComponentListener(this);
		//calling this here will create the image to paint to and the buffered graphics object
		componentResized(null);
		
		Thread t = new Thread(this);
		t.start();

		snakeX = 400;
		snakeY = 400;
		
		appleX = 200;
		appleY = 100;
		
		snakeW = 10;
		snakeH = 10;
		
		dir = 0;
		
		score = 0;
		
		//Has an initial value of 1 because the first piece will be the head.
		pieces = 1;
			
	}

	/**
	 * Used to prevent flickering in the program.  Calls drawAll which calls
	 * the other drawing methods.
	 */
	public void paint(Graphics g) 
	{
		//draw some stuff to the buffered graphics object
		drawAll(m_BufferedGraphics);

		//this paints the image we've been drawing to, to the screen
		g.drawImage(m_RenderTarget, 0, 0, this);
	}
	
	/**
	 * Clears the background and calls the other drawing methods for the
	 * welcome message, the apple, and the snake.
	 * 
	 * @param g
	 */
	public void drawAll (Graphics g)
	{
		// Clear the background
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		
		//Displays the welcome message until the user clicks the screen.
		//Then the welcome message is cleared away and the game begins.
		if (notClicked)
			this.welcomeMessage(g);
		
		//Once the user clicks, these methods are called to draw the snake
		//and apple.
		if (!notClicked)
		{
			this.snakePos(g);
			this.apple(g);
		}
		//Checks to see what the coordinates are for the apple and snake
		//to see if they are on the same 'grid' system.
//		System.out.println(appleX + " " + appleY);
//		System.out.println(snakeX + " " + snakeY);
		System.out.println("Snake has this many pieces " + pieces);
		System.out.println("x's are " + xList);
		System.out.println("y's are " + yList);
		System.out.println("size x is " + xList.size());
		System.out.println("size  y is " + yList.size());
	}
	
	/**
	 * First drawn to the screen.  Will clear away when the user clicks
	 * with the mouse.
	 * 
	 * @param g
	 */
	public void welcomeMessage (Graphics g)
	{
		// Display the welcome message and instructions
		g.setColor(Color.WHITE);
		g.drawString("Welcome to Snake!", this.getWidth() / 3,
				this.getHeight() / 2);
		g.drawString("Use the arrow keys to move the snake.",
				this.getWidth() / 3, this.getHeight() / 2 + 15);
		g.drawString("Eat the red apples to grow.", this.getWidth() / 3,
				this.getHeight() / 2 + 30);
		g.drawString("Don't run into the walls or yourself or the game ends",
				this.getWidth() / 3, this.getHeight() / 2 + 45);
		g.drawString("When you are ready play click with the mouse",
				this.getWidth() / 3, this.getHeight() / 2 + 60);
	}
	
	/**
	 * Draws the snake's head.  Calls the method for the snake's body if
	 * the x and y coordinates of the snake an apple are the same.  Also
	 * checks to see if the snake has crashed into the wall.  If it has then
	 * the game over method is called.
	 * 
	 * @param g
	 */
	public void drawSnake (Graphics g, int x, int y) 
	{
		// Draw the snake.
		g.setColor(Color.GREEN);
		
		g.fillRect(x, y, snakeW, snakeH);
	
		//Checks for wall crashings.
		if (snakeX < 0)
			gameOverMessage(g);
		if (snakeX > this.getWidth())
			gameOverMessage(g);
		if (snakeY < 0)
			gameOverMessage(g);
		if (snakeY > this.getHeight())
			gameOverMessage(g);
	}
	
	/**
	 * Get's the coordinates for x and y of each piece of the snake.  These
	 * values are stored in the arraylists xList and yList.  Then these
	 * values are sent to drawSnake as parameters to update how many pieces
	 * need to be drawn and where they need to be drawn.
	 * 
	 */
	public void snakePos (Graphics g)
	{		
		//These are the initial coordinates for the head.  They will be fed
		//into the arraylist to get it started with a size of 1.
		int initialX = 400;
		int initialY = 400;

		//If the size of the lists are 0 then it will add the initial values
		//once to get the list started.  Afterwards, any changes to the x or
		//y coordinates will be handled by the if statement below.
		if (xList.size() == 0)
			xList.add(initialX);
		if (yList.size() == 0)
			yList.add(initialY);
		
		//Store the location at the index equal to k which is the current index
		//that is being changed.  For each piece it will check what direction it is
		//in and then store the appropriate coordinates for that piece.
		for (int i = 0; i < pieces; i++)
		{
			if (dir == 0)
				for (int k = xList.size()-1; k >= 0; k--)
				{
					xList.set(i, snakeX - 10);
					yList.set(i, snakeY);
				}
			if (dir == 1)
				for (int k = xList.size()-1; k >= 0; k--)
				{
					xList.set(i, snakeX + 10);
					yList.set(i, snakeY);
				}
			if (dir == 2)
				for (int k = yList.size()-1; k >= 0; k--)
				{
					xList.set(i, snakeX);
					yList.set(i, snakeY - 10);
				}
			if (dir == 3)
				for (int k = yList.size()-1; k >= 0; k--)
				{
					xList.set(i, snakeX);
					yList.set(i, snakeY + 10);
				}
		}
		for (int i = 0; i < pieces; i++)
		{
			int x = (Integer) xList.get(i);
			int y = (Integer) yList.get(i);

			drawSnake(g, x, y);	
		}
		
	}
	
	/**
	 * Draws the apple.  When the x and y coordinates are the same, then the
	 * apple will be redrawn in a new location with randomly generated
	 * coordinates.  This method calls the applePos method which will
	 * generate a new location for the apple.
	 * 
	 * @param g
	 */
	public void apple (Graphics g)
	{
		//Generates a random coordinate for the apple when it gets eaten.
		g.setColor(Color.RED);
		g.fillOval(appleX, appleY, 10, 10);
		applePos(g);
	}
	
	/**
	 * Generates a new x and y coordinate for the apple if the snake's
	 * location and apple's location are the same.  If new random location
	 * exceeds a certain range then it will regenerate a new location which
	 * fits the window size. It also updates the score count.
	 * 
	 */
	Random r = new Random();
	public void applePos (Graphics g)
	{
		if (snakeX == appleX && snakeY == appleY)
		{
			//Update the score.
			score++;
			
			//Update the number of snake body pieces there are.
			pieces++;
			
			//Add the coordinates for the new piece every time the x and y
			//for the snake and apple are the same.
			xList.add(snakeX);
			yList.add(snakeY);
			
			appleX = r.nextInt(this.getWidth())*10;
			appleY = r.nextInt(this.getHeight())*10;
			
			//If the new apple coordinates exceed the window, then it will
			//reselect better coordinates.
			while (appleX > 700 || appleY > 700)
			{
				appleX = r.nextInt(50)*10;
				appleY = r.nextInt(50)*10;
			}
		}
		repaint();
	}

	/**
	 * Displayed if the snake crashes into the wall or itself.  Will display
	 * that the game is over, the score, and how to exit the program (the
	 * user will press Enter).
	 * 
	 * @param g
	 */
	public void gameOverMessage (Graphics g)
	{
		animating = false;
		g.setColor(Color.WHITE);
		g.drawString("Game Over", this.getWidth()/3, this.getHeight()/3);
		g.drawString("Your score was " + score, this.getWidth()/3, 
				this.getHeight()/3 + 15);
		g.drawString("Hit Enter to exit", this.getWidth()/3, 
				this.getHeight()/3 + 30);
	}
	
	public void mouseClicked(MouseEvent e) 
	{
		// Initiates the game when the user clicks the mouse

		// Confirms that click events are recognized by the applet.
		//System.out.println("mouse clicked");
		
		//Gets rid of the welcome message.
		if (e.getButton() == MouseEvent.BUTTON1)
		{
			notClicked = false;
			repaint();
		}
	}

	/**
	 *Moves the snake continuously in one direction unless the key events
	 *reset the value of the dir variable which holds the value 0-3 that
	 *is sent to the moveSnake method for the direction variable to set the
	 *direction.
	 *
	 * @param direction
	 */
	public void moveSnake(int direction)
	{
		if (direction == 0)
			snakeX -= 10;
		if (direction == 1)
			snakeX += 10;
		if (direction == 2)
			snakeY -= 10;
		if (direction == 3)
			snakeY += 10;
		
		repaint();
	}
	
	// Changes the snake's direction.
	public void keyPressed(KeyEvent k) 
	{
		int key = k.getKeyCode();
		
		if (key == KeyEvent.VK_LEFT) 
		{
			//System.out.println("left pressed");
			dir = 0;
			moveSnake(dir);
		}
		if (key == KeyEvent.VK_RIGHT) 
		{
			//System.out.println("right pressed");
			dir = 1;
			moveSnake(dir);
		}
		if (key == KeyEvent.VK_UP) 
		{
			//System.out.println("up pressed");
			dir = 2;
			moveSnake(dir);
		}
		if (key == KeyEvent.VK_DOWN) 
		{
			//System.out.println("down pressed");
			dir = 3;
			moveSnake(dir);
		}
		//Exits the applet when the user hits enter.
		//The game over message gives these instructions.
		if (key == KeyEvent.VK_ENTER)
		{
			System.exit(0);
		}
	}
	
	//Calls the moveSnake method which changes the direction of the
	//snake and keeps it traveling in that same direction unless a new
	//arrow key is pressed; then it will travel in the new direction.
	public void run() 
	{
		while (animating)
		{
			try
			{
				Thread.sleep(500);
			}
			catch (Exception e){}
			
			moveSnake(dir);
		}
	}

	//Used to prevent flickering.
	public void componentResized(ComponentEvent arg0) 
	{
		m_RenderTarget = createImage(getWidth(),getHeight());
		m_BufferedGraphics = m_RenderTarget.getGraphics();
	}

	// Required by the key and mouse events and the component listener.
	public void keyReleased(KeyEvent arg0) {}
	public void keyTyped(KeyEvent arg0) {}
	public void mouseEntered(MouseEvent arg0) {}
	public void mouseExited(MouseEvent arg0) {}
	public void mousePressed(MouseEvent arg0) {}
	public void mouseReleased(MouseEvent arg0) {}
	public void componentHidden(ComponentEvent arg0) {}
	public void componentMoved(ComponentEvent arg0) {}
	public void componentShown(ComponentEvent arg0) {}
}



This post has been edited by finalfantasyfreak15: 19 February 2011 - 09:30 PM


Is This A Good Question/Topic? 0
  • +

Replies To: snake game; using the arraylist to store coordinates

#2 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10184
  • View blog
  • Posts: 37,597
  • Joined: 27-December 08

Re: snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 09:35 PM

A few things. First, not good practice at all to use separate ArrayLists to store x and y coordinates. Just use an ArrayList<Point> to store the Points. Which brings me to my second point: ArrayLists are generic. You should not be storing a regual ArrayList. It should have a generic type associated with it like ArrayList<Integer>, ArrayList<String>, etc., for whatever type you want to store in the ArrayList.

Another thing I noticed is that you are comparing Strings using the == and != operators. This isn't really good practice. The == and != operators compare the locations of Strings (and Objects in general) in memory. Use the equals() method isntead, which compares their values.

Lastly, you should really be designing a separate class to manage your Snake, and deal with functionality like bending, etc. Your GUI should modify the Snake object appropriately, and get the points it needs to draw the Snake on the screen.

This post has been edited by macosxnerd101: 19 February 2011 - 10:19 PM
Reason for edit:: My mistake. Must have been looking at another thread. Sorry for the confusion!

Was This Post Helpful? 0
  • +
  • -

#3 Guest_finalfantasyfreak15*


Reputation:

Re: snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 10:17 PM

View Postmacosxnerd101, on 19 February 2011 - 09:35 PM, said:

A few things. First, not good practice at all to use separate ArrayLists to store x and y coordinates. Just use an ArrayList<Point> to store the Points. Which brings me to my second point: ArrayLists are generic. You should not be storing a regual ArrayList. It should have a generic type associated with it like ArrayList<Integer>, ArrayList<String>, etc., for whatever type you want to store in the ArrayList.

Another thing I noticed is that you are comparing Strings using the == and != operators. This isn't really good practice. The == and != operators compare the locations of Strings (and Objects in general) in memory. Use the equals() method isntead, which compares their values.

Lastly, you should really be designing a separate class to manage your Snake, and deal with functionality like bending, etc. Your GUI should modify the Snake object appropriately, and get the points it needs to draw the Snake on the screen.


I'm not comparing any String objects in this program....and does it matter to have to type declared for the arraylist? Also, this is for an assignment in my CS class, and we are not allowed to use multiple classes (I also don't really understand much about creating new classes and using them in a program). I also do not know much about using arraylists which is why I'm having so many problems with this part of the coding. So since I cannot create a separate class, should I create a separate method called bendSnake? And if I create this method what exactly should this method do? I've seen other examples of source code for snake games, and one of the codes I looked at had this kind of method, but I didn't understand conceptually what the method was doing because the code didn't have much comments.
Was This Post Helpful? 0

#4 Guest_finalfantasyfreak15*


Reputation:

Re: snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 10:21 PM

Also, I had thought of using a Point at first, but I wasn't sure how to use it in an arraylist or how to send the x and y values into my method which draws the snake. If I use the point class what would be the difference?
Was This Post Helpful? 0

#5 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10184
  • View blog
  • Posts: 37,597
  • Joined: 27-December 08

Re: snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 10:30 PM

For reference, the cross-post.

Quote

and does it matter to have to type declared for the arraylist?

Yes. Not using generics with Java Collections will produce deprecation warnings, and potential errors due to type casting.

Quote

I also do not know much about using arraylists which is why I'm having so many problems with this part of the coding.

That's why Java has documentation.

Regarding the Point class, you can still access the x and y components.

Regarding the bend() method, think about the direction the snake is moving. The first block should move in the direction you are bending towards. Then as each block gets to the point where the bend occurred, it should move in that new direction.
Was This Post Helpful? 0
  • +
  • -

#6 finalfantasyfreak15  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 13
  • Joined: 19-February 11

Re: snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 10:46 PM

I have been reading the documentation for arraylists and the point class. And I'm not understanding how I would store a point into the list, so I think I will stick with the two lists I have now, since it makes a little more sense to me...

For the bend method: should each piece have it's own direction? That's what I'm not understanding conceptually. I don't understand how I would give each piece drawn it's own direction. I was thinking I could check the direction of the head (the head is at the last index because my TA recommended drawing from tail to head) and then compare the head with the piece next to it. Then the piece adjacent to the head would receive coordinates from the head (which would be the head's old coordinates) and then I would move to the next piece and so on.

But still, I don't know what I'm doing wrong in my code that all the points stored in the arraylists are the same coordinates....I just don't understand what I'm doing wrong that the points all end up being the same..
Was This Post Helpful? 0
  • +
  • -

#7 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10184
  • View blog
  • Posts: 37,597
  • Joined: 27-December 08

Re: snake game; using the arraylist to store coordinates

Posted 19 February 2011 - 11:04 PM

A basic demonstration of using a Point object in a List<Point>:
ArrayList<Point> points = new ArrayList<Point>();
points.add(new Point(someX, someY)); //add a Point to the List

Point p = points.get(0); //get the first Point in the list
int x = p.x; //access the x coordinate
int y = p.y; //access the y coordinate



As for moving the Points, you can use the Point translate() method.

And the reason all your points are the same is b/c you are setting them all to snakeX and snakeY (or the same translation of those variables).
Was This Post Helpful? 1
  • +
  • -

#8 finalfantasyfreak15  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 13
  • Joined: 19-February 11

Re: snake game; using the arraylist to store coordinates

Posted 21 February 2011 - 11:01 AM

So if I use this structure for adding the points to the arraylist, should I send in the global variables snakeX and snakeY? And then if I want to have the snake's pieces move I could use the translate() method to move the point at the indexed location by 10 or something? And would I also use the .remove() method to get rid of things at index 0?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1