zoukankan      html  css  js  c++  java
  • java实现贪吃蛇游戏

    最简单的4个java类就可以实现贪吃蛇:

    main函数:

     1 package tcs;
     2 
     3 public class GreedSnake {
     4 
     5 
     6     public static void main(String[] args) {
     7 
     8         SnakeModel model = new SnakeModel(20,30);
     9         SnakeControl control = new SnakeControl(model);
    10         SnakeView view = new SnakeView(model,control);
    11         //添加一个观察者,让view成为model的观察者
    12         model.addObserver(view);
    13 
    14         (new Thread(model)).start();
    15 
    16     }
    17 
    18 }

    控制蛇的移动类:

     1 package tcs;
     2 
     3 import java.awt.event.KeyEvent;
     4 import java.awt.event.KeyListener;
     5 
     6 
     7 public class SnakeControl  implements KeyListener{
     8     SnakeModel model;
     9 
    10     public SnakeControl(SnakeModel model){
    11         this.model = model;
    12     }
    13 
    14     public void keyPressed(KeyEvent e) {
    15         int keyCode = e.getKeyCode();
    16         if (model.running){                // 运行状态下,处理的按键
    17             switch (keyCode) {
    18             case KeyEvent.VK_UP:
    19                 model.changeDirection(SnakeModel.UP);
    20                 break;
    21             case KeyEvent.VK_DOWN:
    22                 model.changeDirection(SnakeModel.DOWN);
    23                 break;
    24             case KeyEvent.VK_LEFT:
    25                 model.changeDirection(SnakeModel.LEFT);
    26                 break;
    27             case KeyEvent.VK_RIGHT:
    28                 model.changeDirection(SnakeModel.RIGHT);
    29                 break;
    30             case KeyEvent.VK_ADD:
    31             case KeyEvent.VK_PAGE_UP:
    32                 model.speedUp();
    33                 break;
    34             case KeyEvent.VK_SUBTRACT:
    35             case KeyEvent.VK_PAGE_DOWN:
    36                 model.speedDown();
    37                 break;
    38             case KeyEvent.VK_SPACE:
    39             case KeyEvent.VK_P:
    40                 model.changePauseState();
    41                 break;
    42             default:
    43             }
    44         }
    45 
    46         // 任何情况下处理的按键,按键导致重新启动游戏
    47         if (keyCode == KeyEvent.VK_R ||
    48                 keyCode == KeyEvent.VK_S ||
    49                 keyCode == KeyEvent.VK_ENTER) {
    50             model.reset();
    51         }
    52     }
    53 
    54     public void keyReleased(KeyEvent e) {
    55     }
    56 
    57     public void keyTyped(KeyEvent e) {
    58     }
    59 }

    蛇实体类:

      1 package tcs;
      2 
      3 import javax.swing.*;
      4 import java.util.Arrays;
      5 import java.util.LinkedList;
      6 import java.util.Observable;
      7 import java.util.Random;
      8 
      9 
     10 class SnakeModel extends Observable implements Runnable {
     11     boolean[][] matrix;                         // 指示位置上有没蛇体或食物
     12     @SuppressWarnings("rawtypes")
     13     LinkedList nodeArray = new LinkedList();    // 蛇体
     14     Node food;
     15     int maxX;
     16     int maxY;
     17     int direction = 2;                          // 蛇运行的方向
     18     boolean running = false;                    // 运行状态
     19 
     20     int timeInterval = 50;                     // 时间间隔,毫秒
     21     double speedChangeRate = 0.75;              // 每次得速度变化率
     22     boolean paused = false;                     // 暂停标志
     23 
     24     int score = 0;                              // 得分
     25     int countMove = 0;                          // 吃到食物前移动的次数
     26 
     27     // UP and DOWN should be even
     28     // RIGHT and LEFT should be odd
     29     public static final int UP = 2;
     30     public static final int DOWN = 4;
     31     public static final int LEFT = 1;
     32     public static final int RIGHT = 3;
     33 
     34     public SnakeModel( int maxX, int maxY) {
     35         this.maxX = maxX;
     36         this.maxY = maxY;
     37 
     38         reset();
     39     }
     40 
     41     @SuppressWarnings("unchecked")
     42     public void reset(){
     43         direction = SnakeModel.UP;              // 蛇运行的方向
     44         timeInterval = 200;                     // 时间间隔,毫秒
     45         paused = false;                         // 暂停标志
     46         score = 0;                              // 得分
     47         countMove = 0;                          // 吃到食物前移动的次数
     48 
     49         // initial matirx, 全部清0
     50         matrix = new boolean[maxX][];
     51         for (int i = 0; i < maxX; ++i) {
     52             matrix[i] = new boolean[maxY];
     53             Arrays.fill(matrix[i], false);
     54         }
     55 
     56         // initial the snake
     57         // 初始化蛇体,如果横向位置超过20个,长度为10,否则为横向位置的一半
     58         int initArrayLength = maxX > 20 ? 10 : maxX / 2;
     59         nodeArray.clear();
     60         for (int i = 0; i < initArrayLength; ++i) {
     61             int x = maxX / 2 + i;//maxX被初始化为20
     62             int y = maxY / 2;    //maxY被初始化为30
     63             //nodeArray[x,y]: [10,15]-[11,15]-[12,15]~~[20,15]
     64             //默认的运行方向向上,所以游戏一开始nodeArray就变为:
     65             //       [10,14]-[10,15]-[11,15]-[12,15]~~[19,15]
     66             nodeArray.addLast(new Node(x, y));
     67             matrix[x][y] = true;
     68         }
     69 
     70         // 创建食物
     71         food = createFood();
     72         matrix[food.x][food.y] = true;
     73     }
     74 
     75     public void changeDirection(int newDirection) {
     76         // 改变的方向不能与原来方向同向或反向
     77         if (direction % 2 != newDirection % 2) {
     78             direction = newDirection;
     79         }
     80     }
     81 
     82 
     83     @SuppressWarnings("unchecked")
     84     public boolean moveOn() {
     85         Node n = (Node) nodeArray.getFirst();
     86         int x = n.x;
     87         int y = n.y;
     88 
     89         // 根据方向增减坐标值
     90         switch (direction) {
     91         case UP:
     92             y--;
     93             break;
     94         case DOWN:
     95             y++;
     96             break;
     97         case LEFT:
     98             x--;
     99             break;
    100         case RIGHT:
    101             x++;
    102             break;
    103         }
    104 
    105         // 如果新坐标落在有效范围内,则进行处理
    106         if ((0 <= x && x < maxX) && (0 <= y && y < maxY)) {
    107 
    108             if (matrix[x][y]) {        // 如果新坐标的点上有东西(蛇体或者食物)
    109                 if (x == food.x && y == food.y) {       // 吃到食物,成功
    110                     nodeArray.addFirst(food);           // 从蛇头赠长
    111 
    112                     // 分数规则,与移动改变方向的次数和速度两个元素有关
    113                     int scoreGet = (10000 - 200 * countMove) / timeInterval;
    114                     score += scoreGet > 0 ? scoreGet : 10;
    115                     countMove = 0;
    116 
    117                     food = createFood();                // 创建新的食物
    118                     matrix[food.x][food.y] = true;      // 设置食物所在位置
    119                     return true;
    120                 } else                                  // 吃到蛇体自身,失败
    121                     return false;
    122 
    123             } else {                 // 如果新坐标的点上没有东西(蛇体),移动蛇体
    124                 nodeArray.addFirst(new Node(x, y));
    125                 matrix[x][y] = true;
    126                 n = (Node) nodeArray.removeLast();
    127                 matrix[n.x][n.y] = false;
    128                 countMove++;
    129                 return true;
    130             }
    131         }
    132         return false;                                   // 触到边线,失败
    133     }
    134 
    135     public void run() {
    136         running = true;
    137         while (running) {
    138             try {
    139                 Thread.sleep(timeInterval);
    140             } catch (Exception e) {
    141                 break;
    142             }
    143 
    144             if (!paused) {
    145                 if (moveOn()) {
    146                     setChanged();           // Model通知View数据已经更新
    147                     notifyObservers();
    148                 } else {
    149                     JOptionPane.showMessageDialog(null,
    150                             "you failed",
    151                             "Game Over",
    152                             JOptionPane.INFORMATION_MESSAGE);
    153                     break;
    154                 }
    155             }
    156         }
    157         running = false;
    158     }
    159 
    160     private Node createFood() {
    161         int x = 0;
    162         int y = 0;
    163         // 随机获取一个有效区域内的与蛇体和食物不重叠的位置
    164         do {
    165             Random r = new Random();
    166             x = r.nextInt(maxX);
    167             y = r.nextInt(maxY);
    168         } while (matrix[x][y]);
    169 
    170         return new Node(x, y);
    171     }
    172 
    173     public void speedUp() {
    174         timeInterval *= speedChangeRate;
    175     }
    176 
    177     public void speedDown() {
    178         timeInterval /= speedChangeRate;
    179     }
    180 
    181     public void changePauseState() {
    182         paused = !paused;
    183     }
    184 
    185     public String toString() {
    186         String result = "";
    187         for (int i = 0; i < nodeArray.size(); ++i) {
    188             Node n = (Node) nodeArray.get(i);
    189             result += "[" + n.x + "," + n.y + "]";
    190         }
    191         return result;
    192     }
    193 }
    194 
    195 class Node {
    196     int x;
    197     int y;
    198 
    199     Node(int x, int y) {
    200         this.x = x;
    201         this.y = y;
    202     }
    203 }

    图形界面:

      1 package tcs;
      2 import javax.swing.*;
      3 import java.awt.*;
      4 import java.util.Iterator;
      5 import java.util.LinkedList;
      6 import java.util.Observable;
      7 import java.util.Observer;
      8 
      9 
     10 public class SnakeView implements Observer {
     11     SnakeControl control = null;
     12     SnakeModel model = null;
     13 
     14     JFrame mainFrame;
     15     Canvas paintCanvas;
     16     JLabel labelScore;
     17 
     18     public static final int canvasWidth = 200;
     19     public static final int canvasHeight = 300;
     20 
     21     public static final int nodeWidth = 10;
     22     public static final int nodeHeight = 10;
     23 
     24     public SnakeView(SnakeModel model, SnakeControl control) {
     25         this.model = model;
     26         this.control = control;
     27 
     28         mainFrame = new JFrame("GreedSnake");
     29 
     30         Container cp = mainFrame.getContentPane();
     31 
     32         // 创建顶部的分数显示
     33         labelScore = new JLabel("Score:");
     34         cp.add(labelScore, BorderLayout.NORTH);
     35 
     36         // 创建中间的游戏显示区域
     37         paintCanvas = new Canvas();
     38         paintCanvas.setSize(canvasWidth + 1, canvasHeight + 1);
     39         paintCanvas.addKeyListener(control);
     40         cp.add(paintCanvas, BorderLayout.CENTER);
     41 
     42         // 创建底下的帮助栏
     43         JPanel panelButtom = new JPanel();
     44         panelButtom.setLayout(new BorderLayout());
     45         JLabel labelHelp;
     46         labelHelp = new JLabel("PageUp, PageDown for speed;", JLabel.CENTER);
     47         panelButtom.add(labelHelp, BorderLayout.NORTH);
     48         labelHelp = new JLabel("ENTER or R or S for start;", JLabel.CENTER);
     49         panelButtom.add(labelHelp, BorderLayout.CENTER);
     50         labelHelp = new JLabel("SPACE or P for pause", JLabel.CENTER);
     51         panelButtom.add(labelHelp, BorderLayout.SOUTH);
     52         cp.add(panelButtom, BorderLayout.SOUTH);
     53 
     54         mainFrame.addKeyListener(control);
     55         mainFrame.pack();
     56         mainFrame.setResizable(false);
     57         mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     58         mainFrame.setVisible(true);
     59     }
     60 
     61     @SuppressWarnings("rawtypes")
     62     void repaint() {
     63         Graphics g = paintCanvas.getGraphics();
     64 
     65         //draw background
     66         g.setColor(Color.WHITE);
     67         g.fillRect(0, 0, canvasWidth, canvasHeight);
     68 
     69         // draw the snake
     70         g.setColor(Color.BLACK);
     71         LinkedList na = model.nodeArray;
     72         Iterator it = na.iterator();
     73         while (it.hasNext()) {
     74             Node n = (Node) it.next();
     75             drawNode(g, n);
     76         }
     77 
     78         // draw the food
     79         g.setColor(Color.RED);
     80         Node n = model.food;
     81         drawNode(g, n);
     82 
     83         updateScore();
     84     }
     85 
     86     private void drawNode(Graphics g, Node n) {
     87         g.fillRect(n.x * nodeWidth,
     88                 n.y * nodeHeight,
     89                 nodeWidth - 1,
     90                 nodeHeight - 1);
     91     }
     92 
     93     public void updateScore() {
     94         String s = "Score: " + model.score;
     95         labelScore.setText(s);
     96     }
     97 
     98     public void update(Observable o, Object arg) {
     99         repaint();
    100     }
    101 }
  • 相关阅读:
    GitHub简单教程
    Git学习笔记
    Bootstrap学习笔记系列7-----Bootstrap简单背景CSS及其他辅助类
    Bootstrap学习笔记系列6-----Bootstrap文本显示
    Bootstrap学习笔记系列5------Bootstrap图片显示
    bootstrap学习笔记系列4------bootstrap按钮
    Bootstrap学习笔记系列3-------Bootstrap简单表单显示
    证件照制作:使用PS打印一寸照片
    CentOS7.6安装JDK(Openjdk)
    CentOS7.6安装JDK(Openjdk)
  • 原文地址:https://www.cnblogs.com/xiayahui/p/5001036.html
Copyright © 2011-2022 走看看