基础版本
新增内容
1.添加START开始界面
点击空格Space即刻开始游戏
2.新增背景音乐
从游戏开始即可尽享音乐直至游戏结束
3.添加SCORE计分
对贪吃蛇吃掉苹果计入分数
4.新增游戏机制
在贪吃蛇超出界面死亡机制基础上增加 贪吃蛇首尾相遇也会判定死亡
代码实现
1. import java.awt.*; 2. import java.awt.event.*; 3. import java.awt.font.TextLayout; 4. import javax.swing.*; 5. import javax.sound.sampled.AudioInputStream; 6. import javax.sound.sampled.AudioSystem; 7. import javax.sound.sampled.Clip; 8. import javax.sound.sampled.LineUnavailableException; 9. import javax.sound.sampled.UnsupportedAudioFileException; 10. import java.io.File; 11. import java.io.IOException; 12. import java.net.URL; 13. 14. public class SnakeGame extends JFrame implements ActionListener { 15. 16. private static final long serialVersionUID = 1L; 17. private boolean gameStarted = false; 18. // 定义游戏区域的大小 19. private final int WIDTH = 640; 20. private final int HEIGHT = 640; 21. 22. // 定义贪吃蛇的初始位置和大小 23. private final int DOT_SIZE = 10; 24. private final int ALL_DOTS = 900; 25. private final int RAND_POS = 30; 26. private int[] x = new int[ALL_DOTS]; 27. private int[] y = new int[ALL_DOTS]; 28. private int dots; 29. private int apple_x; 30. private int apple_y; 31. private int score = 0; 32. 33. // 定义贪吃蛇的移动方向 34. private boolean leftDirection = false; 35. private boolean rightDirection = true; 36. private boolean upDirection = false; 37. private boolean downDirection = false; 38. 39. // 定义游戏是否结束 40. private boolean inGame = true; 41. 42. // 定义计时器 43. private Timer timer; 44. 45. 46. private void loadAudio() { 47. try { 48. String temp="C:/Users/timberman/Desktop/disco.wav"; 49. AudioInputStream audioIn = AudioSystem.getAudioInputStream(new File(temp)); 50. Clip clip = AudioSystem.getClip(); 51. clip.open(audioIn); 52. clip.loop(Clip.LOOP_CONTINUOUSLY); 53. } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) { 54. e.printStackTrace(); 55. } catch (NullPointerException e) { 56. System.err.println("Error: audio file not found or could not be loaded."); 57. } 58. } 59. public SnakeGame() { 60. initGame(); 61. addKeyListener(new KeyAdapter() { 62. @Override 63. public void keyPressed(KeyEvent e) { 64. int key = e.getKeyCode(); 65. if (key == KeyEvent.VK_LEFT && !rightDirection) { 66. leftDirection = true; 67. upDirection = false; 68. downDirection = false; 69. } else if (key == KeyEvent.VK_RIGHT && !leftDirection) { 70. rightDirection = true; 71. upDirection = false; 72. downDirection = false; 73. } else if (key == KeyEvent.VK_UP && !downDirection) { 74. upDirection = true; 75. leftDirection = false; 76. rightDirection = false; 77. } else if (key == KeyEvent.VK_DOWN && !upDirection) { 78. downDirection = true; 79. leftDirection = false; 80. rightDirection = false; 81. } 82. } 83. }); 84. setFocusable(true); 85. } 86. 87. public void initGame() { 88. loadAudio(); 89. // Initialize game area 90. setTitle("SnakeGame"); 91. setSize(WIDTH, HEIGHT); 92. setResizable(false); 93. setDefaultCloseOperation(EXIT_ON_CLOSE); 94. setVisible(true); 95. getContentPane().setBackground(Color.black); 96. 97. // Add start screen 98. JLabel startLabel = new JLabel("Press the space bar to start the game"); 99. startLabel.setForeground(Color.white); 100. startLabel.setBackground(Color.black); 101. startLabel.setFont(new Font("Helvetica", Font.BOLD, 20)); 102. startLabel.setHorizontalAlignment(JLabel.CENTER); 103. startLabel.setVerticalAlignment(JLabel.CENTER); 104. add(startLabel); 105. 106. // Initialize snake and apple positions 107. dots = 3; 108. for (int i = 0; i < dots; i++) { 109. x[i] = 50 - i * DOT_SIZE; 110. y[i] = 50; 111. } 112. locateApple(); 113. 114. // Initialize timer 115. timer = new Timer(140, this); 116. 117. // Add key listener to start game 118. addKeyListener(new KeyAdapter() { 119. @Override 120. public void keyPressed(KeyEvent e) { 121. int key = e.getKeyCode(); 122. if (key == KeyEvent.VK_SPACE && !gameStarted) { 123. // Remove start screen 124. remove(startLabel); 125. gameStarted = true; 126. // Start timer 127. timer.start(); 128. } 129. } 130. }); 131. 132. score = 0; 133. } 134. 135. public void locateApple() { 136. // 随机生成苹果的位置 137. int r = (int) (Math.random() * RAND_POS); 138. apple_x = r * DOT_SIZE; 139. 140. r = (int) (Math.random() * (RAND_POS/2)); // limit apple to top half of game area 141. apple_y = r * DOT_SIZE; 142. } 143. public void checkApple() { 144. // 检查贪吃蛇是否吃到了苹果 145. if ((x[0] == apple_x) && (y[0] == apple_y)) { 146. dots++; 147. locateApple(); 148. score++; 149. setTitle("SnakeGame - Score: " + score); 150. } 151. } 152. 153. public void checkCollision() { 154. // 检查贪吃蛇是否碰到了边界或自己的身体 155. for (int i = dots; i > 0; i--) { 156. if ((i > 4) && (x[0] == x[i]) && (y[0] == y[i])) { 157. inGame = false; 158. } 159. } 160. 161. if (y[0] >= HEIGHT) { 162. inGame = false; 163. } 164. 165. if (y[0] < 0) { 166. inGame = false; 167. } 168. 169. if (x[0] >= WIDTH) { 170. inGame = false; 171. } 172. 173. if (x[0] < 0) { 174. inGame = false; 175. } 176. 177. if (!inGame) { 178. timer.stop(); 179. } 180. } 181. 182. public void move() { 183. // 移动贪吃蛇 184. for (int i = dots; i > 0; i--) { 185. x[i] = x[(i - 1)]; 186. y[i] = y[(i - 1)]; 187. } 188. 189. if (leftDirection) { 190. x[0] -= DOT_SIZE; 191. } 192. 193. if (rightDirection) { 194. x[0] += DOT_SIZE; 195. } 196. 197. if (upDirection) { 198. y[0] -= DOT_SIZE; 199. } 200. 201. if (downDirection) { 202. y[0] += DOT_SIZE; 203. } 204. } 205. 206. public void actionPerformed(ActionEvent e) { 207. // 计时器触发事件 208. if (inGame) { 209. checkApple(); 210. checkCollision(); 211. move(); 212. repaint(); // 重绘游戏区域 213. } 214. } 215. 216. public void paint(Graphics g) { 217. 218. // 绘制游戏区域 219. super.paint(g); 220. 221. if (inGame) { 222. g.setColor(Color.red); 223. g.fillOval(apple_x, apple_y, DOT_SIZE, DOT_SIZE); 224. 225. for (int i = 0; i < dots; i++) { 226. g.setColor(Color.green); 227. g.fillRect(x[i], y[i], DOT_SIZE, DOT_SIZE); 228. } 229. g.setColor(Color.black); 230. Toolkit.getDefaultToolkit().sync(); 231. } else { 232. gameOver(g); 233. } 234. } 235. 236. public void gameOver(Graphics g) { 237. // 游戏结束 238. String msg = "GAME OVER"; 239. Font small = new Font("Helvetica", Font.BOLD, 40); 240. FontMetrics metr = getFontMetrics(small); 241. 242. g.setColor(Color.white); 243. g.setFont(small); 244. g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2, HEIGHT / 2); 245. 246. String scoreMsg = "Final Score: " + score; 247. Font smallScore = new Font("Helvetica", Font.BOLD, 20); 248. FontMetrics scoreMetr = getFontMetrics(smallScore); 249. g.setFont(smallScore); 250. g.drawString(scoreMsg, (WIDTH - scoreMetr.stringWidth(scoreMsg)) / 2, HEIGHT / 2 + 50); 251. 252. } 253. 254. 255. public static void main(String[] args) { 256. new SnakeGame(); 257. } 258. }
实机演示
贪吃蛇PLUS版