一、实验要求
1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子,上下左右控制“蛇”的移动,吃到“豆子”以后“蛇”的身体加长一点。
2.“蛇”碰到边界或蛇头与蛇身相撞,蛇死亡,游戏结束。
3.为游戏设计友好的交互界面;例如欢迎界面,游戏界面,游戏结束界面。要有开始键、暂停键和停止退出的选项。
4.对蛇吃到豆子进行分值计算,可以设置游戏速度,游戏音乐等拓展元素。
二、实验分析
注意点:
A.新豆子的生成规则为:
①不能超出游戏区域
②不能在蛇身上
B.游戏结束时的检测规则为:
①蛇是否超出游戏区域
②蛇头是否撞到自己身上
三、实现语言
Java
四、软件代码
SnakeGame类:
package mwy;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SnakeGame extends JFrame implements Runnable {
private static final long serialVersionUID = -6497735513679547494L;
SnakeBorder panel;
JPanel jp;
JLabel lab;
JLabel labScore;
JLabel labRecorde;
JButton btnStart;
JButton btnRestart;
private int bestRecorde = 0;
public SnakeGame() {
super("Sanke Game");
this.setSize(1000, 780);
this.saveData();
this.labScore = new JLabel("当前分数:0");
this.labRecorde = new JLabel(" 当前最佳纪录:" + this.bestRecorde);
this.panel = new SnakeBorder();
int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
this.setLocation((x - this.getWidth()) / 2, (y - this.getHeight()) / 2);
this.lab = new JLabel("提示:按↑、↓、←、→控制方向 ");
this.jp = new JPanel();
this.btnStart = new JButton("点击开始");
this.btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == SnakeGame.this.btnStart && !SnakeGame.this.panel.supe) {
SnakeGame.this.btnStart.setText("点击暂停");
SnakeGame.this.panel.resume();
} else if (e.getSource() == SnakeGame.this.btnStart && SnakeGame.this.panel.supe) {
SnakeGame.this.btnStart.setText("点击继续");
SnakeGame.this.panel.supe = false;
}
}
});
this.btnRestart = new JButton("重新开始");
this.btnRestart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == SnakeGame.this.btnRestart) {
SnakeGame.this.panel.init();
SnakeGame.this.panel.resume();
}
}
});
this.jp.setSize(1000, 25);
this.jp.setBackground(Color.cyan);
this.jp.add(this.lab);
this.jp.add(this.btnStart);
this.jp.add(this.btnRestart);
this.jp.add(this.labScore);
this.jp.add(this.labRecorde);
this.add(this.jp, "North");
this.add(this.panel);
this.btnStart.addKeyListener(this.panel);
this.btnRestart.addKeyListener(this.panel);
this.panel.addKeyListener(this.panel);
this.addKeyListener(this.panel);
this.setDefaultCloseOperation(3);
this.setVisible(true);
Thread t = new Thread(this.panel);
t.start();
Thread s = new Thread(this);
s.start();
}
public static void main(String[] args) {
new SnakeGame();
}
public void run() {
while(true) {
this.labScore.setText("当前分数:" + this.panel.score);
if (this.bestRecorde < this.panel.score) {
this.saveData();
}
}
}
public void saveData() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("Data.txt")));
String str = "";
str = in.readLine();
this.bestRecorde = Integer.parseInt(str);
if (this.bestRecorde <= this.panel.score) {
FileOutputStream fos = new FileOutputStream("Data.txt");
PrintWriter pw = new PrintWriter(fos);
pw.write("" + this.panel.score);
pw.flush();
pw.close();
}
in.close();
} catch (Exception var6) {
try {
FileOutputStream fos1 = new FileOutputStream("Data.txt");
PrintWriter pw1 = new PrintWriter(fos1);
pw1.write("" + this.bestRecorde);
pw1.flush();
pw1.close();
} catch (FileNotFoundException var5) {
var5.printStackTrace();
}
}
}
}
Snake类:
package mwy;
import java.awt.Image;
public class Snake {
public Image image;
public int x;
public int y;
public int dir = 4;
public Snake() {
}
}
SnakeBorder类:
package mwy;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class SnakeBorder extends JPanel implements Runnable, KeyListener {
private static final long serialVersionUID = 1L;
private Snake[] images = new Snake[151];
int score;
Image grey;
Image head;
Image body;
Image food;
private int location = 29;
ArrayList<Snake> snake = new ArrayList();
Snake snakeHead;
Snake snakeFood;
Snake snakeBody;
boolean supe;
long time;
boolean gameover;
public SnakeBorder() {
this.init();
}
public void init() {
this.score = 1;
this.time = 500L;
this.supe = false;
this.gameover = false;
this.snake.clear();
this.grey = (new ImageIcon("pictures/grey.png")).getImage();
this.head = (new ImageIcon("pictures/head_right.png")).getImage();
this.body = (new ImageIcon("pictures/body.png")).getImage();
this.food = (new ImageIcon("pictures/food.png")).getImage();
int k;
for(k = 0; k < 151; ++k) {
this.images[k] = new Snake();
}
k = 1;
for(int i = 30; i < 605; i += 60) {
for(int j = 40; j < 940; j += 60) {
this.images[k].x = j;
this.images[k].y = i;
this.images[k].dir = 4;
++k;
}
}
while(this.location % 15 >= 6 || this.location % 15 < 2 || this.location > 90) {
this.location = (int)(Math.random() * 150.0D);
}
this.snakeHead = new Snake();
this.snakeHead.x = this.images[this.location].x;
this.snakeHead.y = this.images[this.location].y;
this.snakeHead.dir = this.images[this.location].dir;
this.snakeHead.image = this.head;
this.snake.add(this.snakeHead);
this.produceFood();
}
public void paint(Graphics g) {
super.paint(g);
int i;
for(i = 1; i < 151; ++i) {
g.drawImage(this.grey, this.images[i].x, this.images[i].y, (ImageObserver)null);
}
for(i = 0; i < this.snake.size(); ++i) {
g.drawImage(((Snake)this.snake.get(i)).image, ((Snake)this.snake.get(i)).x, ((Snake)this.snake.get(i)).y, (ImageObserver)null);
}
g.drawImage(this.snakeFood.image, this.snakeFood.x, this.snakeFood.y, (ImageObserver)null);
}
private void produceFood() {
boolean judge = false;
while(true) {
while(this.location == 1 || this.location == 15 || this.location == 135 || this.location == 150 || !judge) {
this.location = (int)(Math.random() * 149.0D + 1.0D);
for(int i = 0; i < this.snake.size(); ++i) {
if (this.images[this.location].x == ((Snake)this.snake.get(i)).x && this.images[this.location].y == ((Snake)this.snake.get(i)).y) {
judge = false;
break;
}
judge = true;
}
}
this.snakeFood = new Snake();
this.snakeFood.x = this.images[this.location].x;
this.snakeFood.y = this.images[this.location].y;
this.snakeFood.image = this.food;
return;
}
}
private void eatFood() {
int x = ((Snake)this.snake.get(0)).x;
int y = ((Snake)this.snake.get(0)).y;
if (x < this.snakeFood.x + 20 && x > this.snakeFood.x - 20 && y < this.snakeFood.y + 20 && y > this.snakeFood.y - 20) {
this.snakeBody = new Snake();
if (((Snake)this.snake.get(this.snake.size() - 1)).dir == 1) {
this.snakeBody.x = ((Snake)this.snake.get(this.snake.size() - 1)).x;
this.snakeBody.y = ((Snake)this.snake.get(this.snake.size() - 1)).y + 60;
} else if (((Snake)this.snake.get(this.snake.size() - 1)).dir == 2) {
this.snakeBody.x = ((Snake)this.snake.get(this.snake.size() - 1)).x;
this.snakeBody.y = ((Snake)this.snake.get(this.snake.size() - 1)).y - 60;
} else if (((Snake)this.snake.get(this.snake.size() - 1)).dir == 3) {
this.snakeBody.x = ((Snake)this.snake.get(this.snake.size() - 1)).x + 60;
this.snakeBody.y = ((Snake)this.snake.get(this.snake.size() - 1)).y;
} else if (((Snake)this.snake.get(this.snake.size() - 1)).dir == 4) {
this.snakeBody.x = ((Snake)this.snake.get(this.snake.size() - 1)).x - 60;
this.snakeBody.y = ((Snake)this.snake.get(this.snake.size() - 1)).y;
}
this.snakeBody.image = this.body;
this.snakeBody.dir = ((Snake)this.snake.get(this.snake.size() - 1)).dir;
this.snake.add(this.snakeBody);
++this.score;
if (this.time >= 200L) {
this.time -= 30L;
}
this.produceFood();
this.repaint();
}
}
private void moved() {
int k;
for(k = 0; k < this.snake.size(); ++k) {
if (((Snake)this.snake.get(k)).dir == 1) {
((Snake)this.snake.get(k)).y -= 60;
} else if (((Snake)this.snake.get(k)).dir == 2) {
((Snake)this.snake.get(k)).y += 60;
} else if (((Snake)this.snake.get(k)).dir == 3) {
((Snake)this.snake.get(k)).x -= 60;
} else if (((Snake)this.snake.get(k)).dir == 4) {
((Snake)this.snake.get(k)).x += 60;
}
}
this.eatFood();
for(k = this.snake.size() - 1; k > 0; --k) {
if (((Snake)this.snake.get(k)).dir != ((Snake)this.snake.get(k - 1)).dir) {
((Snake)this.snake.get(k)).dir = ((Snake)this.snake.get(k - 1)).dir;
}
}
}
private void isGameOver() {
int choice;
if (((Snake)this.snake.get(0)).x <= 880 && ((Snake)this.snake.get(0)).x >= 40 && ((Snake)this.snake.get(0)).y >= 30 && ((Snake)this.snake.get(0)).y <= 570) {
for(choice = 1; choice < this.snake.size(); ++choice) {
if (((Snake)this.snake.get(0)).x == ((Snake)this.snake.get(choice)).x && ((Snake)this.snake.get(0)).y == ((Snake)this.snake.get(choice)).y) {
this.gameover = true;
break;
}
}
} else {
this.gameover = true;
}
if (this.gameover) {
choice = JOptionPane.showConfirmDialog(this, "你输了!是否再来一局?", (String)null, 0);
if (choice == 0) {
this.init();
this.resume();
this.repaint();
} else {
System.exit(0);
}
}
}
public void run() {
while(true) {
try {
while(true) {
Thread.sleep(this.time);
synchronized(this) {
while(!this.supe) {
this.wait();
}
this.moved();
this.isGameOver();
if (!this.gameover) {
this.repaint();
}
}
}
} catch (Exception var3) {
var3.printStackTrace();
}
}
}
synchronized void resume() {
this.supe = true;
this.notify();
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 40 && ((Snake)this.snake.get(0)).dir != 1) {
((Snake)this.snake.get(0)).dir = 2;
((Snake)this.snake.get(0)).image = (new ImageIcon("pictures/head_down.png")).getImage();
}
if (e.getKeyCode() == 38 && ((Snake)this.snake.get(0)).dir != 2) {
((Snake)this.snake.get(0)).dir = 1;
((Snake)this.snake.get(0)).image = (new ImageIcon("pictures/head_up.png")).getImage();
}
if (e.getKeyCode() == 37 && ((Snake)this.snake.get(0)).dir != 4) {
((Snake)this.snake.get(0)).dir = 3;
((Snake)this.snake.get(0)).image = (new ImageIcon("pictures/head_left.png")).getImage();
}
if (e.getKeyCode() == 39 && ((Snake)this.snake.get(0)).dir != 3) {
((Snake)this.snake.get(0)).dir = 4;
((Snake)this.snake.get(0)).image = (new ImageIcon("pictures/head_right.png")).getImage();
}
}
public void keyReleased(KeyEvent e) {
}
}
图片合集包pictures:
链接:https://pan.baidu.com/s/1eGva9F0xDm4Hq-r-oU-UvA
提取码:1234
五、运行界面
正常游戏:
碰到边界——游戏结束:
撞到自身——游戏结束: