1.小组成员
陈倩
2.选题与前期调查
选题
贪吃蛇
前期调查
根据小时候玩贪吃蛇的经验知道贪吃蛇游戏的几个选项:开始,暂停,重玩,退出。
3.系统功能设计
1.蛇身:设置蛇的颜色,一节蛇身的大小,随机出现的位置,吃到一个食物蛇身增加一节。
2.食物:设置食物的颜色,大小,随机出现的位置。
3.蛇的移动方向:通过↑,↓,←,→键来控制蛇的移动方向。
4.四个按钮:开始,暂停,重玩,退出。
5.分数:记录得分,吃到一个食物时分数加10。
6.GameOver:贪吃蛇吃到自己的尾巴或撞到边界。
4.功能框架图
5.关键代码
游戏界面(GameUi)
`package com.java.snake;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.*;
public class GameUi extends JFrame {
int flag = 1;
JLabel jl = new JLabel();//GameOver标签
JLabel fs = new JLabel();
JButton start = new JButton("开始");
JButton stop = new JButton("暂停");
JButton restart = new JButton("重玩");
JButton exit = new JButton("退出");
boolean p = true;
JPanel pan = new JPanel();//新建pan对象
GridLayout grid = new GridLayout(1, 5);//网格布局为1行,5列
Random r1 = new Random();
Random r2 = new Random();
//食物的坐标
int a = (r1.nextInt(53) + 1) * 10 - 4;
int b = (r2.nextInt(35) + 6) * 10 - 1;
int score = 0;
int foodNumber = 0;
final int HW = 9;//使用final修饰HW后,不能再对它的值进行修改,食物与一节蛇身的宽度与高度
int x = (r1.nextInt(35) + 10) * 10 - 4;
int y = (r2.nextInt(35) + 6) * 10 - 1;
LinkedList
int direction = 1;
SnakeBody tail;
SnakeBody head;
class Mytask implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
head = snake.getFirst();
/*
* 判断蛇是否吃到食物,如果吃到食物则产生一个随机数,若产生的随机数在蛇的身体上则重新再产生一个随机数
/
if (head.getX() == a && head.getY() == b) {
SnakeBody c = new SnakeBody();
snake.add(c);
++foodNumber;
score += 10;
fs.setText("分数:" + score);//setText将fs对象上面的文字设定为分数:
/ 判断生成的食物是不是在蛇的身体里 */
for (int i = 0; i < snake.size(); i++) {
SnakeBody d = snake.get(i);
if (d.getX() == a && d.getY() == b) {
a = (r1.nextInt(53) + 1) * 10 - 4;
b = (r2.nextInt(35) + 6) * 10 - 1;
}
}
}
int x1 = head.getX();
int y1 = head.getY();
/* 判断是否触到边缘 */
if (x1 < 6 || x1 > 536 || y1 < 59 || y1 > 419) {
gameover();
break ;
}
/* 判断是否吃到自己的身体 */
else {
for (int i = 3; i < snake.size(); i++) {
SnakeBody d = snake.get(i);
if (d.getX() == x1 && d.getY() == y1) {
gameover();
break ;
}
}
}
if (p != false) {
moving(direction);
update(getGraphics());
}
try {
//Thread.sleep(500 - foodNumber / 2 * 100);
//可设置等级,等级不同可以有不同的速度
Thread.sleep(67);//暂停67ms来设置贪吃蛇的移动速度
} catch (Exception e) {
//中断标志已经被清除了,sleep是会擦除中断标志的
}
}
}
private void gameover() {
// TODO Auto-generated method stub
jl.setText("GAME OVER");
jl.setBounds(150, 150, 400,100);//x,y,组件长度,高度
jl.setForeground(Color.red);//文本颜色
jl.setFont(new Font("宋体", Font.BOLD, 55));//创建font对象,使用“宋体”字体,加粗Font.BOLD,字体大小为55
add(jl);
update(getGraphics());//更新图像
}
}
Thread timer = new Thread(new Mytask()); //创建线程对象,把实现了Runnable接口的对象作为参数传入
public GameUi() {
// TODO Auto-generated constructor stub
this.setTitle("我的贪吃蛇");
this.setSize(552, 435);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
initSnakeBody();
initEvent();
fs.setText("分数:" + score);
add(pan, BorderLayout.NORTH);//整个pan放在北侧
pan.setLayout(grid);
//在上面建立的pan对象,放入一下按钮
pan.add(start);
pan.add(stop);
pan.add(restart);
pan.add(exit);
pan.add(fs);
this.requestFocus();//就是把焦点设置在这个按钮this上
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == start) {//e.getSource(),就是获得这个按钮
p = true;
}
GameUi g = getUi();
g.requestFocus();
}
});
stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == stop)
p = false;
}
});
restart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == restart) {
new GameUi();
dispose();//销毁程序中指定的图形界面资源
}
}
});
exit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == exit)
System.exit(EXIT_ON_CLOSE);//使用System exit方法退出应用程序
}
});
timer.start();
}
protected GameUi getUi() {
return this;
}
@Override
/* 画边缘,蛇身,食物 */
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
Graphics2D g_2d = (Graphics2D) g;
g_2d.setColor(Color.BLACK);
g_2d.setStroke(new BasicStroke(2f));//设置画笔的宽度. 越大,边框越粗
//起始端点x,y坐标,终点端点x,y的坐标
g_2d.drawLine(5, 58, 547, 58);// 上面的那根线
g_2d.drawLine(5, 58, 5, 430);// 左边的那根线
g_2d.drawLine(5, 430, 547, 430);// 下面的那根线
g_2d.drawLine(547, 58, 547, 430);// 右边的那根线
g_2d.setColor(Color.black);
//画蛇身
for (int i = 0; i < snake.size(); i++) {
SnakeBody b = snake.get(i);
g.fillRect(b.getX(), b.getY(), HW, HW);
}
//画食物
g.setColor(Color.red);
g.fillRect(a, b, HW, HW);//a,b左上角的坐标,宽度高度
}
Image ImageBuffer = null;
Graphics GraImage = null;
@Override
public void update(Graphics g) {
// TODO Auto-generated method stub
ImageBuffer = createImage(this.getWidth(), this.getHeight());
GraImage = ImageBuffer.getGraphics(); // 获取图形缓冲区的图形上下文
paint(GraImage); // 用paint方法中编写的绘图过程对图形缓冲区绘图
GraImage.dispose(); // 释放图形上下文资源
g.drawImage(ImageBuffer, 0, 0, this); // 将图形缓冲区绘制到屏幕上
}
/* 初始化蛇身 */
public void initSnakeBody() {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {
SnakeBody b = new SnakeBody();
b.setX(x + i * HW + i);
b.setY(y);
snake.add(b);
}
tail = snake.getLast();
head = snake.getFirst();
}
/* 蛇移动的时候身体的变化 */
public void moving(int direction) {
tail = snake.removeLast();
head = snake.getFirst();
switch (direction) {
// 1:左;2:上;3:右;4:下
case 1:
tail.setX(head.getX() - HW - 1);
tail.setY(head.getY());
break;
case 2:
tail.setX(head.getX());
tail.setY(head.getY() - HW - 1);
break;
case 3:
tail.setX(head.getX() + HW + 1);
tail.setY(head.getY());
break;
case 4:
tail.setX(head.getX());
tail.setY(head.getY() + HW + 1);
break;
}
snake.addFirst(tail);//在蛇身的首部插入元素tail
}
/* 方向控制 */
public void initEvent() {
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
// TODO Auto-generated method stub
switch (event.getKeyCode()) {
case KeyEvent.VK_UP:
if (direction == 2 || direction == 4) {
break;
}
direction = 2;
break;
case KeyEvent.VK_DOWN:
if (direction == 2 || direction == 4) {
break;
}
direction = 4;
break;
case KeyEvent.VK_LEFT:
if (direction == 1 || direction == 3) {
break;
}
direction = 1;
break;
case KeyEvent.VK_RIGHT:
if (direction == 1 || direction == 3) {
break;
}
direction = 3;
break;
}
}
});
}
}`
蛇身(SnakeBody)
`package com.java.snake;
import java.awt.Color;
public class SnakeBody {
private int x;
private int y;
private Color color;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}`
Test
package com.java.snake;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new GameUi();
}
}
6.运行结果
7.界面
GUI
8.开发工具
Eclipse