El Snake es un videojuego clásico que salió a mediados de lá década de 1970 en los salones recreativos, y que más tarde en 1998 sería incluído de serie en los terminales móviles de Nokia. Una versión del título llamada Nibbles, gozó también de gran popularidad en MS-DOS ya que QBasic lo traía como programa de ejemplo.

Dejando a un lado al simplísimo Pong, podemos pensar en el Snake como en uno de los juegos más fáciles de programar. A continuación expongo el código fuente de una simplísima versión del juego que programé en lenguaje Java, aunque admito que quizá no está muy ordenado ya que lo escribí de madrugada.
Descargar
Snake.java
/*
* SNAKE en Java (1.0 alpha)
*
* Autor: Juan Gestal (Jimmy)
* Fecha: 16/09/09
*
* Web: http://www.gestal.es
*/
package org.sp.Snake;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class Snake extends JFrame implements Runnable {
// Altura y anchura de la ventana
public static int W = 600;
public static int H = 400;
// Tablero
public static int CV = 15; // Casillas verticales
public static int CH = 28; // Casillas horizontales
public static int CT = 20; // Tamaño de las casillas
public static int CX = 20; // Posición X del comienzo del tablero en la
// pantalla
public static int CY = 60; // Posición Y del comienzo del tablero en la
// pantalla
// Juego
public static int juego[][] = new int[CH][CV];
public static int MAX_LONG_SNAKE = 40;
public static int snake[][] = new int[MAX_LONG_SNAKE + 1][2];
public static int snakeLongAct;
public static int snakeMov = 1;
// Comprobaciones
public static boolean gameOver = false;
public static int puntuacion = 0;
// Tecla pulsada
public static int tecla = snakeMov;
// Retardo
public static int retardo = 200;
public void pintarTablero(Graphics g) {
for (int x = 0; x < CH; x++) {
for (int y = 0; y < CV; y++) {
switch (juego[x][y]) {
case 0: // La casilla está vacía
g.setColor(Color.white);
g.fillRect(x * CT + CX, y * CT + CY, CT, CT);
break;
case 1: // La casilla es un borde
g.setColor(Color.black);
g.fillRect(x * CT + CX, y * CT + CY, CT, CT);
break;
}
}
}
}
public void pintarSerpiente(Graphics g) {
for (int i = 0; i < snakeLongAct; i++) {
int x = snake[i][0];
int y = snake[i][1];
if (i == 0)
g.setColor(Color.blue);
else
g.setColor(Color.magenta);
g.fillRect(x * CT + CX, y * CT + CY, CT, CT);
}
}
public void paint(Graphics g) {
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, W, H);
pintarTablero(g);
pintarSerpiente(g);
g.setColor(Color.black);
g.drawString("PUNTUACION:" + puntuacion, 20, 50);
if (gameOver) {
g.drawString("GAME OVER: Pulsa la tecla R para volver a jugar",20,380);
}
}
public static void main(String[] args) {
Snake snk = new Snake();
crearVentana(snk);
inicializarJuego();
inicializarSerpiente();
ponerManzana();
}
public static void crearVentana(Snake snk) {
snk.setVisible(true);
snk.setBounds(0, 0, W, H);
}
public static void inicializarJuego() {
// Inicializamos el tablero de juego
for (int x = 0; x < CH; x++) {
for (int y = 0; y < CV; y++) {
juego[x][y] = 0;
}
}
// Fijamos los bordes
for (int x = 1; x < CH; x++) {
juego[x][0] = 1;
juego[x][CV - 1] = 1;
}
for (int y = 0; y < CV; y++) {
juego[0][y] = 1;
juego[CH - 1][y] = 1;
}
}
public static void inicializarSerpiente() {
// Situamos la serpiente en su posición inicial
int mitadVertical = CV / 2;
snake[0][0] = 4;
snake[0][1] = mitadVertical;
snake[1][0] = 3;
snake[1][1] = mitadVertical;
snake[2][0] = 2;
snake[2][1] = mitadVertical;
snakeLongAct = 3; // Fijamos la longitud inicial
}
public Snake() {
Thread hilo = new Thread(this);
hilo.start();
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
tecla = e.getKeyCode();
// Tenemos que comprobar siempre que no vaya en dirección
// contraria
switch (e.getKeyCode()) {
case 39: { // Derecha
if (snakeMov != 3)
snakeMov = 1;
break;
}
case 40: { // Abajo
if (snakeMov != 4)
snakeMov = 2;
break;
}
case 37: { // Izquierda
if (snakeMov != 1)
snakeMov = 3;
break;
}
case 38: { // Arriba
if (snakeMov != 2)
snakeMov = 4;
break;
}
case 'r':
case 'R': {
puntuacion = 0;
snakeMov = 1;
gameOver=false;
inicializarJuego();
inicializarSerpiente();
ponerManzana();
break;
}
}
}
});
}
public void run() {
while (true) {
try {
Thread.sleep(retardo);
} catch (Exception e) {
}
// Comprobar movimiento
comprobaciones();
if (!gameOver) {
movimientoSerpiente();
}
repaint();
// Repintar
}
}
public void comprobaciones() {
int sx = snake[0][0];
int sy = snake[0][1];
switch (snakeMov) {
case 1:
sx = snake[0][0] + 1;
break;
case 2:
sy = snake[0][1] + 1;
break;
case 3:
sx = snake[0][0] - 1;
break;
case 4:
sy = snake[0][1] - 1;
break;
}
for (int x = 0; x < CH; x++) {
for (int y = 0; y < CV; y++) {
if ((x == sx) && (y == sy)) {
if ((juego[x][y] == 1)) { // Choca contra la pared
gameOver = true;
}
if (juego[x][y] == 1000) { // Comemos manzana
juego[x][y] = 0; // Quitamos la manzana
if (snakeLongAct < MAX_LONG_SNAKE) { // Si es posible
// crecer,
// crecemos
snakeLongAct++;
}
puntuacion += 10; // Aumentamos los puntos
ponerManzana(); // Colocamos una nueva manzana
}
}
}
}
for (int i = 0; i < snakeLongAct; i++) {
if ((sx == snake[i][0]) && (sy == snake[i][1]))
gameOver = true;
}
}
public void movimientoSerpiente() {
for (int i = snakeLongAct; i > 0; i--) {
snake[i][0] = snake[i - 1][0];
snake[i][1] = snake[i - 1][1];
}
switch (snakeMov) {
case 1:
snake[0][0] = snake[0][0] + 1;
break;
case 2:
snake[0][1] = snake[0][1] + 1;
break;
case 3:
snake[0][0] = snake[0][0] - 1;
break;
case 4:
snake[0][1] = snake[0][1] - 1;
break;
}
}
public static void ponerManzana() {
boolean manzanaPuesta = false;
while (!manzanaPuesta) {
// Generamos una posición aleatoria en el tablero
int xManzana = (int) (Math.random() * CH);
int yManzana = (int) (Math.random() * CV);
// Comprobamos que no haya nada en la posición
if (juego[xManzana][yManzana] == 0) { // Es una casilla libre, hay
// que mirar que en ella no
// se encuentre la serpiente
boolean estaSerpiente = false;
for (int i = 0; i < snakeLongAct; i++) {
if ((snake[i][0] == xManzana) && (snake[i][1] == yManzana))
estaSerpiente = true;
}
if (!estaSerpiente) { // Podemos poner la manzana
juego[xManzana][yManzana] = 1000;
manzanaPuesta = true;
}
}
}
}
}
Podrías subir el package, para jugarlo en mi pc?