<p>class Control代码:</p><p>import java.awt.event.KeyEvent;</p>import java.awt.event.KeyListener; public class Control implements KeyListener { //对键盘进行监听 SnakeModel snake=null; public Control(SnakeModel snake) { this.snake=snake; } @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_UP){ snake.changeDirection(SnakeModel.UP); } if(e.getKeyCode()==KeyEvent.VK_DOWN){ //监听按键↓,向下移动 snake.changeDirection(SnakeModel.DOWN); } if(e.getKeyCode()==KeyEvent.VK_LEFT){ //监听按键←,向左移动 snake.changeDirection(SnakeModel.LEFT); } if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //监听按键↑,向上移动 snake.changeDirection(SnakeModel.RIGHT); } if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //监听按键→,向右移动 snake.changeDirection(SnakeModel.RIGHT); } if(e.getKeyCode()==KeyEvent.VK_R){//监听按键R,重置 snake.reStart(); } } @Override public void keyTyped(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) {} }
class SnakeModel 代码:
<pre name="code" class="java">import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.Timer; import cn.hncu.xh.Snake.snakePoint.point; /* * 思路: 利用动态数组装蛇模型,蛇身的点都只跟着蛇头(即:数组的第一个元素)动, * 每 repaint()一次,就把动态数组里面的蛇全部数出来。 * 每吃一个食物时,就添加在蛇头,蛇头往后移动一步,然后蛇身跟着移动。 * 注意:在蛇吃到食物时,要避免捆绑!!! */ public class SnakeModel extends Canvas implements ActionListener { private snakePoint[] snakePoint; //装蛇的数组 private static Timer timer; //定时器 private static int score = 0; //分数 private int Dx, Dy;// 蛇头所在坐标 private int Px, Py; //食物的坐标 static final int LEFT = 1; static final int UP = 2; static final int DOWN = 4; static final int RIGHT = 3; int direction = 4; //初始方向为向下移动 boolean isFrist = true; //控制第一个食物的位置 boolean isOne = true; //控制每次刷新一次蛇只能按一次键盘 boolean food; //控制没吃到一个食物才去刷新食物的坐标 public SnakeModel(int delay) {// 构造蛇模型 this.snakePoint = new snakePoint[300]; // 用来装蛇头 snakePoint[1] = new snakePoint(100, 100);// 画蛇头 // 使用定时器 timer = new Timer(delay, this); timer.start(); } public static int getScore() { // 获取分数 return score; } class snakePoint { //蛇身(每条蛇由很多蛇身构成) int x, y; public snakePoint(int x, int y) { this.x = x; this.y = y; } snakePoint(snakePoint p) { this.x = p.x; this.y = p.y; } } @Override public void paint(Graphics g) { //食物 creatFood(); // 每走一次就让数组自动移动一次 if (score != 0) { for (int i = score + 2; i > 1; i--) { snakePoint[i] = new snakePoint(snakePoint[i - 1]); } } switch (direction) {// 判断蛇头的走向 case UP: snakePoint[1].y -= 10; break; case DOWN: snakePoint[1].y += 10; break; case LEFT: snakePoint[1].x -= 10; break; case RIGHT: snakePoint[1].x += 10; break; } // 吃到了食物 //要考虑食物的坐标不可能与蛇头坐标重合 if (snakePoint[1].x <= Px + 7 && snakePoint[1].x >= Px - 5 && snakePoint[1].y <= Py + 7 && snakePoint[1].y >= Py - 5) { score++; // 分数加一 food = true; // 刷新食物 SnakeMain.re(); // 刷新分数 timer.setDelay((timer.getDelay() - 4) <= 0 ? 20 : timer.getDelay() - 4); //每次吃到食物后就会加速蛇的移动速度 // System.out.println(timer.getDelay()); // 吃掉一个食物后,在蛇头增加一个长度 for (int j = score + 1; j > 1; j--) { snakePoint[j] = new snakePoint(snakePoint[j - 1]); } // 让蛇头往移动方向走一步 switch (direction) {// 判断蛇头的走向 case UP: snakePoint[1].y -= 10; break; case DOWN: snakePoint[1].y += 10; break; case LEFT: snakePoint[1].x -= 10; break; case RIGHT: snakePoint[1].x += 10; break; } } g.setColor(Color.RED);//食物为红色 g.fillRect(Px, Py, 10, 10);// 画食物 g.setColor(Color.BLACK);//蛇为黑色 // 画蛇,把蛇从数组中画出来 for (int i = 1; i <= score + 1; i++) { g.fillRect(snakePoint[i].x, snakePoint[i].y, 10, 10); } } private void creatFood() { if (isFrist) { Px = legal(380);// 获得合法的x值, Py = legal(330);// 获得合法的y值,即与x组合成食物坐标后不在蛇身上 isFrist = false; return; } // 下一个食物坐标 if (food) { Px = legal(380);//同上 Py = legal(330); food = false; } // System.out.println(Px); // System.out.println(Py); } private int legal(int i) { Random r = new Random(); //生成随机数 if (i == 380) { //生成食物的y坐标 while (true) { int n = (r.nextInt(37) + 1) * 10; for (int j = 1; j <= score + 1; j++) { //每次都要与蛇身进行匹配,避免食物出现在蛇身上;下同 if (snakePoint[j].x != n && j == (score + 1)) { return n; } } } } if (i == 330) { //生成食物的x坐标 while (true) { int n = (r.nextInt(32) + 1) * 10; for (int j = 1; j <= score + 1; j++) { if (snakePoint[j].y != n && j == (score + 1)) { return n; } } } } return 0; } @Override public void actionPerformed(ActionEvent e) { isOver();// 判断是否结束游戏 repaint(); isOne = true; // System.out.println(snakePoint[1].x+" "+snakePoint[1].y); } private void isOver() { if (isCondition()) {// isCondition()//判断是否结束的所有条件放在里面 timer.stop(); SnakeMain.gameOver(); // 游戏结束,弹出对话框 } } private boolean isCondition() { //游戏结束的条件 // 出界(撞墙) if (snakePoint[1].x <= 0 || snakePoint[1].x >= 380 || snakePoint[1].y <= 0 || snakePoint[1].y >= 330) { return true; } //蛇头吃到蛇身了 for (int i = 2; i <= score + 1; i++) { if (snakePoint[1].x == snakePoint[i].x && snakePoint[1].y == snakePoint[i].y) { return true; } } return false; } public void changeDirection(int newDirection) { // 改变方向 if (direction % 2 != newDirection % 2 && isOne) {// 改变的方向不能与原来的方向相同或相反 direction = newDirection; isOne = false; } } public static void stop() { timer.stop(); } public static void start() { timer.start(); } //重置所有的数据 public void reStart(){ score=0; direction = 4; isFrist = true; isOne = true; food=false; // snakePoint=null; snakePoint[1].x=100; snakePoint[1].y=100; creatFood(); timer.start(); } }
class SnakeMain 代码:
<pre name="code" class="java">import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; public class SnakeMain extends JFrame implements ActionListener { private static JTextField scoreField; private JButton stop,start; public static void main(String[] args) { new SnakeMain(); } public SnakeMain() { super("贪吃蛇"); this.setBounds(300, 100, 400, 400); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setResizable(false); JPanel p = new JPanel(); this.getContentPane().add(p, "North"); p.add(new JLabel("Score:")); scoreField = new JTextField("0", 5); scoreField.setEditable(false); stop = new JButton("stop"); start = new JButton("start"); // 让这些组件丢失焦点 scoreField.setFocusable(false); stop.setFocusable(false); start.setFocusable(false); //添加组件到面板p p.add(scoreField); p.add(stop); p.add(start); SnakeModel snake = new SnakeModel(400);// 500为刷新时间 this.getContentPane().add(snake); // 把蛇加入到面板中 (蛇的运行范围:0<=x<=380 // 0<=y<=330) Control control = new Control(snake); // 控制蛇 // 进行监听 stop.addActionListener(this); start.addActionListener(this); this.addKeyListener(control); // 显示 this.setVisible(true); } public static void re() { // 刷新分数框 scoreField.setText("" + SnakeModel.getScore()); } public static void gameOver() {// 游戏结束 JOptionPane.showMessageDialog(null, "Game Over!!!"); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == stop) { SnakeModel.stop(); } if (e.getSource() == start) { SnakeModel.start(); } } }