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. 实验项目二 贪吃蛇游戏开发

    一.实验要求 1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子, 2.上下左右控制"蛇"的移动,吃到"豆子"以后" ...

  2. 实验二 贪吃蛇的游戏开发

    实验目的: 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后"蛇" ...

  3. 计算机软件实习项目二 —— 贪吃蛇游戏 (实验准备)

    目录 一.实验目的 二.编程语言和平台 三.实验难点: 四.参考资料 一.实验目的 1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子 2.上下左右控制"蛇 ...

  4. c语言设计贪吃蛇实验报告,贪吃蛇游戏程序设计实验报告

    <贪吃蛇游戏程序设计实验报告>由会员分享,可在线阅读,更多相关<贪吃蛇游戏程序设计实验报告(11页珍藏版)>请在人人文库网上搜索. 1.Windows编程大作业贪吃蛇设计与实现 ...

  5. 计算机软件实习项目二 —— 贪吃蛇游戏 (代码实现) 12-16

    代码实现   不得不说python真是太香了,我感觉写起来比C++快,而且代码量更少,还有非常多十分方便的方法可以使用.在pycharm里有非常多的快捷键十分的方便,相较项目使用的visual stu ...

  6. java多线程贪吃蛇实验报告_JAVA开放性实验报告贪吃蛇

    JAVA开放性实验报告贪吃蛇 JAVA程序设计 开放性实验报告 专 业: 计算机科学与技术 班 级: 2012级2班 学 号: 姓 名: 实验2贪吃蛇游戏设计(4学时) 1.实验内容 (1) 创建软件 ...

  7. 实验二、贪吃蛇游戏开发

    实验要求 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后"蛇" ...

  8. 实验项目二:贪吃蛇游戏开发

    贪吃蛇游戏开发 一.前言 二.基本流程 三.游戏界面设计 1. 界面构造 2. 蛇的构造 3. 食物构造 四.游戏过程 1. 蛇的移动 2. 蛇吃食物与碰撞检测 五.游戏结束 1. 结束界面 六.扩展 ...

  9. 开发Windows贪吃蛇游戏——(二)代码实现

    目录 前言 窗体部分 Frame部分 声明全局变量 Panel的初始化 startGame方法 paintComponent方法 drawGame方法 newSnake方法 newFood方法 mov ...

  10. 【使用java swing制作简易贪吃蛇游戏】软件实习项目二

    一.项目准备 需求分析: 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后" ...

最新文章

  1. php常见排序算去,PHP兑现常见排序算法
  2. 2018年终总结之AI领域开源框架汇总
  3. python方法和函数的格式是完全一样的_Python成为专业人士笔记-返回变量形式函数- str() 和 repr()...
  4. nginx+tomcat动静分离结构
  5. VS2015 无法启动 IIS服务器
  6. 一个页面从输入URL到加载显示完成,发生了什么?
  7. Linux: 两个USB摄像头的数据采集问题
  8. python sort dict 总结
  9. 被薅秃了!元气森林:损失近千万元 将为14.05万下单用户每人寄一箱白桃气泡水...
  10. ASN.1编解码:ORAN-E2AP分析
  11. 分享一个完整的Mybatis分页解决方案
  12. Use AVAudioPlayer in OperationQueue
  13. ASP.NET Core中返回 json 数据首字母大小写问题
  14. 医院机房服务器维护表,医院信息系统机房版.docx
  15. python实现微信接口——itchat模块
  16. 【Java】我的世界Java版外挂制作 [0] - 配置环境
  17. 体验美容科技产品:让人不断保养和自我厌恶 | 行业
  18. 史上最详细最易懂的EventBus源码解析
  19. Core Text 实践:自定义每个字的位置
  20. js日期格式转换Wed Mar 22 13:38:37 CST 2017 转换 为yyyy-mm-dd

热门文章

  1. iOS-UIGraphics将两个图片合并成一张
  2. 遭遇Trojan.PSW.ZhengTu,Trojan.PSW.OnlineGames,Trojan.PSW.ZhuXian.b等
  3. python 图片二值化处理(处理后为纯黑白的图片)
  4. 7、WiFi共享大师
  5. 用计算机弹课间进行曲,课间进行曲(修改稿)
  6. 2022年烷基化工艺模拟考试题及烷基化工艺模拟考试题库
  7. 微软服务器系统突然要求密钥,买了Win10新电脑?小心微软偷走你的设备加密密钥...
  8. Proteus仿真51单片机入门
  9. 旅游|受不住热暑的炎烤 就到山上“凉拌”空气去
  10. java十进制_JAVA 十进制 转换成 三进制