Snake/Java: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎Code: small changes)
(→‎{{header|Java}}: cleaned up code a bit)
Line 9: Line 9:


public class Snake extends JPanel implements Runnable {
public class Snake extends JPanel implements Runnable {
enum Dir {
up, right, down, left
};

final Random rand = new Random();
final Random rand = new Random();
final int[][] dirs = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
final int[][] dirs = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
final int WALL = -1;
final int WALL = -1;
final int MAX_ENERGY = 1500;


volatile boolean gameOver = true;
volatile boolean gameOver = true;
Line 19: Line 24:
int nRows = 44;
int nRows = 44;
int nCols = 64;
int nCols = 64;
int dir;
Dir dir;
int energy;
int energy;


Line 53: Line 58:


case KeyEvent.VK_UP:
case KeyEvent.VK_UP:
if (dir != 2)
if (dir != Dir.down)
dir = 0;
dir = Dir.up;
break;
break;


case KeyEvent.VK_LEFT:
case KeyEvent.VK_LEFT:
if (dir != 1)
if (dir != Dir.right)
dir = 3;
dir = Dir.left;
break;
break;


case KeyEvent.VK_RIGHT:
case KeyEvent.VK_RIGHT:
if (dir != 3)
if (dir != Dir.left)
dir = 1;
dir = Dir.right;
break;
break;


case KeyEvent.VK_DOWN:
case KeyEvent.VK_DOWN:
if (dir != 0)
if (dir != Dir.up)
dir = 2;
dir = Dir.down;
break;
break;
}
}
Line 82: Line 87:
stop();
stop();
initGrid();
initGrid();
treats = new LinkedList<>();


dir = 3;
dir = Dir.left;
energy = 1500;
energy = MAX_ENERGY;


if (score > hiScore)
if (score > hiScore)
Line 90: Line 96:
score = 0;
score = 0;


treats = new LinkedList<>();
snake = new ArrayList<>();
snake = new ArrayList<>();
for (int x = 0; x < 7; x++)
for (int x = 0; x < 7; x++)
Line 127: Line 132:
}
}


energy -= 10;
if (energyUsed() || hitsWall() || hitsSnake()) {
if (energy <= 0)
gameOver();
gameOver();
} else {

else if (hitsWall())
if (eatsTreat()) {
gameOver();
score++;
energy = MAX_ENERGY;

else if (hitsSnake())
growSnake();
gameOver();
}

else if (eatsTreat()) {
score++;
energy = 1500;
growSnake();
}

if (!gameOver) {
moveSnake();
moveSnake();
addTreat();
addTreat();
Line 149: Line 145:
repaint();
repaint();
}
}
}

boolean energyUsed() {
energy -= 10;
return energy <= 0;
}

boolean hitsWall() {
Point head = snake.get(0);
int nextCol = head.x + dirs[dir.ordinal()][0];
int nextRow = head.y + dirs[dir.ordinal()][1];
return grid[nextRow][nextCol] == WALL;
}

boolean hitsSnake() {
Point head = snake.get(0);
int nextCol = head.x + dirs[dir.ordinal()][0];
int nextRow = head.y + dirs[dir.ordinal()][1];
for (Point p : snake)
if (p.x == nextCol && p.y == nextRow)
return true;
return false;
}

boolean eatsTreat() {
Point head = snake.get(0);
int nextCol = head.x + dirs[dir.ordinal()][0];
int nextRow = head.y + dirs[dir.ordinal()][1];
for (Point p : treats)
if (p.x == nextCol && p.y == nextRow) {
return treats.remove(p);
}
return false;
}
}


Line 154: Line 183:
gameOver = true;
gameOver = true;
stop();
stop();
}

void moveSnake() {
for (int i = snake.size() - 1; i > 0; i--) {
Point p1 = snake.get(i - 1);
Point p2 = snake.get(i);
p2.x = p1.x;
p2.y = p1.y;
}
Point head = snake.get(0);
head.x += dirs[dir.ordinal()][0];
head.y += dirs[dir.ordinal()][1];
}

void growSnake() {
Point tail = snake.get(snake.size() - 1);
int x = tail.x + dirs[dir.ordinal()][0];
int y = tail.y + dirs[dir.ordinal()][1];
snake.add(new Point(x, y));
}

void addTreat() {
if (treats.size() < 3) {

if (rand.nextInt(10) == 0) { // 1 in 10

if (rand.nextInt(4) != 0) { // 3 in 4
int x, y;
while (true) {

x = rand.nextInt(nCols);
y = rand.nextInt(nRows);
if (grid[y][x] != 0)
continue;

Point p = new Point(x, y);
if (snake.contains(p) || treats.contains(p))
continue;

treats.add(p);
break;
}
} else if (treats.size() > 1)
treats.remove(0);
}
}
}
}


