最近我做了一个贪食蛇的java小程序,加了几个功能,
不过总体很简单的demo,没有写什么注释,主要有以下特点:
允许用户保存名字,并独立存档写入磁盘。
每次启动和服务器进行通信,检查并显示信息。
允许空格减速,但会耗费积分。
分数等级越高,蛇的长度和速度越快,难度越大。
以下是预览图:
不过总体很简单的demo,没有写什么注释,主要有以下特点:
允许用户保存名字,并独立存档写入磁盘。
每次启动和服务器进行通信,检查并显示信息。
允许空格减速,但会耗费积分。
分数等级越高,蛇的长度和速度越快,难度越大。
以下是预览图:


以下是源代码:
package org.dmjsz.entity;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;
import org.dmjsz.listener.SnakeListener;
import org.dmjsz.util.Global;
public class Snake {
private boolean life = true;
private SnakeListener snakeListener;
public static final int UP = 1;
public static final int DOWN = -1;
public static final int LEFT = 3;
public static final int RIGHT = -3;
public static int speed = 400;
private Point tail;
private int oldDirection, newDirection;
private LinkedList body = new LinkedList();
public Snake() {
init();
}
public void init() {
int x = Global.WIDTH / 2;
int y = Global.HEIGHT / 2;
for (int i = 0; i < 3; i++) {
body.add(new Point(x - i, y));
}
this.oldDirection = this.newDirection = RIGHT;
}
public void move() {
tail = body.removeLast();
int x = body.getFirst().x;
int y = body.getFirst().y;
if (this.oldDirection + this.newDirection != 0)
this.oldDirection = this.newDirection;
switch (oldDirection) {
case UP:
y--;
if (y < 0)
y = Global.HEIGHT - 1;
break;
case DOWN:
y++;
if (y >= Global.HEIGHT)
y = 0;
break;
case LEFT:
x--;
if (x < 0)
x = Global.WIDTH - 1;
break;
case RIGHT:
x++;
if (x >= Global.WIDTH)
x = 0;
break;
}
body.addFirst(new Point(x, y));
System.out.println("moving");
}
public void eatFood(Food food) {
body.addLast(tail);
System.out.println("eating");
}
public void changeDirection(int direction) {
this.newDirection = direction;
System.out.println("changing");
}
public void drawMe(Graphics g) {
System.out.println("printing itself");
g.setColor(Color.blue);
for (Point p : body) {
g.fill3DRect(p.x * Global.CELL_SIZE, p.y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true);
}
}
public int getBodySize() {
return body.size();
}
public boolean isEatSelf() {
for (int i = 1; i < body.size(); i++) {
if (body.get(i).equals(getHead())) {
return true;
}
}
return false;
}
public void addSnakeListener(SnakeListener snakeListener) {
if (snakeListener != null) {
this.snakeListener = snakeListener;
}
}
public void start() {
new SnakeDriver().start();
}
public Point getHead() {
return body.getFirst();
}
public void setLife(boolean life) {
this.life = life;
}
public class SnakeDriver extends Thread {
public void run() {
while (life) {
move();
snakeListener.snakeMoved(Snake.this);
try {
Thread.sleep(speed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package org.dmjsz.entity;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;
import org.dmjsz.util.Global;
public class Ground {
private int[][] rocks = new int[Global.WIDTH][Global.HEIGHT];
public Ground() {
for (int y = 0; y < Global.HEIGHT; y++) {
for (int x = 0; x < Global.WIDTH; x++) {
if (y == 0 || y == Global.HEIGHT - 1)
rocks[y][x] = 1;
if (x == 0 || x == Global.WIDTH - 1)
rocks[y][x] = 1;
}
}
}
public boolean isEatBySnake(Snake snake) {
System.out.println("check the Snake " + "touth Ground or not");
Point head = snake.getHead();
for (int x = 0; x < Global.WIDTH; x++) {
for (int y = 0; y < Global.HEIGHT; y++) {
if (rocks[x][y] == 1 && head.x == x && head.y == y)
return true;
}
}
return false;
}
public void drawMe(Graphics g) {
g.setColor(Color.yellow);
for (int y = 0; y < Global.HEIGHT; y++) {
for (int x = 0; x < Global.WIDTH; x++) {
if (rocks[y][x] == 1) {
g.fill3DRect(x * Global.CELL_SIZE, y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true);
}
}
}
System.out.println("Ground is printing itself");
}
public Point getPoint() {
int x, y;
do {
x = new Random().nextInt(Global.WIDTH);
y = new Random().nextInt(Global.HEIGHT);
} while (rocks[x][y] == 1);
return new Point(x, y);
}
}
package org.dmjsz.entity;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import org.dmjsz.control.Controller;
import org.dmjsz.util.Global;
public class Food extends Point {
private static final long serialVersionUID = 1L;
public static int count = 0;
public void drawMe(Graphics g) {
g.setColor(Color.red);
g.fill3DRect(x * Global.CELL_SIZE, y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true);
System.out.println("Food is Drawing itself");
}
public boolean isEatBySnake(Snake snake) {
Point head = snake.getHead();
if (this.equals(head))
return true;
return false;
}
public void addFood(Point p) {
this.x = p.x;
this.y = p.y;
count++;
Controller c = new Controller();
c.gameSpeed();
}
public static int getCount() {
return count;
}
public static void setCount(int m) {
count = count - m;
}
}
package org.dmjsz.entity;
import java.awt.Graphics;
import javax.swing.JPanel;
public class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
private Snake snake;
private Food food;
private Ground ground;
public void display(Snake snake, Food food, Ground ground) {
System.out.println("Panel is displaying");
this.snake = snake;
this.food = food;
this.ground = ground;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (snake != null && food != null && ground != null) {
snake.drawMe(g);
food.drawMe(g);
ground.drawMe(g);
}
}
}
package org.dmjsz.control;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import org.dmjsz.entity.*;
import org.dmjsz.listener.SnakeListener;
import org.dmjsz.test.ScorePanel;
public class Controller extends KeyAdapter implements SnakeListener {
private Snake snake;
private Food food;
private Ground ground;
private GamePanel gamePanel;
public Controller() {
}
public Controller(Snake snake, Food food, Ground ground, GamePanel gamePanel) {
super();
this.snake = snake;
this.food = food;
this.ground = ground;
this.gamePanel = gamePanel;
}
@Override
public void keyPressed(KeyEvent e) {
int Keycode = e.getKeyCode();
switch (Keycode) {
case KeyEvent.VK_UP:
snake.changeDirection(Snake.UP);
break;
case KeyEvent.VK_DOWN:
snake.changeDirection(Snake.DOWN);
break;
case KeyEvent.VK_LEFT:
snake.changeDirection(Snake.LEFT);
break;
case KeyEvent.VK_RIGHT:
snake.changeDirection(Snake.RIGHT);
break;
case KeyEvent.VK_SPACE:
slowDown();
break;
}
}
@Override
public void snakeMoved(Snake snake) {
System.out.println("checking");
if (food.isEatBySnake(snake)) {
snake.eatFood(food);
food.addFood(ground.getPoint());
}
if (ground.isEatBySnake(snake)) {
snake.setLife(false);
overGame();
}
if (snake.isEatSelf()) {
snake.setLife(false);
overGame();
}
gamePanel.display(snake, food, ground);
}
public void startGame() {
snake.start();
food.addFood(ground.getPoint());
}
public void overGame() {
try {
new ScorePanel();
} catch (IOException e) {
e.printStackTrace();
}
}
public void gameSpeed() {
switch ((int) (Food.getCount() / 3)) {
case 1:
Snake.speed = 350;
break;
case 2:
Snake.speed = 300;
break;
case 3:
Snake.speed = 280;
break;
case 4:
Snake.speed = 260;
break;
case 5:
Snake.speed = 240;
break;
case 6:
Snake.speed = 220;
break;
case 7:
Snake.speed = 200;
break;
case 8:
Snake.speed = 165;
break;
case 9:
Snake.speed = 135;
break;
case 10:
Snake.speed = 110;
break;
case 11:
Snake.speed = 90;
break;
case 12:
Snake.speed = 80;
break;
case 13:
Snake.speed = 75;
break;
case 14:
Snake.speed = 70;
break;
case 15:
Snake.speed = 65;
break;
case 16:
Snake.speed = 60;
break;
case 17:
Snake.speed = 55;
break;
case 18:
Snake.speed = 50;
break;
case 19:
Snake.speed = 45;
break;
case 20:
Snake.speed = 30;
break;
case 21:
Snake.speed = 10;
break;
}
}
public void slowDown() {
if(Food.getCount()>0){
Snake.speed += 100;
Food.setCount(5);}
}
}
package org.dmjsz.listener;
import org.dmjsz.entity.Snake;
public interface SnakeListener {
public void snakeMoved(Snake snake);
}
package org.dmjsz.util;
public class Global {
public static final int CELL_SIZE = 15;
public static final int WIDTH = 20;
public static final int HEIGHT = 20;
}
package org.dmjsz.test;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class getName extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField textField;
public getName() {
getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panel = new ImagePanel();
getContentPane().add(panel);
panel.setLayout(null);
final JLabel n1 = new JLabel("贪食蛇2015");
n1.setBounds(70, 10, 200, 30);
n1.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 30));
final JLabel n2 = new JLabel("程序设计:Dmjsz");
n2.setBounds(85, 50, 200, 20);
n2.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 15));
n2.setVisible(false);
final JLabel n3 = new JLabel("程序美工:xxx");
n3.setBounds(75, 70, 200, 20);
n3.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 15));
n3.setVisible(false);
final JLabel n4 = new JLabel("程序测试:zzz");
n4.setBounds(75, 90, 200, 20);
n4.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 15));
n4.setVisible(false);
final JLabel n5 = new JLabel("yyyy");
n5.setBounds(50, 110, 200, 20);
n5.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 15));
n5.setVisible(false);
final JButton bt3 = new JButton("显示作者");
bt3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
n2.setVisible(true);
n3.setVisible(true);
n4.setVisible(true);
n5.setVisible(true);
}
});
bt3.setBounds(50, 250, 200, 30);
panel.add(n1);
panel.add(n2);
panel.add(n3);
panel.add(n4);
panel.add(n5);
panel.add(bt3);
final JLabel jl = new JLabel("请输入昵称以存档:");
jl.setBounds(50, 145, 200, 20);
jl.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 20));
panel.add(jl);
textField = new JTextField();
textField.setBounds(50, 170, 200, 20);
panel.add(textField);
textField.setColumns(10);
final JButton bt = new JButton("确认名称");
bt.setBounds(50, 210, 200, 30);
panel.add(bt);
final JButton bt2 = new JButton("获取更新");
bt2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new getUpdata();
setVisible(false);
}
});
bt2.setBounds(50, 250, 200, 30);
bt2.setVisible(false);
panel.add(bt2);
bt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
bt.setEnabled(false);
textField.setEnabled(false);
bt2.setVisible(true);
bt3.setVisible(false);
bt.setText("已完成存档");
jl.setText("完成存档");
ScorePanel.username = textField.getText();
}
});
setLocationRelativeTo(null);
setBounds(500, 200, 335, 375);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setTitle("确认昵称");
}
public static void main(String[] args) {
new getName();
}
class ImagePanel extends JPanel {
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
ImageIcon icon = new ImageIcon("base/snake.dll");
g.drawImage(icon.getImage(), 0, 0, null);
}
}
}
package org.dmjsz.test;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import org.dmjsz.util.Global;
public class getUpdata extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
new getUpdata();
}
getUpdata() {
final JFrame frame = new JFrame("连接远程服务器中...");
setLayout(null);
frame.setBounds(100, 100, Global.CELL_SIZE * Global.WIDTH + 15, Global.CELL_SIZE * Global.HEIGHT + 35);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JTextArea jt = new JTextArea();
jt.setBounds(0, 0, 200, 100);
final JButton bt = new JButton("开始游戏");
bt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new UI();
frame.setVisible(false);
}
});
bt.setBounds(0, 100, 200, 100);
frame.add(jt);
frame.add(bt, BorderLayout.SOUTH);
jt.setLineWrap(true);
frame.setVisible(true);
try {
jt.setText(inf());
frame.setTitle("更新信息");
} catch (IOException e) {
jt.setText("获取远程服务器信息失败,请检查你的网络连接!");
}
}
String inf() throws IOException {
URL url = new URL("http://www.dmjsz.com/snakegame");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream inputStream = conn.getInputStream();
byte[] getData = readInputStream(inputStream);
String data = new String(getData, "gb2312");
System.out.println(data);
return data;
}
public static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
return bos.toByteArray();
}
}
package org.dmjsz.test;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import org.dmjsz.entity.Food;
import org.dmjsz.entity.Snake;
import org.dmjsz.util.Global;
public class ScorePanel extends JFrame {
public static String username;
private static final long serialVersionUID = 1L;
private FileInputStream fis;
public ScorePanel() throws IOException {
final JFrame frame = new JFrame("游戏结束(看不到结果请调整窗口大小)");
setLayout(new BorderLayout());
frame.setBounds(1000, 100, Global.CELL_SIZE * Global.WIDTH + 15, Global.CELL_SIZE * Global.HEIGHT + 35);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Container c = new Container();
c.setLayout(new GridLayout(5, 1, 10, 10));
JLabel jl0 = new JLabel("游戏结束", JLabel.CENTER);
jl0.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 20));
JLabel jl1 = new JLabel("得分:" + Food.getCount() * 175, JLabel.CENTER);
jl1.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 20));
JLabel jl2 = new JLabel("", JLabel.CENTER);
jl2.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 20));
Reader reader = null;
BufferedReader br = null;
try {
reader = new FileReader("data/Snake_" + username + ".snake");
br = new BufferedReader(reader);
StringBuffer sb = new StringBuffer();
String data = null;
while ((data = br.readLine()) != null) {
sb.append(data);
if ((Integer.valueOf(data).intValue()) - Food.getCount() * 175 > 0) {
jl2.setText("你的最高分:" + data);
} else {
jl2.setText("你的最高分:" + Food.getCount() * 175);
FileOutputStream out = new FileOutputStream("data/Snake_" + username + ".snake");
out.write(((Food.getCount() * 175) + "").getBytes());
out.close();
}
}
} catch (IOException e) {
jl2.setText("你的最高分:" + Food.getCount() * 175);
FileOutputStream out = new FileOutputStream("data/Snake_" + username + ".snake");
out.write(((Food.getCount() * 175) + "").getBytes());
out.close();
} finally {
try {
reader.close();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
JLabel jl3 = new JLabel("等级:" + Food.getCount() / 3, JLabel.CENTER);
jl3.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 20));
JButton jb1 = new JButton("详细战绩");
jb1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
jump();
}
});
String allContent = "得分:" + Food.getCount() * 175 + "等级:" + (Food.getCount() / 3) + "===";
FileOutputStream out = new FileOutputStream("data/Snake_" + username + "_all" + ".snake", true);
out.write((allContent).getBytes());
out.close();
c.add(jl0);
c.add(jl1);
c.add(jl2);
c.add(jl3);
c.add(jb1);
frame.add(c);
}
public void jump() {
final JFrame jf2 = new JFrame("详细战绩");
jf2.setBounds(1000, 100, Global.CELL_SIZE * Global.WIDTH + 15, Global.CELL_SIZE * Global.HEIGHT + 35);
jf2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf2.setLocationRelativeTo(null);
jf2.setVisible(true);
Container c = new Container();
c.setLayout(null);
JTextArea jta = new JTextArea();
String str = "";
try {
File file = new File("data/Snake_" + username + "_all" + ".snake");
fis = new FileInputStream(file);
byte[] bytes = new byte[1024];
int length = 0;
while ((length = fis.read(bytes)) != -1) {
str += new String(bytes, 0, length);
}
System.out.println(str);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
jta.setText(str);
jta.setLineWrap(true);
jta.setBounds(0, 0, Global.CELL_SIZE * Global.WIDTH + 80, Global.CELL_SIZE * Global.HEIGHT - 10);
JButton jbn1 = new JButton("再来一局");
jbn1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new UI();
jf2.setVisible(false);
Food.setCount(Food.getCount());
Snake.speed=400;
}
});
jta.setBounds(0, 0, Global.CELL_SIZE * Global.WIDTH, Global.CELL_SIZE * Global.HEIGHT - 60);
jbn1.setBounds(0, Global.CELL_SIZE * Global.HEIGHT - 50, Global.CELL_SIZE * Global.WIDTH, 50);
c.add(jta);
c.add(jbn1);
jf2.add(c);
}
}
package org.dmjsz.test;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import org.dmjsz.control.Controller;
import org.dmjsz.entity.Food;
import org.dmjsz.entity.GamePanel;
import org.dmjsz.entity.Ground;
import org.dmjsz.entity.Snake;
import org.dmjsz.util.Global;
public class UI extends JFrame {
private static final long serialVersionUID = 1L;
public UI() {
Snake snake = new Snake();
Food food = new Food();
Ground ground = new Ground();
GamePanel gamePanel = new GamePanel();
Controller c = new Controller(snake, food, ground, gamePanel);
snake.addSnakeListener(c);
gamePanel.addKeyListener(c);
JFrame frame = new JFrame("贪食蛇游戏 @Dmjsz");
setLayout(new BorderLayout());
frame.setBounds(1000, 100, Global.CELL_SIZE * Global.WIDTH + 15, Global.CELL_SIZE * Global.HEIGHT + 35);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
gamePanel.setFocusable(true);
frame.add(gamePanel);
c.startGame();
frame.setVisible(true);
}
}
/**
* 贪食蛇游戏ver1.1
* 作者: Dmjsz
* 命名页背景图片来自网络
* 程序设计及参与者版权所有
* 转载署名,不得商用
* 2015年05月
**/
package org.dmjsz.test;
public class SnakeGameTest {
public static void main(String[] args) {
new getName();
}
}
Comments NOTHING