1 package greedySnaker;
2
3 import java.awt.Graphics;
4 import java.util.LinkedList;
5
6 /**
7 * 蛇类
8 * @author 俊霖
9 *
10 */
11 public class Snake {
12 private Direction dir = Direction.LEFT;
13 private LinkedList<SnakeNode> list = new LinkedList<SnakeNode>();
14 private boolean isAlive = true;
15 public Snake(){
16 for (int i = 0; i < GameContext.SNAKE_LENGTH; i++) {
17 list.add(new SnakeNode(270 + i * GameContext.SNAKE_SIZE, 290,i == 0));
18 }
19 }
20 /**
21 * 改变蛇的方向
22 * @param dir 新的方向
23 */
24 public void changeDir(Direction newDir) {
25 if (!((dir == Direction.LEFT && newDir == Direction.RIGHT) ||
26 (dir == Direction.RIGHT && newDir == Direction.LEFT) ||
27 (dir == Direction.UP && newDir == Direction.DOWN) ||
28 (dir == Direction.DOWN && newDir == Direction.UP))) {
29 dir = newDir;
30 }
31 }
32 public SnakeNode getHead() {
33 return list.get(0);
34 }
35 public SnakeNode getTail() {
36 return list.get(list.size() - 1);
37 }
38 /**
39 * 移动
40 */
41 public void move(){
42 SnakeNode headNode = getHead();
43 int x = headNode.getX();
44 int y = headNode.getY();
45 int size = GameContext.SNAKE_SIZE;
46 switch (dir) {
47 case UP:
48 y -= size;
49 break;
50 case DOWN:
51 y += size;
52 break;
53 case LEFT:
54 x -= size;
55 break;
56 case RIGHT:
57 x += size;
58 break;
59 }
60 SnakeNode newNode = new SnakeNode(x, y,true);
61 for (SnakeNode snakeNode : list) {
62 snakeNode.setHead(false);
63 }
64 list.addFirst(newNode);
65 }
66 public void remove() {
67 list.removeLast();
68 }
69 /**
70 * 返回到上一步
71 */
72 public void returnBack() {
73 SnakeNode headNode = getTail();
74 int x = headNode.getX();
75 int y = headNode.getY();
76 int size = GameContext.SNAKE_SIZE;
77 switch (dir) {
78 case UP:
79 y += size;
80 break;
81 case DOWN:
82 y -= size;
83 break;
84 case LEFT:
85 x += size;
86 break;
87 case RIGHT:
88 x -= size;
89 break;
90 }
91 SnakeNode newNode = new SnakeNode(x, y);
92 list.addLast(newNode);
93 list.removeFirst();
94 getHead().setHead(true);
95 }
96 /**
97 * 蛇撞到
98 */
99 public void callideSnakeNode() {
100 SnakeNode head = getHead();
101 int headX = head.getX();
102 int headY = head.getY();
103 for (int i = 1; i < list.size(); i++) {
104 if (headX == list.get(i).getX() && headY == list.get(i).getY()) {
105 isAlive = false;
106 }
107 }
108 }
109 /**
110 * 绘制
111 * @param g 画笔工具
112 */
113 public void draw(Graphics g) {
114 for (SnakeNode snakeNode : list) {
115 snakeNode.draw(g);
116 }
117 }
118 /**
119 * 蛇吃蛋
120 * @param egg
121 * @return
122 */
123 public boolean eat(Egg egg) {
124 SnakeNode headNode = getHead();
125 return headNode.getX() == egg.getX() && headNode.getY() == egg.getY();
126 }
127 public Direction getDir() {
128 return dir;
129 }
130 public boolean isAlive() {
131 return isAlive;
132 }
133 public void setAlive(boolean isAlive) {
134 this.isAlive = isAlive;
135 }
136
137
138 }
1 package greedySnaker;
2
3 import java.awt.Color;
4 import java.awt.Graphics;
5
6 public class Egg {
7 private int x,y;
8 private int size = GameContext.EGG_SIZE;
9 public Egg(){
10 int maxX = (GameContext.SQUARER_WIDTH - GameContext.EGG_SIZE) / 20;
11 x = (int) ((int)(Math.random() * maxX) * 20 + GameContext.WALL_X);
12 int maxY = (GameContext.SQUARER_HEIGHT - GameContext.EGG_SIZE) / 20;
13 y = (int) ((int)(Math.random() * maxY) * 20 + GameContext.WALL_Y);
14 }
15 public void draw(Graphics g) {
16 g.setColor(Color.ORANGE);
17 g.fillOval(x, y, size, size);
18 }
19 public int getX() {
20 return x;
21 }
22 public int getY() {
23 return y;
24 }
25
26 }
1 package greedySnaker;
2 /**
3 * 游戏的上下文
4 * @author 俊霖
5 *
6 */
7 public class GameContext {
8 public static final int EGG_SIZE = 20;
9 /**
10 * 蛇的初始长度
11 */
12 public static final int SNAKE_LENGTH = 5;
13 /**
14 * 蛇的速度
15 */
16 public static final int SNAKE_SPEED = 5;
17 /**
18 * 蛇头初始坐标
19 */
20 public static final int SNAKE_X = 270;
21 public static final int SNAKE_Y = 290;
22 /**
23 * 蛇大小
24 */
25 public static final int SNAKE_SIZE = 20;
26 /**
27 * 游戏宽度
28 */
29 public static final int GAME_WIDTH = 600;
30 /**
31 * 游戏高度
32 */
33 public static final int GAME_HEIGHT = 600;
34 /**
35 * 围墙宽度
36 */
37 public static final int SQUARER_WIDTH = 500;
38 /**
39 * 围墙高度
40 */
41 public static final int SQUARER_HEIGHT = 500;
42 /**
43 * 围墙坐标
44 */
45 public static final int WALL_X = 50;
46 public static final int WALL_Y = 50;
47 /**
48 * 刷新间隔时间
49 */
50 public static final int INTERVAL = 200;
51 }
1 package greedySnaker;
2
3 import java.awt.Color;
4 import java.awt.Graphics;
5 /**
6 * 蛇节点类
7 * @author 俊霖
8 *
9 */
10 public class SnakeNode {
11 private int x,y;
12 private int size = GameContext.SNAKE_SIZE;
13 private boolean isHead = false;
14
15 public SnakeNode(int x, int y) {
16 this.x = x;
17 this.y = y;
18 }
19
20 public SnakeNode(int x, int y, boolean isHead) {
21 this.x = x;
22 this.y = y;
23 this.isHead = isHead;
24 }
25
26 public int getX() {
27 return x;
28 }
29 public int getY() {
30 return y;
31 }
32 /**
33 * 绘制蛇节点
34 * @param g 画笔工具
35 */
36 public void draw(Graphics g) {
37 if (!isHead) {
38 g.setColor(Color.GREEN);
39 }else {
40 g.setColor(Color.RED);
41 }
42 g.fillRect(x, y, size, size);
43 g.setColor(Color.BLACK);
44 g.drawRect(x, y, size, size);
45 }
46
47 public void setHead(boolean isHead) {
48 this.isHead = isHead;
49 }
50
51 }
1 package greedySnaker;
2 /**
3 * 方向枚举
4 * @author 俊霖
5 *
6 */
7 public enum Direction {
8 UP,DOWN,LEFT,RIGHT
9 }
1 package greedySnaker;
2
3 import java.awt.BasicStroke;
4 import java.awt.Color;
5 import java.awt.Graphics;
6 import java.awt.Graphics2D;
7 import java.awt.Image;
8 import java.awt.Stroke;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11 import java.awt.event.KeyAdapter;
12 import java.awt.event.KeyEvent;
13 import java.awt.image.BufferedImage;
14
15 import javax.swing.JFrame;
16 import javax.swing.Timer;
17
18
19 @SuppressWarnings("serial")
20 public class GameFrame extends JFrame{
21 private Timer timer;
22 private int score;
23 private int interval = GameContext.INTERVAL;
24 private Egg egg = new Egg();
25 private Snake snake = new Snake();
26 private Image image = new BufferedImage(GameContext.GAME_WIDTH, GameContext.GAME_HEIGHT, BufferedImage.TYPE_INT_RGB);
27 public GameFrame(){
28 this.setTitle("贪吃蛇");
29 this.setSize(GameContext.GAME_WIDTH,GameContext.GAME_HEIGHT);
30 this.setResizable(false);
31 this.setLocationRelativeTo(null);
32 this.setDefaultCloseOperation(EXIT_ON_CLOSE);
33 initComponents();
34 }
35
36 private void initComponents() {
37 this.setLayout(null);
38 timer = new Timer(interval, new ActionListener() {
39
40 @Override
41 public void actionPerformed(ActionEvent e) {
42 snake.move();
43 snake.callideSnakeNode();
44 if (snake.isAlive()) {
45 if (snake.eat(egg)) {
46 egg = new Egg();
47 score += 10;
48 if (score == 100) {
49 interval -= 30;
50 } else if (score == 200) {
51 interval -= 50;
52 } else if (score == 300) {
53 interval -= 50;
54 }
55 } else {
56 snake.remove();
57 }
58 SnakeNode head = snake.getHead();
59 int x = head.getX();
60 int y = head.getY();
61 if (x < GameContext.WALL_X
62 || x > GameContext.WALL_X
63 + GameContext.SQUARER_WIDTH
64 - GameContext.SNAKE_SIZE
65 || y < GameContext.WALL_Y
66 || y > GameContext.WALL_Y
67 + GameContext.SQUARER_HEIGHT
68 - GameContext.SNAKE_SIZE) {
69 timer.stop();
70 snake.setAlive(false);
71 }
72 repaint();
73 }
74 }
75 });
76 timer.start();
77 this.addKeyListener(new KeyAdapter() {
78 @Override
79 public void keyPressed(KeyEvent e) {
80 Direction newDir = snake.getDir();
81 switch (e.getKeyCode()) {
82 case KeyEvent.VK_A:
83 newDir = Direction.LEFT;
84 break;
85 case KeyEvent.VK_D:
86 newDir = Direction.RIGHT;
87 break;
88 case KeyEvent.VK_W:
89 newDir = Direction.UP;
90 break;
91 case KeyEvent.VK_S:
92 newDir = Direction.DOWN;
93 break;
94 case KeyEvent.VK_F2:
95 snake = new Snake(); //重置蛇
96 newDir = Direction.LEFT;//重置方向
97 egg = new Egg(); //重置蛋
98 timer.start();
99 break;
100 }
101 if (snake.getDir() != newDir && snake.isAlive()) {
102 snake.changeDir(newDir);
103 }
104 }
105 });
106 }
107 @Override
108 public void paint(Graphics g) {
109 Graphics2D imageG = (Graphics2D)image.getGraphics();
110 super.paint(imageG);
111 imageG.setColor(Color.BLACK);//内存图片的画笔默认为白色,所以要设置一下画笔颜色
112 Stroke stroke = imageG.getStroke();
113 imageG.setStroke(new BasicStroke(4));
114 imageG.drawRect(GameContext.WALL_X, GameContext.WALL_Y, GameContext.SQUARER_WIDTH, GameContext.SQUARER_HEIGHT);
115 imageG.setStroke(stroke);
116 imageG.setColor(Color.RED);
117 imageG.drawString("得分:" + String.valueOf(score), 50, 40);
118 if (!snake.isAlive()) {
119 snake.returnBack();
120 imageG.setColor(Color.BLACK);
121 imageG.drawString("按F2重置游戏", 280, 40);
122 }
123 snake.draw(imageG);
124 egg.draw(imageG);
125 g.drawImage(image, 0, 0, null);
126 }
127 public static void main(String[] args) {
128 new GameFrame().setVisible(true);
129 }
130 }