Line 216: Line 291:
drawScore(g);
drawScore(g);
}
}
}

void moveSnake() {
for (int i = snake.size() - 1; i > 0; i--) {
Point p1 = snake.get(i - 1);
Point p2 = snake.get(i);
p2.x = p1.x;
p2.y = p1.y;
}
Point head = snake.get(0);
head.x += dirs[dir][0];
head.y += dirs[dir][1];
}

void growSnake() {
Point tail = snake.get(snake.size() - 1);
int x = tail.x + dirs[dir][0];
int y = tail.y + dirs[dir][1];
snake.add(new Point(x, y));
}

void addTreat() {
if (treats.size() < 3) {

if (rand.nextInt(10) == 0) { // 1 in 10

if (rand.nextInt(4) != 0) { // 3 in 4
int x, y;
while (true) {

x = rand.nextInt(nCols);
y = rand.nextInt(nRows);
if (grid[y][x] != 0)
continue;

Point p = new Point(x, y);
if (snake.contains(p) || treats.contains(p))
continue;

treats.add(p);
break;
}
} else if (treats.size() > 1)
treats.remove(0);
}
}
}

boolean hitsWall() {
Point head = snake.get(0);
int nextCol = head.x + dirs[dir][0];
int nextRow = head.y + dirs[dir][1];
return grid[nextRow][nextCol] == WALL;
}

boolean hitsSnake() {
Point head = snake.get(0);
int nextCol = head.x + dirs[dir][0];
int nextRow = head.y + dirs[dir][1];
for (Point p : snake)
if (p.x == nextCol && p.y == nextRow)
return true;
return false;
}

boolean eatsTreat() {
Point head = snake.get(0);
int nextCol = head.x + dirs[dir][0];
int nextRow = head.y + dirs[dir][1];
for (Point p : treats)
if (p.x == nextCol && p.y == nextRow) {
treats.remove(p);
return true;
}
return false;
}
}



Revision as of 13:30, 31 March 2016

Code

Works with: Java version 8

<lang java>import java.awt.*; import java.awt.event.*; import static java.lang.String.format; import java.util.*; import java.util.List; import javax.swing.*;

public class Snake extends JPanel implements Runnable {

