贪吃蛇实现--Java

来源:互联网 发布:数据库管理规定 编辑:程序博客网 时间:2024/04/28 04:56
package cn.sun;import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.util.*;//=============================================//Main Class//=============================================public class GreedSnake implements KeyListener {JFrame mainFrame;Canvas paintCanvas;JLabel labelScore;// 计分牌SnakeModel snakeModel = null;// 蛇public static final int canvasWidth = 200;public static final int canvasHeight = 300;public static final int nodeWidth = 10;public static final int nodeHeight = 10;// ----------------------------------------------------------------------// GreedSnake():初始化游戏界面// ----------------------------------------------------------------------public GreedSnake() {// 设置界面元素mainFrame = new JFrame("GreedSnake");Container cp = mainFrame.getContentPane();labelScore = new JLabel("Score:");cp.add(labelScore, BorderLayout.NORTH);paintCanvas = new Canvas();paintCanvas.setSize(canvasWidth + 1, canvasHeight + 1);paintCanvas.addKeyListener(this);cp.add(paintCanvas, BorderLayout.CENTER);JPanel panelButtom = new JPanel();panelButtom.setLayout(new BorderLayout());JLabel labelHelp;// 帮助信息labelHelp = new JLabel("PageUp, PageDown for speed;", JLabel.CENTER);panelButtom.add(labelHelp, BorderLayout.NORTH);labelHelp = new JLabel("ENTER or R or S for start;", JLabel.CENTER);panelButtom.add(labelHelp, BorderLayout.CENTER);labelHelp = new JLabel("SPACE or P for pause", JLabel.CENTER);panelButtom.add(labelHelp, BorderLayout.SOUTH);cp.add(panelButtom, BorderLayout.SOUTH);mainFrame.addKeyListener(this);mainFrame.pack();mainFrame.setResizable(false);mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);mainFrame.setVisible(true);begin();}// ----------------------------------------------------------------------// keyPressed():按键检测// ----------------------------------------------------------------------public void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();if (snakeModel.running)switch (keyCode) {case KeyEvent.VK_UP:snakeModel.changeDirection(SnakeModel.UP);break;case KeyEvent.VK_DOWN:snakeModel.changeDirection(SnakeModel.DOWN);break;case KeyEvent.VK_LEFT:snakeModel.changeDirection(SnakeModel.LEFT);break;case KeyEvent.VK_RIGHT:snakeModel.changeDirection(SnakeModel.RIGHT);break;case KeyEvent.VK_ADD:case KeyEvent.VK_PAGE_UP:snakeModel.speedUp();// 加速break;case KeyEvent.VK_SUBTRACT:case KeyEvent.VK_PAGE_DOWN:snakeModel.speedDown();// 减速break;case KeyEvent.VK_SPACE:case KeyEvent.VK_P:snakeModel.changePauseState();// 暂停或继续break;default:}// 重新开始if (keyCode == KeyEvent.VK_R || keyCode == KeyEvent.VK_S|| keyCode == KeyEvent.VK_ENTER) {snakeModel.running = false;begin();}}// ----------------------------------------------------------------------// keyReleased():空函数// ----------------------------------------------------------------------public void keyReleased(KeyEvent e) {}// ----------------------------------------------------------------------// keyTyped():空函数// ----------------------------------------------------------------------public void keyTyped(KeyEvent e) {}// ----------------------------------------------------------------------// repaint():绘制游戏界面(包括蛇和食物)// ----------------------------------------------------------------------void repaint() {Graphics g = paintCanvas.getGraphics();// draw backgroundg.setColor(Color.YELLOW);g.fillRect(0, 0, canvasWidth, canvasHeight);// draw the snakeg.setColor(Color.BLACK);LinkedList na = snakeModel.nodeArray;Iterator it = na.iterator();while (it.hasNext()) {Node n = (Node) it.next();drawNode(g, n);}// draw the foodg.setColor(Color.RED);Node n = snakeModel.food;drawNode(g, n);updateScore();}// ----------------------------------------------------------------------// drawNode():绘画某一结点(蛇身或食物)// ----------------------------------------------------------------------private void drawNode(Graphics g, Node n) {g.fillRect(n.x * nodeWidth, n.y * nodeHeight, nodeWidth - 1,nodeHeight - 1);}// ----------------------------------------------------------------------// updateScore():改变计分牌// ----------------------------------------------------------------------public void updateScore() {String s = "Score: " + snakeModel.score;labelScore.setText(s);}// ----------------------------------------------------------------------// begin():游戏开始,放置贪吃蛇// ----------------------------------------------------------------------void begin() {if (snakeModel == null || !snakeModel.running) {snakeModel = new SnakeModel(this, canvasWidth / nodeWidth,this.canvasHeight / nodeHeight);(new Thread(snakeModel)).start();}}// ----------------------------------------------------------------------// main():主函数// ----------------------------------------------------------------------public static void main(String[] args) {GreedSnake gs = new GreedSnake();}}

