(贪吃蛇)
需求说明书
完成日期:2024年 07月15日 | |||
编制:一只普通柚子 日期:7月15日 | 审核:一只普通柚子 日期:7月15日 | 批准:一只普通柚子 日期:7月15日 | |
目录
1. 任务概述....................................................... 3
1.1. 目标........................................................ 3
1.2. 系统(或用户)的特点................... 3
2. 假定和约束................................................... 3
3. 需求规定....................................................... 3
3.1. 软件功能说明..................................... 3
3.2. 对功能的一般性规定........................ 3
3.3. 对性能的一般性规定........................ 4
3.4. 其他专门要求..................................... 4
3.5. 对安全性的要求................................. 4
4. 运行环境规定............................................... 4
4.1. 设备及分布.......................................... 4
4.2. 支撑软件............................................... 4
4.3. 接口........................................................ 4
4.4. 程序运行方式..................................... 5
5. 尚需解决的问题........................................... 5
开发意图:提供一个简单有趣,易上手的贪吃蛇游戏,以满足用户在休闲娱乐时的需求。
应用目标:进行贪吃蛇游戏;含各种难度级别的游戏模式;适用于不同年龄阶段的用户;确保游戏在不同系统都可以正常运行;保证游戏流畅,占有空间小,响应快。
作用范围:
1.休闲娱乐,消磨时间。
2.挑战自我,提高反应速度和策略规划能力。
3.用于社交,与朋友进行分数比较和挑战。
开发背景:
在暑期里复习GUI编程,提高专业能力。
-
- 系统(或用户)的特点
- 难度多样化:包含简单,正常,困难三种模式。
- 个性化设置:允许用户自定义游戏内皮肤,以适应个人偏好
本产品预计四天完成。
3.1.1 软件功能列表
- 游戏主系统:
功能1:控制贪吃蛇移动
功能2:吃食物增加长度
功能3:碰撞检测(墙壁或自身)
功能4:游戏结束判定
- 游戏难度子系统
功能1:简单 200ms
功能2:正常 100ms
功能3:困难 40ms
- 用户设置子系统
功能1:更改游戏皮肤
3.1.2 主要业务流程分析
- 启动游戏:用户打开游戏软件,进入主界面。
- 选择模式:用户通过鼠标点击左下方按钮选择游戏难度。
- 控制移动:用户通过键盘控制贪吃蛇移动方向。
- 吃食物:贪吃蛇吃到食物,长度增加,食物再次随机刷新。
- 游戏结束:贪吃蛇撞墙或撞到自身,游戏结束。
3.1.3 软件部署结构分析
-
- 对功能的一般性规定
- 用户界面一致性设计,游戏界面为900*750。
- 响应式设计:键盘操作时有视觉反馈。
- 响应速度快,用户操作后可迅速给出反馈。
- 稳定性强:长时间运行时不会出现错误异常等情况。
- 数据安全
- 多平台兼容Windows,macOS,Linux,iOS,Android在安装JDK后都可运行
- 保证在各种情况下软件能够稳定运行。
- 对数据进行保护,确保用户输入的数据不会被非法获取,篡改和泄露。
- 合理设置权限,只有授权的操作才能被执行。
主机类型:个人计算器
网络类型:有线网络,无线网络,移动网络,离线都可以运行。
存贮器容量:几百KB到几MB左右
其他特殊设备:外接键盘
设备分布图:
-
- 支撑软件
操作系统:Windows操作系统。
数据库管理系统:简单的计算器代码不需要用到数据库管理系统。
其他支撑软件:集成开发环境(IDE)。
独立运行程序
- 尚需解决的问题
问题1:游戏地图相对简单,更多游戏地图待开发 |
问题2:现阶段只适用于java运行环境,并未打包为程序应用 |
问题3:游戏在高难度下是否会出现不支持的情况 |
问题4:还不能帮助用户存储,查询,管理历史成绩 |
代码实现
package YMP.GUI.Snake; import javax.swing.*; //游戏的主启动类 public class startGame { public static void main(String[] args) { JFrame frame=new JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setBounds(10,10,900,750); frame.setResizable(false);//设置窗口大小不可变 frame.setTitle("贪吃蛇"); //正常的游戏界面是在游戏面板上! frame.add(new gamePanel()); frame.setVisible(true); } }
package YMP.GUI.Snake; 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 gamePanel extends JPanel implements KeyListener , ActionListener { //定义蛇的数据结构 int length;//蛇的长度 int []snakeX=new int[600];//蛇的X坐标25*25 int []snakeY=new int[500];//蛇的Y坐标25*25 //方向 String orientation; //食物的坐标 int foodX; int foodY; Random random=new Random(); //成绩 int score; //游戏当前的状态:开始,停止 boolean isStart=false;//默认停止! //游戏失败状态 boolean isFaild=false; //定时器,以毫秒为单位 Timer timer=new Timer(100,this);//100毫秒执行一次 //构造器 public gamePanel(){ this.setLayout(null); init(); //获得焦点和键盘事件 this.setFocusable(true);//获得焦点事件 this.addKeyListener(this);//获得键盘监听事件 timer.start();//游戏一开始定时器就启动 //菜单按钮 JButton button=new JButton(); button.setIcon(Data.set); button.setBackground(Color.white); button.setFocusable(false); ButtonGroup buttonGroup=new ButtonGroup(); JDialog dialog=new JDialog(); dialog.setSize(400,400); dialog.setTitle("更多"); dialog.setFont(new Font("宋体",Font.BOLD,24)); dialog.setLayout(new GridLayout(3,3)); JCheckBox checkboxNormal=new JCheckBox("难度:正常"); JCheckBox checkboxSimple=new JCheckBox("难度:简单"); JCheckBox checkboxDifficlty=new JCheckBox("难度:困难"); checkboxNormal.setFont(new Font("宋体",Font.BOLD,24)); checkboxDifficlty.setFont(new Font("宋体",Font.BOLD,24)); checkboxSimple.setFont(new Font("宋体",Font.BOLD,24)); buttonGroup.add(checkboxNormal); buttonGroup.add(checkboxSimple); buttonGroup.add(checkboxDifficlty); dialog.add(checkboxNormal); dialog.add(checkboxSimple); dialog.add(checkboxDifficlty); checkboxNormal.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { timer.setDelay(100); } }); checkboxSimple.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { timer.setDelay(200); } }); checkboxDifficlty.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { timer.setDelay(40); } }); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dialog.setVisible(true); } }); button.setBounds(10,680,32,32); this.add(button); } //初始化方法 public void init(){ length=3; snakeX[0]=100; snakeY[0]=100;//脑袋的坐标 snakeX[1]=75; snakeY[1]=100;//第一个身体的坐标 snakeX[2]=50; snakeY[2]=100;//第二个身体的坐标 orientation="R";//初始方向向右 //把食物随机分布在界面上 foodX=25+25*random.nextInt(34); foodY=75+25*random.nextInt(24); //初始成绩 score=0; } //绘制面板,游戏所有东西使用此方法的画笔来画 @Override protected void paintComponent(Graphics g) { super.paintComponent(g);//清屏 this.setBackground(Color.white); //绘制静态面板 Data.header.paintIcon(this,g,25,0);//头部广告栏 g.fillRect(25,75,850,600);//默认的游戏界面 //画积分 g.setColor(new Color(0x72D9E2)); g.setFont(new Font("宋体",Font.BOLD,18)); g.drawString("长度"+length,450,30); g.drawString("分数"+score,450,55); //画食物 Data.food.paintIcon(this,g,foodX,foodY); //把小蛇放上去 if (orientation.equals("R")){ Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//脑袋初始化向右,通过方向来判断 }else if (orientation.equals("L")){ Data.left.paintIcon(this,g,snakeX[0],snakeY[0]); }else if (orientation.equals("U")){ Data.up.paintIcon(this,g,snakeX[0],snakeY[0]); }else if (orientation.equals("D")){ Data.down.paintIcon(this,g,snakeX[0],snakeY[0]); } //身体生成 for (int i=1;i<length;i++){ Data.body.paintIcon(this,g,snakeX[i],snakeY[i]); } //游戏状态 if(isStart==false){ g.setColor(Color.white); //设置字体 g.setFont(new Font("宋体",Font.BOLD,40)); g.drawString("按下空格开始游戏",300,300); } //游戏失败 if(isFaild==true){ g.setColor(Color.red); g.setFont(new Font("宋体",Font.BOLD,40)); g.drawString("失败,按下空格重新开始",300,300); } } //事件监听--需要通过固定的事件来判断,1s-10此 @Override public void actionPerformed(ActionEvent e) { if(isStart && isFaild==false){//如果游戏是开始状态,就让小蛇动起来 //吃食物 if (snakeX[0]==foodX&&snakeY[0]==foodY){ length++;//长度加一 score=score+10;//分数加10 //再次随机食物 foodX=25+25*random.nextInt(34); foodY=75+25*random.nextInt(24); } //移动 for (int i=length-1;i>0;i--){ snakeX[i]=snakeX[i-1];//向前移动一节 snakeY[i]=snakeY[i-1]; } //走向 if (orientation.equals("R")){ snakeX[0]=snakeX[0]+25; //边界判断 if ((snakeX[0]>850)){ snakeX[0]=25; } } else if (orientation.equals("L")) { snakeX[0]=snakeX[0]-25; //边界判断 if(snakeX[0]<25){ snakeX[0]=850; } } else if (orientation.equals("U")) { snakeY[0]=snakeY[0]-25; //边界判断 if (snakeY[0]<75){ snakeY[0]=650; } } else if (orientation.equals("D")) { snakeY[0]=snakeY[0]+25; //边界判断 if (snakeY[0]>650){ snakeY[0]=75; } } //失败判定,撞到自己算失败 for (int i=1;i<length;i++){ if (snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]){ isFaild=true; } } repaint(); } timer.start(); } @Override public void keyTyped(KeyEvent e) { } //键盘监听器 @Override public void keyPressed(KeyEvent e) { int keyCode=e.getKeyCode();//获得键盘按键是哪一个 if(keyCode==KeyEvent.VK_SPACE){//如果按下的是空格键 if(isFaild){ //重新开始 isFaild=false; init(); } else { isStart=!isStart;//取反 } repaint(); } //小蛇移动,向下时不能向上撞自己,同理。 if (keyCode==KeyEvent.VK_UP && orientation!="D"){ orientation="U"; } else if (keyCode==KeyEvent.VK_DOWN && orientation!="U") { orientation="D"; } else if (keyCode==KeyEvent.VK_LEFT && orientation!="R") { orientation="L"; } else if (keyCode==KeyEvent.VK_RIGHT && orientation!="L") { orientation="R"; } } @Override public void keyReleased(KeyEvent e) { } }
package YMP.GUI.Snake; import javax.swing.*; import java.awt.*; import java.net.URL; //数据中心 public class Data { //相对路径 //绝对路径 / 相当于当前的项目 public static ImageIcon header=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\header.png"); public static ImageIcon up=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\up.png"); public static ImageIcon down=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\down.png"); public static ImageIcon left=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\left.png"); public static ImageIcon right=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\right.png"); public static ImageIcon food=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\food.png"); public static ImageIcon body=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\body.png"); public static ImageIcon set=new ImageIcon("E:\\code\\java\\Hello\\src\\main\\java\\YMP\\GUI\\Snake\\Static\\a.png"); }