   enum Dir {
       up, right, down, left
   };
   final Random rand = new Random();
   final int[][] dirs = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
   final int WALL = -1;
   final int MAX_ENERGY = 1500;
   volatile boolean gameOver = true;
   Thread gameThread;
   int score, hiScore;
   int nRows = 44;
   int nCols = 64;
   Dir dir;
   int energy;
   int[][] grid;
   List<Point> snake, treats;
   Font smallFont;
   public Snake() {
       setPreferredSize(new Dimension(640, 440));
       setBackground(Color.white);
       setFont(new Font("SansSerif", Font.BOLD, 48));
       setFocusable(true);
       smallFont = getFont().deriveFont(Font.BOLD, 18);
       initGrid();
       addMouseListener(new MouseAdapter() {
           @Override
           public void mousePressed(MouseEvent e) {
               if (gameOver) {
                   startNewGame();
                   repaint();
               }
           }
       });
       addKeyListener(new KeyAdapter() {
           @Override
           public void keyPressed(KeyEvent e) {
               switch (e.getKeyCode()) {
                   case KeyEvent.VK_UP:
                       if (dir != Dir.down)
                           dir = Dir.up;
                       break;
                   case KeyEvent.VK_LEFT:
                       if (dir != Dir.right)
                           dir = Dir.left;
                       break;
                   case KeyEvent.VK_RIGHT:
                       if (dir != Dir.left)
                           dir = Dir.right;
                       break;
                   case KeyEvent.VK_DOWN:
                       if (dir != Dir.up)
                           dir = Dir.down;
                       break;
               }
               repaint();
           }
       });
   }
   void startNewGame() {
       gameOver = false;
       stop();
       initGrid();
       treats = new LinkedList<>();
       dir = Dir.left;
       energy = MAX_ENERGY;
       if (score > hiScore)
           hiScore = score;
       score = 0;
       snake = new ArrayList<>();
       for (int x = 0; x < 7; x++)
           snake.add(new Point(nCols / 2 + x, nRows / 2));
       (gameThread = new Thread(this)).start();
   }
   void stop() {
       if (gameThread != null) {
           Thread tmp = gameThread;
           gameThread = null;
           tmp.interrupt();
       }
   }
   void initGrid() {
       grid = new int[nRows][nCols];
       for (int r = 0; r < nRows; r++) {
           for (int c = 0; c < nCols; c++) {
               if (c == 0 || c == nCols - 1 || r == 0 || r == nRows - 1)
                   grid[r][c] = WALL;
           }
       }
   }
   @Override
   public void run() {
       while (Thread.currentThread() == gameThread) {
           try {
               Thread.sleep(Math.max(75 - score, 25));
           } catch (InterruptedException e) {
               return;
           }
           if (energyUsed() || hitsWall() || hitsSnake()) {
               gameOver();
           } else {
               if (eatsTreat()) {
                   score++;
                   energy = MAX_ENERGY;
                   growSnake();
               }
               moveSnake();
               addTreat();
           }
           repaint();
       }
   }
   boolean energyUsed() {
       energy -= 10;
       return energy <= 0;
   }
   boolean hitsWall() {
       Point head = snake.get(0);
       int nextCol = head.x + dirs[dir.ordinal()][0];
       int nextRow = head.y + dirs[dir.ordinal()][1];
       return grid[nextRow][nextCol] == WALL;
   }
   boolean hitsSnake() {
       Point head = snake.get(0);
       int nextCol = head.x + dirs[dir.ordinal()][0];
       int nextRow = head.y + dirs[dir.ordinal()][1];
       for (Point p : snake)
           if (p.x == nextCol && p.y == nextRow)
               return true;
       return false;
   }
   boolean eatsTreat() {
       Point head = snake.get(0);
       int nextCol = head.x + dirs[dir.ordinal()][0];
       int nextRow = head.y + dirs[dir.ordinal()][1];
       for (Point p : treats)
           if (p.x == nextCol && p.y == nextRow) {
               return treats.remove(p);
           }
       return false;
   }
   void gameOver() {
       gameOver = true;
       stop();
   }
   void moveSnake() {
       for (int i = snake.size() - 1; i > 0; i--) {
           Point p1 = snake.get(i - 1);
           Point p2 = snake.get(i);
           p2.x = p1.x;
           p2.y = p1.y;
       }
       Point head = snake.get(0);
       head.x += dirs[dir.ordinal()][0];
       head.y += dirs[dir.ordinal()][1];
   }
   void growSnake() {
       Point tail = snake.get(snake.size() - 1);
       int x = tail.x + dirs[dir.ordinal()][0];
       int y = tail.y + dirs[dir.ordinal()][1];
       snake.add(new Point(x, y));
   }
   void addTreat() {
       if (treats.size() < 3) {
           if (rand.nextInt(10) == 0) { // 1 in 10
               if (rand.nextInt(4) != 0) {  // 3 in 4
                   int x, y;
                   while (true) {
                       x = rand.nextInt(nCols);
                       y = rand.nextInt(nRows);
                       if (grid[y][x] != 0)
                           continue;
                       Point p = new Point(x, y);
                       if (snake.contains(p) || treats.contains(p))
                           continue;
                       treats.add(p);
                       break;
                   }
               } else if (treats.size() > 1)
                   treats.remove(0);
           }
       }
   }
   void drawGrid(Graphics2D g) {
       g.setColor(Color.lightGray);
       for (int r = 0; r < nRows; r++) {
           for (int c = 0; c < nCols; c++) {
               if (grid[r][c] == WALL)
                   g.fillRect(c * 10, r * 10, 10, 10);
           }
       }
   }
   void drawSnake(Graphics2D g) {
       g.setColor(Color.blue);
       for (Point p : snake)
           g.fillRect(p.x * 10, p.y * 10, 10, 10);
       g.setColor(energy < 500 ? Color.red : Color.orange);
       Point head = snake.get(0);
       g.fillRect(head.x * 10, head.y * 10, 10, 10);
   }
   void drawTreats(Graphics2D g) {
       g.setColor(Color.green);
       for (Point p : treats)
           g.fillRect(p.x * 10, p.y * 10, 10, 10);
   }
   void drawStartScreen(Graphics2D g) {
       g.setColor(Color.blue);
       g.setFont(getFont());
       g.drawString("Snake", 240, 190);
       g.setColor(Color.orange);
       g.setFont(smallFont);
       g.drawString("(click to start)", 250, 240);
   }
   void drawScore(Graphics2D g) {
       int h = getHeight();
       g.setFont(smallFont);
       g.setColor(getForeground());
       String s = format("hiscore %d    score %d", hiScore, score);
       g.drawString(s, 30, h - 30);
       g.drawString(format("energy %d", energy), getWidth() - 150, h - 30);
   }
   @Override
   public void paintComponent(Graphics gg) {
       super.paintComponent(gg);
       Graphics2D g = (Graphics2D) gg;
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       drawGrid(g);
       if (gameOver) {
           drawStartScreen(g);
       } else {
           drawSnake(g);
           drawTreats(g);
           drawScore(g);
       }
   }
   public static void main(String[] args) {
       SwingUtilities.invokeLater(() -> {
           JFrame f = new JFrame();
           f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           f.setTitle("Snake");
           f.setResizable(false);
           f.add(new Snake(), BorderLayout.CENTER);
           f.pack();
           f.setLocationRelativeTo(null);
           f.setVisible(true);
       });
   }

}</lang>