- 有个食物的坐标,食物的坐标是随机的
- 写食物的初始化数据
- 把食物画在面板上
- 在事件监听里面,判断食物的状态


1 package com.gui.snake;
2
3 import javax.swing.*;
4 import java.awt.*;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.awt.event.KeyEvent;
8 import java.awt.event.KeyListener;
9 import java.util.Random;
10
11 //游戏的面板
12 public class GamePanel extends JPanel implements KeyListener, ActionListener {
13
14 //定义蛇的数据结构
15 int length; //蛇的长度
16 int[] snakeX = new int[600]; //蛇的x坐标 25*25
17 int[] snakeY = new int[500]; //蛇的Y坐标 25*25
18 String fx;
19
20 //食物的坐标
21 int foodx;
22 int foody;
23 Random random = new Random();
24
25 //游戏当前的状态:开始、停止
26 boolean isStart = false; //默认是不开始
27
28 //定时器 以毫秒为单位 1000ms = 1s
29 Timer timer = new Timer(100, this);//100ms执行一次
30
31 //构造器
32 public GamePanel() {
33 init();
34 //获得焦点和键盘事件
35 this.setFocusable(true);//获得焦点事件
36 this.addKeyListener(this);//获得键盘监听事件:写的当前这个类,所以是this如果是其他类的话,去new一个监听器
37 timer.start();//游戏一开始,就让定时器启动
38 }
39
40 //初始化方法
41 public void init() {
42 length = 3;
43 snakeX[0] = 100;snakeY[0] = 100;//脑袋的坐标
44 snakeX[1] = 75 ;snakeY[1] = 100;//第一个身体的坐标
45 snakeX[2] = 50 ;snakeY[2] = 100;//第二个身体的坐标
46 fx = "R";//初始方向向右
47
48 //把食物随机分配在界面上
49 foodx = 25 + 25 * random.nextInt(34);
50 foody = 75 + 25 * random.nextInt(24);
51 }
52
53 //绘制面板,我们游戏中的所有东西,都是用这个画笔来画。 Ctrl+O,画组件
54 @Override
55 protected void paintComponent(Graphics g) {
56 super.paintComponent(g);//清屏的作用,不用会闪烁
57 //绘制静态的面板
58 this.setBackground(Color.WHITE);
59 Data.header.paintIcon(this, g, 25, 11);//头部广告栏画上去
60 g.fillRect(25, 75, 850, 600);//默认游戏界面
61
62 //把小蛇画上去
63 if (fx.equals("R")) {
64 Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右,需要通过方向来判断
65 } else if (fx.equals("L")) {
66 Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
67 } else if (fx.equals("U")) {
68 Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
69 } else if (fx.equals("D")) {
70 Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
71 }
72
73 for (int i = 1; i < length; i++) {
74 Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);//蛇的身体
75 }
76
77 //画食物
78 Data.food.paintIcon(this,g,foodx,foody);
79
80
81 //游戏状态
82 if (isStart == false) {
83 g.setColor(Color.white);
84 g.setFont(new Font("楷体", Font.BOLD, 40));
85 g.drawString("按下空格开始游戏", 300, 300);
86 }
87 }
88
89
90 //键盘监听事件
91 @Override
92 public void keyPressed(KeyEvent e) {
93 int keyCode = e.getKeyCode();//获得键盘按键是哪一个
94 if (keyCode == KeyEvent.VK_SPACE) {//如果按下的是空格键
95 isStart = !isStart;//取反
96 repaint();//重新绘制,因为值已经变化了
97 }
98 //小蛇移动
99 if (keyCode == KeyEvent.VK_UP) {
100 fx = "U";
101 } else if (keyCode == KeyEvent.VK_DOWN) {
102 fx = "D";
103 } else if (keyCode == KeyEvent.VK_LEFT) {
104 fx = "L";
105 } else if (keyCode == KeyEvent.VK_RIGHT) {
106 fx = "R";
107 }
108 }
109
110 //事件监听---需要通过固定的时间来刷新,1s=10次
111 @Override
112 public void actionPerformed(ActionEvent e) {
113 if (isStart) {//如果游戏是开始状态,就让小蛇动起来!
114
115 //吃食物
116 if(snakeX[0] == foodx && snakeY[0] == foody){
117 length++;//长度 + 1
118 //再次随机食物
119 foodx = 25 + 25 * random.nextInt(34);
120 foody = 75 + 25 * random.nextInt(24);
121 }
122
123 //移动
124 for (int i = length - 1; i > 0; i--) {//后一节移到前一节的位置 snake[1] = snake [0];
125 snakeX[i] = snakeX[i - 1];
126 snakeY[i] = snakeY[i - 1];
127 }
128
129 //走向
130 if (fx.equals("R")) {
131 snakeX[0] = snakeX[0] + 25;
132 if (snakeX[0] > 850) { snakeX[0] = 25; }//边界判断
133 } else if (fx.equals("L")) {
134 snakeX[0] = snakeX[0] - 25;
135 if (snakeX[0] < 25) { snakeX[0] = 850; }//边界判断
136 } else if (fx.equals("U")) {
137 snakeY[0] = snakeY[0] - 25;
138 if (snakeY[0] < 75) { snakeY[0] = 650; }//边界判断
139 } else if (fx.equals("D")) {
140 snakeY[0] = snakeY[0] + 25;
141 if (snakeY[0] > 650) { snakeY[0] = 75; }//边界判断
142 }
143
144 repaint();//重画页面
145 }
146 timer.start();
147 }
148
149 @Override
150 public void keyReleased(KeyEvent e) {
151 }
152
153 @Override
154 public void keyTyped(KeyEvent e) {
155 }
156 }
测试效果:
存在问题:
- 会出现一个重叠上去的感觉,因为画的话两个是在同一个界面上,我们是判断这两个点相同的时候,才给它干掉的.他有个闪烁的问题。
- 脑袋能在自己身体里边走,来回穿梭,这个也不行.所以应该做一件事情,把失败判定上去。