最近我做了一个贪食蛇的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 LinkedListbody = 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(); } }