java实现贪吃蛇极速版

 更新时间:2021年09月13日 16:01:44   作者:July  
这篇文章主要为大家分享了java贪吃蛇极速版,贪吃蛇经典手机游戏,既简单又耐玩,本文用java来实现下贪吃蛇小游戏,感兴趣的小伙伴可以参考下

Java技术迷

本文为大家推荐了一款由java实现经典小游戏:贪吃蛇,相信大家都玩过,如何实现的呐?

效果图:

废话不多说,直接奉上代码:

1、

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

2、

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

3、

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

4、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package mvcTest;
 
//SnakeView.java
import javax.swing.*;
import java.awt.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
 
 
public class SnakeView implements Observer {
  SnakeControl control = null;
  SnakeModel model = null;
 
  JFrame mainFrame;
  Canvas paintCanvas;
  JLabel labelScore;
 
  public static final int canvasWidth = 200;
  public static final int canvasHeight = 300;
 
  public static final int nodeWidth = 10;
  public static final int nodeHeight = 10;
 
  public SnakeView(SnakeModel model, SnakeControl control) {
    this.model = model;
    this.control = control;
 
    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(control);
    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(control);
    mainFrame.pack();
    mainFrame.setResizable(false);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setVisible(true);
  }
 
  void repaint() {
    Graphics g = paintCanvas.getGraphics();
 
    //draw background
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, canvasWidth, canvasHeight);
 
    // draw the snake
    g.setColor(Color.BLACK);
    LinkedList na = model.nodeArray;
    Iterator it = na.iterator();
    while (it.hasNext()) {
      Node n = (Node) it.next();
      drawNode(g, n);
    }
 
    // draw the food
    g.setColor(Color.RED);
    Node n = model.food;
    drawNode(g, n);
 
    updateScore();
  }
 
  private void drawNode(Graphics g, Node n) {
    g.fillRect(n.x * nodeWidth,
        n.y * nodeHeight,
        nodeWidth - 1,
        nodeHeight - 1);
  }
 
  public void updateScore() {
    String s = "Score: " + model.score;
    labelScore.setText(s);
  }
 
  public void update(Observable o, Object arg) {
    repaint();
  }
}

本文的目的就是带着大家回味经典,但是更主要的目的就是帮助大家学习好java程序设计。

蓄力AI

微信公众号搜索 “ 脚本之家 ” ,选择关注

程序猿的那些事、送书等活动等着你

相关文章

  • springboot + vue 实现递归生成多级菜单(实例代码)

    springboot + vue 实现递归生成多级菜单(实例代码)

    这篇文章主要介绍了springboot + vue 实现递归生成多级菜单,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • spring中使用mybatis实现批量插入的示例代码

    spring中使用mybatis实现批量插入的示例代码

    这篇文章主要介绍了spring中使用mybatis实现批量插入的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • SpringBoot中定位切点的两种常用方法

    SpringBoot中定位切点的两种常用方法

    有时候,我们使用AOP来进行放的增强,编写切面类的时候,需要定位在哪个方法上试用该切面进行增强,本片文章主要讲解两种在SpringBoot中定位切点的方法,感兴趣的可以了解一下
    2021-06-06
  • maven package 打包报错 Failed to execute goal的解决

    maven package 打包报错 Failed to execute goal的解决

    这篇文章主要介绍了maven package 打包报错 Failed to execute goal的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java实现商品的查找、添加、出库、入库操作完整案例

    Java实现商品的查找、添加、出库、入库操作完整案例

    这篇文章主要介绍了Java实现商品的查找、添加、出库、入库操作,结合完整实例形式分析了java基于面向对象的商品信息添加、删除、查找等相关操作技巧,需要的朋友可以参考下
    2019-11-11
  • SpringBoot跨域问题的解决方法实例

    SpringBoot跨域问题的解决方法实例

    这篇文章主要给大家介绍了关于SpringBoot跨域问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • Java Excel数据导入数据库的方法

    Java Excel数据导入数据库的方法

    这篇文章主要为大家详细介绍了Java Excel数据导入数据库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • SpringBoot3整合SpringDoc实现在线接口文档的详细过程

    SpringBoot3整合SpringDoc实现在线接口文档的详细过程

    这篇文章主要介绍了SpringBoot3整合SpringDoc实现在线接口文档的详细过程,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-06-06
  • SpringMVC实现表单验证功能详解

    SpringMVC实现表单验证功能详解

    这篇文章主要为大家详细介绍了SpringMVC 表单验证的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10

最新评论