实验二 贪吃蛇游戏的开发
1,项目概述
1.1项目目标和主要内容
目标:整体程序无bug,实现贪吃蛇游戏基本功能;
1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子。玩家能利用上下左右键控制“蛇”的移动,“蛇”吃到“豆子”后“蛇”身体加长一节,得分增加,“蛇”碰到边界或蛇头与蛇身相撞,“蛇”死亡,游戏结束。
2)进行交互界面的设计,要有开始键、暂停键和停止退出的选项,能够控制游戏进程。对蛇吃到豆子进行分值计算,可以设置游戏速度,游戏音乐等拓展元素。
使用Java编程语言,在IntelliJ IDEA Community Edition上进行开发。
主要内容:屏幕上随机出现一个“食物”,称为豆子,上下左右控制“蛇”的移动,吃到“豆子”以后“蛇”的身体加长一点,得分增加,“蛇”碰到边界或,蛇头与蛇身相撞,蛇死亡,游戏结束。为游戏设计初始欢迎界面,游戏界面,游戏结束界面。
2.项目设计
3.程序运行结果及分析:
分析;
可以实现贪吃蛇游戏的基本功能;
具有计分(每吃一个食物加1分)功能,开始游戏计分为零。开始游戏界面,空格控制游戏的暂停/开始游戏功能,WASD控制方向。游戏结束界面。
完整代码
import java.awt.*;
import java.awt.event.*;
import java.util.Objects;
import java.util.Random;
import javax.swing.*;class Grid {int x;int y;public Grid(int x0, int y0) {x = x0;y = y0;}
}public class Snakes extends JComponent {private final int MAX_SIZE = 400;//蛇身体最长为400节private final Grid temp = new Grid(0, 0);private final Grid temp2 = new Grid(0, 0);private Grid head = new Grid(227, 170);//头部的位置初始化为(227,170)private final Grid[] body = new Grid[MAX_SIZE];private boolean first_launch = false;private int body_length = 5;//身体长度初始化为5private boolean isRun = true;private int RandomX, RandomY;private Thread run;private String direction = "R";//默认向右走private String current_direction = "R";//当前方向private final JLabel Score = new JLabel("0");private final JLabel Time = new JLabel("");private int hour = 0;private int min = 0;private int sec = 0;private boolean pause = false;public Snakes() {//布局JLabel label = new JLabel("POINT:");add(label);label.setBounds(5, 15, 80, 20);label.setFont(new Font("微软雅黑", Font.PLAIN, 15));add(Score);Score.setBounds(90, 15, 80, 20);Score.setFont(new Font("微软雅黑", Font.PLAIN, 15));JLabel label2 = new JLabel("TIME:");add(label2);label2.setBounds(5, 45, 80, 20);label2.setFont(new Font("微软雅黑", Font.PLAIN, 15));add(Time);Time.setBounds(90, 45, 80, 20);Time.setFont(new Font("微软雅黑", Font.PLAIN, 15));for (int i = 0; i < MAX_SIZE; i++) {body[i] = new Grid(0, 0);}addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent e) {super.keyPressed(e);if (e.getKeyCode() == KeyEvent.VK_D) {if (isRun && !current_direction.equals("L")) {direction = "R";}}if (e.getKeyCode() == KeyEvent.VK_A) {if (isRun && !current_direction.equals("R")) {direction = "L";}}if (e.getKeyCode() == KeyEvent.VK_W) {if (isRun && !current_direction.equals("D")) {direction = "U";}}if (e.getKeyCode() == KeyEvent.VK_S) {if (isRun && !current_direction.equals("U")) {direction = "D";}}if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {direction = "R";//默认向右走current_direction = "R";//当前方向first_launch = false;isRun = true;body_length = 5;head = new Grid(227, 100);Score.setText("0");hour = 0;min = 0;sec = 0;for (int i = 0; i < MAX_SIZE; i++) {body[i].x = 0;body[i].y = 0;}System.out.println("Start again");}if (e.getKeyCode() == KeyEvent.VK_SPACE) {if (!pause)//暂停{pause = true;isRun = false;} else//开始{pause = false;isRun = true;}}}});new Timer();setFocusable(true);}public void paintComponent(Graphics g1) {super.paintComponent(g1);Graphics2D g = (Graphics2D) g1;//画头g.setColor(Color.BLACK);g.fillRoundRect(head.x, head.y, 20, 20, 5, 5);if (!first_launch) {//初始化身体int x = head.x;for (int i = 0; i < body_length; i++) {x -= 22;//相邻两个方块的间距为2个像素,方块宽度都为20像素body[i].x = x;body[i].y = head.y;g.fillRoundRect(body[i].x, body[i].y, 20, 20, 5, 5);}//初始化食物位置ProduceRandom();} else {//每次刷新身体for (int i = 0; i < body_length; i++) {g.fillRoundRect(body[i].x, body[i].y, 20, 20, 5, 5);}if (EatFood())//被吃了重新产生食物{ProduceRandom();}}g.fillOval(RandomX, RandomY, 19, 19);first_launch = true;//墙g.setStroke(new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));g.setBackground(Color.WHITE);g.drawRect(2, 77, 491, 469);//网格线for (int i = 1; i < 22; i++) {g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));g.setColor(Color.WHITE);g.drawLine(5 + i * 22, 79, 5 + i * 22, 542);//墙宽为4,预留1个像素,以免蛇蹭墙。if (i <= 20) {g.drawLine(4, 80 + i * 22, 491, 80 + i * 22);}}}public void ProduceRandom() {boolean flag = true;Random rand = new Random();RandomX = (rand.nextInt(21) + 1) * 22 + 7;RandomY = (rand.nextInt(20) + 1) * 22 + 82;while (flag) {for (int i = 0; i < body_length; i++) {if (body[i].x == RandomX && body[i].y == RandomY) {RandomX = (rand.nextInt(21) + 1) * 22 + 7;RandomY = (rand.nextInt(20) + 1) * 22 + 82;flag = true;break;} else {if (i == body_length - 1) {flag = false;}}}}}public void HitWall() {//判断是否撞墙if (Objects.equals(current_direction, "L")) {if (head.x < 7) {new Snake().start();isRun = false;int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "提醒", JOptionPane.YES_NO_OPTION);if (result == JOptionPane.YES_NO_OPTION) {direction = "R";//默认向右走current_direction = "R";//当前方向first_launch = false;isRun = true;body_length = 5;head = new Grid(227, 170);Score.setText("6");hour = 0;min = 0;sec = 0;for (int i = 0; i < MAX_SIZE; i++) {body[i].x = 0;body[i].y = 0;}System.out.println("Start again");}}}if (Objects.equals(current_direction, "R")) {if (head.x > 489) {new Snake().start();isRun = false;int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "提醒", JOptionPane.YES_NO_OPTION);if (result == JOptionPane.YES_NO_OPTION) {direction = "R";//默认向右走current_direction = "R";//当前方向first_launch = false;isRun = true;body_length = 5;head = new Grid(227, 170);Score.setText("0");hour = 0;min = 0;sec = 0;for (int i = 0; i < MAX_SIZE; i++) {body[i].x = 0;body[i].y = 0;}System.out.println("Start again");}}}if (Objects.equals(current_direction, "U")) {if (head.y < 94) {new Snake().start();isRun = false;int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "提醒", JOptionPane.YES_NO_OPTION);if (result == JOptionPane.YES_NO_OPTION) {direction = "R";//默认向右走current_direction = "R";//当前方向first_launch = false;isRun = true;body_length = 5;head = new Grid(227, 100);Score.setText("0");hour = 0;min = 0;sec = 0;for (int i = 0; i < MAX_SIZE; i++) {body[i].x = 0;body[i].y = 0;}System.out.println("Start again");}}}if (Objects.equals(current_direction, "D")) {if (head.y > 542) {new Snake().start();isRun = false;int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "提醒", JOptionPane.YES_NO_OPTION);if (result == JOptionPane.YES_NO_OPTION) {direction = "R";//默认向右走current_direction = "R";//当前方向first_launch = false;isRun = true;body_length = 5;head = new Grid(227, 170);Score.setText("0");hour = 0;min = 0;sec = 0;for (int i = 0; i < MAX_SIZE; i++) {body[i].x = 0;body[i].y = 0;}System.out.println("Start again");}}}}public void HitSelf() {//判断是否撞到自己身上for (int i = 0; i < body_length; i++) {if (body[i].x == head.x && body[i].y == head.y) {new Snake().start();isRun = false;int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "提醒", JOptionPane.YES_NO_OPTION);if (result == JOptionPane.YES_NO_OPTION) {direction = "R";//默认向右走current_direction = "R";//当前方向first_launch = false;isRun = true;body_length = 5;head = new Grid(227, 170);Score.setText("0");hour = 0;min = 0;sec = 0;for (int j = 0; j < MAX_SIZE; j++) {body[j].x = 0;body[j].y = 0;}System.out.println("Start again");}break;}}}public boolean EatFood() {return head.x == RandomX && head.y == RandomY;}
public int s=0;public void Thread() {long millis = 300;//每隔300毫秒刷新一次run = new Thread(() -> {while (true) {try {Thread.sleep(millis);} catch (InterruptedException ex) {ex.printStackTrace();}if (!pause) {temp.x = head.x;temp.y = head.y;//头部移动if (Objects.equals(direction, "L")) {head.x -= 22;}if (Objects.equals(direction, "R")) {head.x += 22;}if (Objects.equals(direction, "U")) {head.y -= 22;}if (Objects.equals(direction, "D")) {head.y += 22;}current_direction = direction;//刷新当前前进方向//身体移动for (int i = 0; i < body_length; i++) {temp2.x = body[i].x;temp2.y = body[i].y;body[i].x = temp.x;body[i].y = temp.y;temp.x = temp2.x;temp.y = temp2.y;}if (EatFood()) {body_length++;s++;body[body_length - 1].x = temp2.x;body[body_length - 1].y = temp2.y;Score.setText("" + (s));new Snake().start();}repaint();HitWall();HitSelf();}}});run.start();}//计时器类class Timer extends Thread {public Timer() {this.start();}@Overridepublic void run() {while (true) {if (isRun) {sec += 1;if (sec >= 60) {sec = 0;min += 1;}if (min >= 60) {min = 0;hour += 1;}showTime();}try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}private void showTime() {String strTime;if (hour < 10)strTime = "0" + hour + ":";elsestrTime = "" + hour + ":";if (min < 10)strTime = strTime + "0" + min + ":";elsestrTime = strTime + "" + min + ":";if (sec < 10)strTime = strTime + "0" + sec;elsestrTime = strTime + "" + sec;//在窗体上设置显示时间Time.setText(strTime);}}public static void main(String[] args) {Snakes t = new Snakes();t.Thread();JFrame game = new JFrame();game.setTitle("贪吃蛇.GluttonousSnake");game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);game.setSize(510, 590);game.setResizable(false);game.setLocationRelativeTo(null);game.add(t);game.setVisible(true);}
}class Snake extends Thread {public Snake() {}
}
4.总结
4.1 项目的难点和关键点
显示界面需要JFrame和Jpanel来实现。使用一个全局变量记录当前蛇的长度,方便绘图时画出正确的蛇。在做碰撞检测时,只需要将蛇头节点的坐标和蛇身的坐标、食物的坐标、墙的坐标进行比较即可。当蛇在移动时,需要将储存蛇的数组的每一个元素赋给后一个元素,最后计算首元素,此时最后一个元素的值被丢弃。若吃到食物,则将最后一个元素继续向后赋值,同时设置蛇的长度加一。
4.2 项目的评价:
贪吃蛇的主要功能可以很好的实现,在其基础上加入有趣的图片使得游戏更具有可玩性。
4.3 心得体会
通过该项目,练习了frame框架和GUI编程的用法。
5.参考文献
用Java开发贪食蛇小游戏@阿雪狼
实验二 贪吃蛇游戏的开发相关推荐
- 实验项目二 贪吃蛇游戏开发
一.实验要求 1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子, 2.上下左右控制"蛇"的移动,吃到"豆子"以后" ...
- 实验二 贪吃蛇的游戏开发
实验目的: 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后"蛇" ...
- 计算机软件实习项目二 —— 贪吃蛇游戏 (实验准备)
目录 一.实验目的 二.编程语言和平台 三.实验难点: 四.参考资料 一.实验目的 1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子 2.上下左右控制"蛇 ...
- c语言设计贪吃蛇实验报告,贪吃蛇游戏程序设计实验报告
<贪吃蛇游戏程序设计实验报告>由会员分享,可在线阅读,更多相关<贪吃蛇游戏程序设计实验报告(11页珍藏版)>请在人人文库网上搜索. 1.Windows编程大作业贪吃蛇设计与实现 ...
- 计算机软件实习项目二 —— 贪吃蛇游戏 (代码实现) 12-16
代码实现 不得不说python真是太香了,我感觉写起来比C++快,而且代码量更少,还有非常多十分方便的方法可以使用.在pycharm里有非常多的快捷键十分的方便,相较项目使用的visual stu ...
- java多线程贪吃蛇实验报告_JAVA开放性实验报告贪吃蛇
JAVA开放性实验报告贪吃蛇 JAVA程序设计 开放性实验报告 专 业: 计算机科学与技术 班 级: 2012级2班 学 号: 姓 名: 实验2贪吃蛇游戏设计(4学时) 1.实验内容 (1) 创建软件 ...
- 实验二、贪吃蛇游戏开发
实验要求 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后"蛇" ...
- 实验项目二:贪吃蛇游戏开发
贪吃蛇游戏开发 一.前言 二.基本流程 三.游戏界面设计 1. 界面构造 2. 蛇的构造 3. 食物构造 四.游戏过程 1. 蛇的移动 2. 蛇吃食物与碰撞检测 五.游戏结束 1. 结束界面 六.扩展 ...
- 开发Windows贪吃蛇游戏——(二)代码实现
目录 前言 窗体部分 Frame部分 声明全局变量 Panel的初始化 startGame方法 paintComponent方法 drawGame方法 newSnake方法 newFood方法 mov ...
- 【使用java swing制作简易贪吃蛇游戏】软件实习项目二
一.项目准备 需求分析: 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后" ...
最新文章
- php常见排序算去,PHP兑现常见排序算法
- 2018年终总结之AI领域开源框架汇总
- python方法和函数的格式是完全一样的_Python成为专业人士笔记-返回变量形式函数- str() 和 repr()...
- nginx+tomcat动静分离结构
- VS2015 无法启动 IIS服务器
- 一个页面从输入URL到加载显示完成,发生了什么?
- Linux: 两个USB摄像头的数据采集问题
- python sort dict 总结
- 被薅秃了!元气森林:损失近千万元 将为14.05万下单用户每人寄一箱白桃气泡水...
- ASN.1编解码:ORAN-E2AP分析
- 分享一个完整的Mybatis分页解决方案
- Use AVAudioPlayer in OperationQueue
- ASP.NET Core中返回 json 数据首字母大小写问题
- 医院机房服务器维护表,医院信息系统机房版.docx
- python实现微信接口——itchat模块
- 【Java】我的世界Java版外挂制作 [0] - 配置环境
- 体验美容科技产品:让人不断保养和自我厌恶 | 行业
- 史上最详细最易懂的EventBus源码解析
- Core Text 实践:自定义每个字的位置
- js日期格式转换Wed Mar 22 13:38:37 CST 2017 转换 为yyyy-mm-dd
热门文章
- iOS-UIGraphics将两个图片合并成一张
- 遭遇Trojan.PSW.ZhengTu,Trojan.PSW.OnlineGames,Trojan.PSW.ZhuXian.b等
- python 图片二值化处理(处理后为纯黑白的图片)
- 7、WiFi共享大师
- 用计算机弹课间进行曲,课间进行曲(修改稿)
- 2022年烷基化工艺模拟考试题及烷基化工艺模拟考试题库
- 微软服务器系统突然要求密钥,买了Win10新电脑?小心微软偷走你的设备加密密钥...
- Proteus仿真51单片机入门
- 旅游|受不住热暑的炎烤 就到山上“凉拌”空气去
- java十进制_JAVA 十进制 转换成 三进制