一、功能扩展报告
- 使蛇体能够发生移动
- 按键控制蛇体的转向
- 游戏的启止控制
- 食物的随机生成
- 吃到食物蛇体增长
- 吃到食物获得积分
- 头撞到身体后失败
- 蛇体的边界判断
二、预期功能展望
- 问题优化:
- 优化蛇体死亡展示
- 限制蛇体转向
- 功能补充:
- 蛇初始出现的随机性
- 增设食物种类
- 增设失败种类
- 设置自定义图标
三、程序代码展示
1:程序的入口
StartGame.java
代码如下:
package snakegame2;
import javax.swing.*;
//程序启动
public class StartGame2 {
public static void main(String[] args) {
//绘制静态窗口
JFrame frame = new JFrame("贪吃蛇小游戏");
//设置界面的宽高
frame.setSize(965, 655);
//屏幕中央弹出
frame.setLocationRelativeTo(null);
//窗口大小固定
frame.setResizable(false);
//关闭窗口时退出程序
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//添加游戏面板
frame.add(new GamePanel2());
//设置窗体可见
frame.setVisible(true);
}
}
2:程序的主体
GamePanel.java
代码如下:
package snakegame2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
//游戏面板
public class GamePanel2 extends JPanel implements KeyListener, ActionListener {
//一、基本属性
//定义蛇
int length; //蛇体长度
int[] snakeX = new int[800]; //蛇的坐标
int[] snakeY = new int[800];
String order; //方向,"R"(右),"L"(左),"U"(上),"D"(下);
//定义食物
int foodX; //食物的坐标
int foodY;
//实例化Random对象
Random random = new Random();
boolean isStart; //开始判断(默认暂停)
boolean isFail; //死亡判断(默认存活)
//初始化定时器
Timer timer = new Timer(100, this);
//设置积分系统
int score; //积分
int f = 50; //50分
//二、初始化操作
//定义构造器
public GamePanel2() {
init(); //调用初始化方法
//获取键盘监听事件
this.setFocusable(true); //对窗口设置键盘焦点
this.addKeyListener(this); //添加监听器
//启动定时器
timer.start();
}
//定义初始化方法
public void init() {
length = 3; //初始化蛇长(3节)
score = 0; //积分清零
snakeX[0] = 100; //初始化蛇位置
snakeY[0] = 75;
snakeX[1] = 75;
snakeY[1] = 75;
snakeX[2] = 50;
snakeY[2] = 75;
order = "R"; //初始化蛇头方向
//随机生成食物位置
foodX = 25 + 25 * random.nextInt(36);
foodY = 50 + 25 * random.nextInt(22);
}
//三、画板部分:执行绘制操作
@Override
protected void paintComponent(Graphics g) {
//画界面
super.paintComponent(g); //清屏操作
this.setBackground(Color.white); //设置背景颜色
//绘制游戏区域
g.setColor(Color.black);
g.fillRect(25, 50, 900, 550);
//画积分
g.setColor(Color.black); //设置字体颜色
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString("分数:" + (score) + "分", 770, 25);
//根据当前的方向(order)画蛇头
switch (order) {
case "R":
Data2.right.paintIcon(this, g, snakeX[0], snakeY[0]);
break;
case "L":
Data2.left.paintIcon(this, g, snakeX[0], snakeY[0]);
break;
case "U":
Data2.up.paintIcon(this, g, snakeX[0], snakeY[0]);
break;
case "D":
Data2.down.paintIcon(this, g, snakeX[0], snakeY[0]);
break;
}
//画蛇身
for (int i = 1; i < length; i++) {
Data2.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
//画食物
Data2.food.paintIcon(this, g, foodX, foodY);
//交互设置
//游戏开始提示语句(游戏暂停时)
if (!isStart) {
g.setColor(Color.white);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString("按空格键开始游戏", 370, 340);
}
//游戏结束提示语句(游戏失败时)
if (isFail) {
g.setColor(Color.white);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString("游戏结束,本次得分:" + (score) + "分,按空格键重新开始", 230, 340);
}
}
//四、监听器部分:执行键盘操作
@Override
//键盘按下(未释放)
public void keyPressed(KeyEvent e) {
//接收键盘的输入
int keyCode = e.getKeyCode();
//若按下了空格键
if (keyCode == KeyEvent.VK_SPACE) {
//如果结束,按下空格键重新开始
if (isFail) {
isFail = false;
init(); //重新做初始化
} else {
//按下空格键开始/暂停游戏
isStart = !isStart;
}
//刷新(重画)界面
repaint();
}
//('W'/'S'/'A'/'D'键或'up'/'down'/'left'/'right'键)按键控制蛇头转向
if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_A) {
order = "L";
} else if (keyCode == KeyEvent.VK_RIGHT || keyCode == KeyEvent.VK_D) {
order = "R";
} else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_W) {
order = "U";
} else if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_S) {
order = "D";
}
}
//五、定时器部分:执行定时操作
@Override
public void actionPerformed(ActionEvent e) {
//若游戏处于开始状态(且游戏未失败)-->蛇发生移动
if (isStart && !isFail) {
//蛇身移动
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
//蛇头移动
switch (order) {
case "R":
snakeX[0] += 25;
break;
case "L":
snakeX[0] -= 25;
break;
case "U":
snakeY[0] -= 25;
break;
case "D":
snakeY[0] += 25;
break;
}
//边界判断
if (snakeX[0] > 900 || snakeX[0] < 25 || snakeY[0] < 50 || snakeY[0] > 575) {
if (snakeX[0] > 900) {
snakeX[0] = 25;
} else if (snakeX[0] < 25) {
snakeX[0] = 900;
} else if (snakeY[0] < 50) {
snakeY[0] = 575;
} else {
snakeY[0] = 50;
}
}
//游戏失败判定
//蛇头碰到蛇身后失败(循环判定蛇头坐标是否与任一节蛇身重合)
for (int i = 1; i < length; i++) {
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
//判定为失败
isFail = true;
break;
}
}
//蛇吃到食物(坐标重合)后增长/积分
if (snakeX[0] == foodX && snakeY[0] == foodY) {
length++; //蛇身长度加一
score += f; //食物积分
//重新生成食物位置
foodX = 25 + 25 * random.nextInt(36);
foodY = 50 + 25 * random.nextInt(22);
}
//刷新(重画)界面
repaint();
}
//启动定时器
timer.start();
}
@Override
public void keyTyped(KeyEvent keyEvent) {
}
@Override
public void keyReleased(KeyEvent keyEvent) {
}
}
3:存放图片资源
Data.java
代码如下:
package snakegame2;
import javax.swing.*;
import java.net.URL;
//存放数据
public class Data1 {
//导入素材图片
//蛇头图片
private static final URL upURL = Data2.class.getResource("/resources2/up2.jpg"); //上
private static final URL leftURL = Data2.class.getResource("/resources2/left2.jpg"); //左
private static final URL rightURL = Data2.class.getResource("/resources2/right2.jpg"); //右
private static final URL downURL = Data2.class.getResource("/resources2/down2.jpg"); //下
public static ImageIcon up = new ImageIcon(upURL);
public static ImageIcon left = new ImageIcon(leftURL);
public static ImageIcon right = new ImageIcon(rightURL);
public static ImageIcon down = new ImageIcon(downURL);
//蛇身图片
private static final URL bodyURL = Data2.class.getResource("/resources2/body2.jpg");
public static ImageIcon body = new ImageIcon(bodyURL);
//食物图片
private static final URL foodURL = Data2.class.getResource("/resources2/food2.jpg");
public static ImageIcon food = new ImageIcon(foodURL);
}