import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Canvas extends JPanel implements Runnable {
  private TheGame theGame;

  private volatile boolean running = true;
  
  private Graphics g;
  private Image img;
  
  public Canvas() {
    setPreferredSize(new Dimension(GameData.BOARD_WIDTH * 10,GameData.BOARD_HEIGHT * 10));
    setFocusable(true);
    requestFocus();
    
    addKeyListener(new KeyAdapter() {
      @Override
      public void keyPressed(KeyEvent ke) {
        switch ke.getKeyCode() ) {
          case KeyEvent.VK_UP :
            theGame.setDirection(0);
          break;
          case KeyEvent.VK_LEFT :
            theGame.setDirection(1);
          break;
          case KeyEvent.VK_DOWN :
            theGame.setDirection(2);
          break;
          case KeyEvent.VK_RIGHT :
            theGame.setDirection(3);
          break;
        }
      }
    });
  }
  
  public void startGame() {
    theGame = new TheGame();
    new Thread(this).start();
  }
  
  public void run() {
    while running ) {
      try {
        theGame.mainLoop();
      catch (Exception e) {
        running = false;
        JOptionPane.showMessageDialog(null, e.getMessage(),"Game Over",JOptionPane.ERROR_MESSAGE);
        System.exit(0);
      }
      
      render();
      paintScreen();

      try {
        Thread.sleep(200);
      catch (Exception e) {
        running = false;
        e.printStackTrace();
      }
    }
  }
  
  private void render() {
    if img == null ) {
      img = createImage(GameData.BOARD_WIDTH * 10,GameData.BOARD_HEIGHT * 10);
      g = img.getGraphics();
    }
    
    g.setColor(Color.BLACK);
    g.fillRect(00, GameData.BOARD_WIDTH * 10, GameData.BOARD_HEIGHT * 10);
    g.setColor(Color.GREEN);
    g.fillRect(theGame.getFood().x * 10, theGame.getFood().y * 101010);
    g.setColor(Color.RED);
    g.fillRect(theGame.getHead().position.x * 10, theGame.getHead().position.y * 101010);
    g.setColor(Color.ORANGE);
    SnakePart tail = theGame.getHead().getTail();
    while tail != null ) {
      g.fillRect(tail.position.x * 10, tail.position.y * 101010);
      tail = tail.getTail();
    }
  }
    
  private void paintScreen() { 
    Graphics g;
    try {
      g = this.getGraphics();
      g.drawImage(img, 00null);
      g.dispose();
    }
    catch (Exception e) {
      System.out.println("Graphics error: " + e);  
    }
  }
  
}
Java2html

import java.awt.Point;

/**
 
 */

/**
 @author Panagiotis Peikidis
 @version 1.0
 *
 */
public class GameData {
  public SnakePart head;
  public int direction;
  public Point food;
  public static final int BOARD_WIDTH = 32;
  public static final int BOARD_HEIGHT = 32;

  public GameData() {
    this.head = new SnakePart(new Point(GameData.BOARD_WIDTH / 2,GameData.BOARD_HEIGHT / 2));
    this.direction = 3;
    this.food = new Point(-1,-1);
  }
}
Java2html

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 
 */

/**
 @author Panagiotis Peikidis
 @version 1.0
 *
 */
public class GUI extends JFrame {

  private Canvas canvas = new Canvas();
  
  public GUI () {
    setTitle("JSnake");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    getContentPane().add(canvas);
    pack();
    setLocationRelativeTo(null);
    canvas.startGame();
  }
  
  public static void main(String[] args) {
    new GUI().setVisible(true);
  }

}
Java2html

import java.awt.Point;

/**
 
 */

/**
 @author Panagiotis Peikidis
 @version 1.0
 *
 */
public class SnakePart {
  public Point position;
  private SnakePart tail;
  
  public SnakePart(Point position, SnakePart tail) {
    this.position = position;
    this.tail = tail;
  }

  public SnakePart(Point position) {
    this(position,null);
  }
  
  public void move(Point position) {
    Point previous = this.position;
    this.position = position;
    if tail != null )
      tail.move(previous);
  }
  
  public SnakePart getTail() {
    return this.tail;
  }
  
  public void setTail(SnakePart tail) {
    this.tail = tail;
  }
}
Java2html

import java.awt.Point;
import java.util.Random;

/**
 
 */

/**
 @author Panagiotis Peikidis
 @version 1.0
 *
 */
public class TheGame {
  private GameData data;
  private Random ran = new Random();
  
  public TheGame() {
    this.data = new GameData();
    createFood();
  }
  
  public boolean wallCollision() {
    if ( ( data.head.position.x == -
        || data.head.position.y == -)
        || data.head.position.x == GameData.BOARD_WIDTH )
        || data.head.position.y == GameData.BOARD_HEIGHT ) )
      return true;
    return false;
  }
  
  public boolean tailCollision() {
    SnakePart tail = data.head.getTail();
    while tail != null ) {
      if tail.position.equalsdata.head.position ) ) {
        return true;
      else {
        tail = tail.getTail();
      }
    }
    return false;
  }
  
  public boolean foodCollision() {
    if data.food.equals(data.head.position) ) {
      return true;
    else {
      return false;
    }
  }
  
  public void mainLoop() throws Exception {
    switch data.direction ) {
      case 0:
        data.head.move(new Point(data.head.position.x,data.head.position.y - 1));
      break;
      case 1:
        data.head.move(new Point(data.head.position.x - 1,data.head.position.y));
      break;
      case 2:
        data.head.move(new Point(data.head.position.x,data.head.position.y + 1));
      break;
      case 3:
        data.head.move(new Point(data.head.position.x + 1,data.head.position.y));
      break;
    }
    
    if wallCollision() )
      throw new Exception("Game Over - Wall hit");
    
    if tailCollision() )
      throw new Exception("Game Over - Tail hit");

    if foodCollision() ) {
      SnakePart headTail = data.head.getTail();
      data.head.setTail(new SnakePart(data.head.position,headTail));
      createFood();
    }
  }
  
  public void createFood() {
    this.data.food.x = ran.nextInt(GameData.BOARD_WIDTH);
    this.data.food.y = ran.nextInt(GameData.BOARD_HEIGHT);
  }
  
  public Point getFood() {
    return data.food;
  }
  
  public SnakePart getHead() {
    return data.head;
  }
  
  public void setDirection(int direction) {
    data.direction = direction;
  }
}
Java2html