package cn.sun;/************************************************************************** *文件名:SnakeModel.java *要点分析: *1)数据结构:matrix[][]用来存储地图上面的信息,如果什么也没有设置为false, * 如果有食物或蛇,设置为true;nodeArray,一个LinkedList,用来保存蛇的每 * 一节;food用来保存食物的位置;而Node类是保存每个位置的信息。 *2)重要函数: * changeDirection(int newDirection) ,用来改变蛇前进的方向,而且只是 * 保存头部的前进方向,因为其他的前进方向已经用位置来指明了。 其中newDirection * 必须和原来的direction不是相反方向,所以相反方向的值用了同样的奇偶性。在测试 * 的时候使用了direction%2!=newDirection%2 进行判断。 * moveOn(),用来更新蛇的位置,对于当前方向,把头部位置进行相应改变。如果越界, * 结束;否则,检测是否遇到食物(加头部)或身体(结束);如果什么都没有,加上头部, * 去掉尾部。由于用了LinkedList数据结构,省去了相当多的麻烦。 *************************************************************************/import java.util.*;import javax.swing.*;//----------------------------------------------------------------------//Node:结点类//----------------------------------------------------------------------class Node {int x;int y;Node(int x, int y) {this.x = x;this.y = y;}}// ----------------------------------------------------------------------// SnakeModel:贪吃蛇模型// ----------------------------------------------------------------------class SnakeModel implements Runnable {GreedSnake gs;boolean[][] matrix;// 界面数据保存在数组里LinkedList nodeArray = new LinkedList();Node food;int maxX;// 最大宽度int maxY;// 最大长度int direction = 2;// 方向boolean running = false;int timeInterval = 200;// 间隔时间(速度)double speedChangeRate = 0.65;// 速度改变程度boolean paused = false;// 游戏状态int score = 0;int countMove = 0;// UP和DOWN是偶数,RIGHT和LEFT是奇数public static final int UP = 2;public static final int DOWN = 4;public static final int LEFT = 1;public static final int RIGHT = 3;// ----------------------------------------------------------------------// GreedModel():初始化界面// ----------------------------------------------------------------------public SnakeModel(GreedSnake gs, int maxX, int maxY) {this.gs = gs;this.maxX = maxX;this.maxY = maxY;matrix = new boolean[maxX][];for (int i = 0; i < maxX; ++i) {matrix[i] = new boolean[maxY];Arrays.fill(matrix[i], false);// 没有蛇和食物的地区置false}// 初始化贪吃蛇int initArrayLength = maxX > 20 ? 10 : maxX / 2;for (int i = 0; i < initArrayLength; ++i) {int x = maxX / 2 + i;int y = maxY / 2;nodeArray.addLast(new Node(x, y));matrix[x][y] = true;// 蛇身处置true}food = createFood();matrix[food.x][food.y] = true;// 食物处置true}// ----------------------------------------------------------------------// changeDirection():改变运动方向// ----------------------------------------------------------------------public void changeDirection(int newDirection) {if (direction % 2 != newDirection % 2)// 避免冲突{direction = newDirection;}}// ----------------------------------------------------------------------// moveOn():贪吃蛇运动函数// ----------------------------------------------------------------------public boolean moveOn() {Node n = (Node) nodeArray.getFirst();int x = n.x;int y = n.y;switch (direction) {case UP:y--;break;case DOWN:y++;break;case LEFT:x--;break;case RIGHT:x++;break;}if ((0 <= x && x < maxX) && (0 <= y && y < maxY)) {if (matrix[x][y])// 吃到食物或者撞到身体{if (x == food.x && y == food.y)// 吃到食物{nodeArray.addFirst(food);// 在头部加上一结点// 计分规则与移动长度和速度有关int scoreGet = (10000 - 200 * countMove) / timeInterval;score += scoreGet > 0 ? scoreGet : 10;countMove = 0;food = createFood();matrix[food.x][food.y] = true;return true;} elsereturn false;// 撞到身体} else// 什么都没有碰到{nodeArray.addFirst(new Node(x, y));// 加上头部matrix[x][y] = true;n = (Node) nodeArray.removeLast();// 去掉尾部matrix[n.x][n.y] = false;countMove++;return true;}}return false;// 越界(撞到墙壁)}// ----------------------------------------------------------------------// run():贪吃蛇运动线程// ----------------------------------------------------------------------public void run() {running = true;while (running) {try {Thread.sleep(timeInterval);} catch (Exception e) {break;}if (!paused) {if (moveOn())// 未结束{gs.repaint();} else// 游戏结束{JOptionPane.showMessageDialog(null, "GAME OVER","Game Over", JOptionPane.INFORMATION_MESSAGE);break;}}}running = false;}// ----------------------------------------------------------------------// createFood():生成食物及放置地点// ----------------------------------------------------------------------private Node createFood() {int x = 0;int y = 0;do {Random r = new Random();x = r.nextInt(maxX);y = r.nextInt(maxY);} while (matrix[x][y]);return new Node(x, y);}// ----------------------------------------------------------------------// speedUp():加快蛇运动速度// ----------------------------------------------------------------------public void speedUp() {timeInterval *= speedChangeRate;}// ----------------------------------------------------------------------// speedDown():放慢蛇运动速度// ----------------------------------------------------------------------public void speedDown() {timeInterval /= speedChangeRate;}// ----------------------------------------------------------------------// changePauseState(): 改变游戏状态(暂停或继续)// ----------------------------------------------------------------------public void changePauseState() {paused = !paused;}}


0 0
原创粉丝点击