我参考了【Java】Java实现贪吃蛇小游戏(带详细注释)和
java贪吃蛇小游戏(详解)

先设置需要用到的常数

package Snake;public class ConstantNumber {public static int WIDTH=1024;public static int HEIGHT=578;static final int Up = 0 , Down = 1 , Left = 2 , Right = 3;
}
package Snake;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;public class MyFrame extends JFrame  {MyPanel jPanel_L=new MyPanel();public void loadFrame(){this.setTitle("贪吃蛇");//设置窗体标题this.setSize(ConstantNumber.WIDTH, ConstantNumber.HEIGHT);//设置窗体大小this.setBackground(Color.gray);//设置背景this.setLocationRelativeTo(null);//居中jPanel_L.setBackground(Color.black);jPanel_L.setLayout(null);jPanel_L.setBounds(0,0,800,700);JPanel jPanel_R=new JPanel();jPanel_R.setLayout(null);jPanel_R.setBounds(800,0,800,800);jPanel_R.setBackground(Color.gray);jPanel_R.requestFocus(false);add( jPanel_L);JButton button1=new JButton("开始");   JButton button2 = new JButton("暂停");JButton button3=new JButton("继续");button1.setFocusable(false); //这行必不可少button1.setBounds(900, 200, 100, 50); //设置按钮的大小位置button2.setBounds(900, 400, 100, 50);button2.setFocusable(false);button3.setBounds(900, 50, 100, 50);button3.setFocusable(false);button1.addActionListener(new Button1Listen());button2.addActionListener(new Button2Listen());button3.addActionListener(new Button3Listen());jPanel_R.add(button1);jPanel_R.add(button2);jPanel_R.add(button3);add(jPanel_R);
//        add(button1);
//        add(button2);//设置可关闭this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});//设置可见this.setVisible(true);}//内部类监听按钮class Button1Listen implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubjPanel_L.Start();}}class Button2Listen implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubjPanel_L.pauseThread();}}class Button3Listen implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubjPanel_L.resumeThread();}}public static void main(String[] args){      new MyFrame().loadFrame();  }}

setFocusable(false)很重要,一开始暂停后就失去了对键盘的监听,因为button扰乱了聚焦,所以加上。

package Snake;import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;public  abstract class SnakeObject {int x;//横坐标int y;//纵坐标public boolean live=true;//死亡/存活   public abstract void draw(Graphics g);}

蛇和食物建一个共同的父类

package Snake;import java.awt.Color;
import java.awt.Graphics;public class Food extends SnakeObject{Food(){x = (int)(Math.random() * 790);//800减去10 游戏屏幕大小减去事物sizey = (int)(Math.random() * 516);//这个范围是我打印出来范围坐标才确定的,我猜测是游戏上面加了边框,所以不能单纯减去size得到}public void draw(Graphics g){g.setColor(Color.green);g.fillRect(x, y, 10, 10); }
}
package Snake;import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;import javax.swing.JOptionPane;class Node {private int x , y;public Node() {}public Node(int a , int b){x = a;y = b;}public Node(Node tmp) {x = tmp.getX(); y = tmp.getY();}int getX() {return x;}int getY() {return y;}void setX(int a) {x = a;}void setY(int b) {y = b;}
}public class Snakedraw extends SnakeObject{static final int DIR [][] = {{0 , -1} , {0 , 1} , {-1 , 0} , {1 , 0}};private List<Node> lt = new ArrayList<Node>();private int curDir; //当前运动方向private int speed=1;/***  初始化*  蛇的初始方向是向右,Right=3*/public Snakedraw() {curDir = 3;lt.add(new Node(350 , 250));}/***  List的长度表示蛇的长度* @return*/int length() {return lt.size();}int getDir() {return curDir;}public void draw(Graphics g) {g.setColor(Color.WHITE);for(int i = 0; i < lt.size(); i++) {g.fillRect(lt.get(i).getX(), lt.get(i).getY(), 10, 10);}}/*** 头部移动的位置* @return tmp:头部的位置坐标*/Node headMove(){//         当向上或向下时,curDir为0/1,此时X轴不变(即 Snakedraw.Size * DIR[curDir][0]的值为0),Y轴变化
//        当向左或向右时,curDir为2/3,此时Y轴不变(即 Snakedraw.Size * DIR[curDir][1]的值为0),X轴变化int tx = lt.get(0).getX() + speed * DIR[curDir][0];int ty = lt.get(0).getY() + speed * DIR[curDir][1];
//          System.out.println(ty);if(tx<0||tx>790||ty<0||ty>516){                  live=false;return new Node(0,0);}elsereturn new Node(tx,ty);}void Dead1() {for(int i = 1; i < lt.size(); i++) {if(lt.get(0).getX() == lt.get(i).getX() && lt.get(0).getY() == lt.get(i).getY()) {live= false;break;}         }}//       void Dead2(Node newNode )
//      {//          if( lt.contains(newNode))
//          {//              live= false;
//          }
//      }void move(Food food){//        头部的位置Node head = headMove();
//      新添加的节点的位置Node newNode = new Node();Dead1();boolean eat = false;//      abs()返回参数的绝对值
//       通过判断头部的X/Y坐标位置和食物的X/Y坐标位置,由于头部大小是10,故距离小于10就代表吃到了if(Math.abs(head.getX() - food.x) < 10 && Math.abs(head.getY() - food.y) < 10) {food.live = false;eat=true;newNode = new Node(lt.get(lt.size() - 1));}
//        把前一个点的位置给后一点(即移动)for(int i = lt.size() - 1; i > 0; i--) lt.set(i, lt.get(i - 1));lt.set(0, head);if(!live) {//            弹出对话框,告知游戏结束JOptionPane.showMessageDialog(null, "Game over", "Message", JOptionPane.ERROR_MESSAGE);System.exit(1);}if(eat) {lt.add(newNode);speed++;            }}void changeDir(int dir) {curDir = dir;}}

Dead2的方法contains如果是同一对象即地址相同的情况下,才会返回true,而对于对象属性值相同但地址不同的不同对象,始终返回false。所以不可用

package Snake;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;import javax.swing.JPanel;public class MyPanel extends JPanel implements KeyListener {Snakedraw mySnake=new Snakedraw();Food food=new Food();private final Object lock = new Object();private boolean start=false;private boolean pause = false;/*** 调用该方法实现线程的暂停*/void pauseThread(){pause = true;}/*调用该方法实现恢复线程的运行*/void resumeThread(){pause =false;synchronized (lock){lock.notify();}}/*** 这个方法只能在run 方法中实现,不然会阻塞主线程,导致页面无响应*/void onPause() {synchronized (lock) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}}public  MyPanel(){super();setFocusable(true);addKeyListener(this);}public void Start(){start=true;new MyThread().start();}public void keyPressed(KeyEvent e) {if(!start)  return;//先开始才有用
//        System.out.print("work");switch(e.getKeyCode()) {//           如果蛇的长度为1,则表示刚开始,什么方向都可以;
//           若蛇的长度不为1,则表示它在运动,此时不能操作它向反方向运动case KeyEvent.VK_UP:if(mySnake.length() != 1 && mySnake.getDir() == ConstantNumber.Down) break;mySnake.changeDir(ConstantNumber.Up);break;case KeyEvent.VK_DOWN:if(mySnake.length() != 1 && mySnake.getDir() == ConstantNumber.Up) break;mySnake.changeDir(ConstantNumber.Down);break;case KeyEvent.VK_LEFT:if(mySnake.length() != 1 && mySnake.getDir() == ConstantNumber.Right) break;mySnake.changeDir(ConstantNumber.Left);break;case KeyEvent.VK_RIGHT:if(mySnake.length() != 1 && mySnake.getDir() == ConstantNumber.Left) break;mySnake.changeDir(ConstantNumber.Right);break;}}@Overridepublic void keyReleased(KeyEvent arg0) {// TODO Auto-generated method stub}@Overridepublic void keyTyped(KeyEvent arg0) {// TODO Auto-generated method stub}//在repaint()调用paint()方法之前,还会先调用update()方法//首先创建一张基于原面板的一场图像,先将绘制图像的工作在这张图片上面完成,最后再将这张图片直接贴到面板上面public void paint(Graphics g){super.paint(g);   //没有会将button刷掉if(mySnake.live){//如果蛇活着,就绘制mySnake.draw(g);if(food.live){//如果食物活着,就绘制food.draw(g);mySnake.move(food);}else{//否则,产生新食物food = new Food();}}else{//蛇死亡,弹出游戏结束字样}}private Image offScreenImage;public void update(Graphics g) {//g是前面屏幕的画笔if(offScreenImage == null)offScreenImage = this.createImage(ConstantNumber.WIDTH, ConstantNumber.HEIGHT);Graphics gOffScreen = offScreenImage.getGraphics();//gOffScreen是背后屏幕的画笔Color c = gOffScreen.getColor();gOffScreen.setColor(Color.BLACK);gOffScreen.fillRect(0, 0, ConstantNumber.WIDTH, ConstantNumber.HEIGHT);//画矩形 gOffScreen.setColor(c);paint(gOffScreen);//在背后屏幕画g.drawImage(offScreenImage, 0, 0, null);//将背后屏幕画的贴在前面屏幕上}class MyThread extends Thread{@Overridepublic void run() {super.run();while(true){while (pause){onPause();}repaint();try {sleep(30);//每30毫秒重绘一次} catch (InterruptedException e) {e.printStackTrace();}}}}}

这里用线程刷新画面,用双缓存避免了闪烁,用锁来控制线程的暂停可开始

Java 贪吃虫小游戏相关推荐

  1. 手把手教你做一个Java贪吃蛇小游戏

    大家好,我是孙不坚1208,这篇博客给大家分享一下:如何做一个贪吃蛇小游戏(Java版)的exe应用程序,希望能给需要帮助的朋友带来方便. 手把手教你做一个Java贪吃蛇小游戏的exe应用程序 一.J ...

  2. java贪吃蛇小游戏(详解)

    首先给出代码下载地址(含素材):https://share.weiyun.com/8hkvy1Ja 目录 1.实现效果: ​​2.游戏玩法 3.需求分析 4.代码实现 1.实现效果: 2.游戏玩法 该 ...

  3. 简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏

    本文实例为大家分享了java版贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public stat ...

  4. 用 Java 实现贪吃蛇小游戏

    程序说明 这是一个用 Java Awt 实现的贪吃蛇小游戏的完整代码 算法分析 (一)启动一个独立线程根据 direction 重绘面板实现蛇身移动效果,运行过程: 记录上次头部的坐标到 tempBo ...

  5. 贪吃蛇小游戏java实现代码分析

    贪吃蛇小游戏java实现代码分析 贪吃蛇的小游戏,网上的代码比较多,今天周五,在教研室没啥事做,在电脑中发现了一个贪吃蛇的小游戏,于是就看了下实现的源码,发现别人写的代码确实挺好的,自己也是边加注释边 ...

  6. Java实现贪吃蛇小游戏(附完整源码)

    今天我就从零开始来完成这个小游戏,完成的方式也是一步一步的添加功能这样的方式来实现. 第一步完成的功能:写一个界面 大家见到的贪吃蛇小游戏,界面肯定是少不了的.因此,第一步就是写一个小界面. 实现代码 ...

  7. JAVA版贪吃蛇小游戏

    这是一篇关于JAVA的贪吃蛇游戏,源代码的部分在下面正文中介绍,图片和音频的部分都放在百度云盘,需要的自行下载. 文章目录 开发环境 一.下载方法 二.运行效果展示 三.项目结构以及主程序入口 1.项 ...

  8. Java Swing 贪吃蛇小游戏

    静态资源参考: 注:实际上没有用到header.png. 工程目录: 源码: package snake;import javax.swing.*; import java.net.URL;/*** ...

  9. 计算机毕业设计-基于Java的GUI实现贪吃蛇小游戏

    标题:基于Java多线程版本GUI贪吃蛇小游戏 1.项目技术点 1.多线程的运用. 2.JAVA的GUI的运用. 3.数据结构的灵活运用. 4.随机食物的生成. 5.关卡加速,随着蛇身增长,蛇的速度也 ...

最新文章

  1. 匿名函数的this指向为什么是window?
  2. GCC 链接时出现undefined reference to “...”时可能解决办法
  3. java 集合(Set接口)
  4. Java面向对象(11)--多态性
  5. STL源码剖析 Stack栈 queue队列
  6. javascript 函数整理
  7. 她不讲武德,北航博士竟然把60年来的文本分类综述都整理了!!!
  8. Kotlin StandardKt
  9. 散列表(中):如何打造一个工业级水平的散列表?
  10. 计算机网络中计算机资源管理器,计算机基础知识:资源管理器的使用
  11. APS生产计划排产在注塑行业的应用
  12. 计算机应用基础单选题10an,计算机应用基础10考(附答案).doc
  13. android 8 平板,击败Android平板:Windows 8志在必得
  14. 使用ONVIF Device Test Tool获取网络摄像头的音/视频
  15. 支付宝沙箱测试手机网站支付,提示商户合作协议已到期,无法继续使用
  16. 批量将 PDF 转为 ePub 格式文档
  17. 京东API详情接口调用示例
  18. 华为入局网约车,已在多个城市测试“ Petal 出行”应用
  19. 本质复杂性 偶然复杂性_结构偶然性(第一部分)
  20. 日语语法实践篇十二——新编日语第一册第十三课之会话篇

热门文章

  1. 深度学习入门论文(必看)
  2. 【Antd Design Upload】 antd Upload 上传时只有Uploading状态,无法获取返回的数据
  3. io密集服务器cpu性能,IO密集型和CPU密集型 线程数的计算
  4. 网络常见面试题总结(三)
  5. 非常适合菜鸟练手的Python项目,墙裂建议收藏!
  6. 学生晚上回宿舍时其在实验室的计算机主机,学生晚上回宿舍时, 其在实验室的计算机主机应关闭, 显示器一般不用关。...
  7. python 预约系统_Python_字典实现简单预约系统
  8. python培训﹣首选马哥
  9. 各种软件如何双开,三开,N开,包括微信,qq等。
  10. 动手制作智能化家居“魔镜”