JavaGUI编程之贪吃蛇小游戏原码

直接放原码

./src/statics 下图标文件,注意命名规范

body.png

body.png

down.png

food.png

left.png

right.png

up.png

header.png

./src/com 下三个代码文件

Data.java

package com; import javax.swing.*; import java.net.URL; // 数据中心 public class Data { // 相对路径 tx.jpg // 绝对路径 / 相当于当前的项目/ public static URL headerURL = Data.class.getResource("../statics/header.png"); public static ImageIcon header = new ImageIcon(headerURL); public static URL upURL = Data.class.getResource("../statics/up.png"); public static URL downURL = Data.class.getResource("../statics/down.png"); public static URL leftURL = Data.class.getResource("../statics/left.png"); public static URL rightURL = Data.class.getResource("../statics/right.png"); public static ImageIcon up = new ImageIcon(upURL); public static ImageIcon down = new ImageIcon(downURL); public static ImageIcon left = new ImageIcon(leftURL); public static ImageIcon right = new ImageIcon(rightURL); public static URL bodyURL = Data.class.getResource("../statics/body.png"); public static ImageIcon body = new ImageIcon(bodyURL); public static URL foodURL = Data.class.getResource("../statics/food.png"); public static ImageIcon food = new ImageIcon(foodURL); }

GamePanel.java

package com; 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 fx; // food`s location int foodx; int foody; Random random = new Random(); int score; // 游戏当前状态 : 开始停止 boolean isStart = false; // 默认不开始 boolean isFail = false; // 游戏默认不失败 // 定时器 Timer timer = new Timer(100,this); // 100ms执行一次 // 构造器 public GamePanel(){ init(); // 获取焦点和键盘事件 this.setFocusable(true);// 获取焦点事件 this.addKeyListener(this);// 获得键盘监听事件 timer.start(); // 游戏一开始定时器就启动 } // 初始化方法 public void init(){ length = 3; snakeX[0] = 100; snakeY[0] = 100; // 脑袋坐标 snakeX[1] = 75; snakeY[1] = 100; // 第一个身体的坐标 snakeX[2] = 50; snakeY[2] = 100; // 第二个身体的坐标 fx = "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,11);// 头部广告栏 g.fillRect(25,75,850,600); // 画积分 g.setColor(Color.white); g.setFont(new Font("微软雅黑",Font.BOLD,18)); g.drawString("长度" + length, 750, 35); g.drawString("分数" + score, 750, 30); // 把小蛇画上去 if (fx.equals("R")){ Data.right.paintIcon(this,g,snakeX[0],snakeY[0]); // 蛇头初始化向右,需要通过方向来判断 }else if (fx.equals("L")){ Data.left.paintIcon(this,g,snakeX[0],snakeY[0]); // 蛇头初始化向右,需要通过方向来判断 }else if (fx.equals("U")){ Data.up.paintIcon(this,g,snakeX[0],snakeY[0]); // 蛇头初始化向右,需要通过方向来判断 }else if (fx.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]); // 第一个身体坐标 } // 画食物 Data.food.paintIcon(this,g,foodx,foody); // 游戏状态 if (isStart == false){ g.setColor(Color.white); g.setFont(new Font("微软雅黑",Font.BOLD,40));// 设置字体 g.drawString("按下空格开始游戏", 300, 300); } if(isFail){ g.setColor(Color.RED); g.setFont(new Font("微软雅黑",Font.BOLD,40));// font g.drawString("失败,按下空格重新开始",300, 300); } } // 键盘监听事件 @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); // 获取键盘按键是哪个 if(keyCode == KeyEvent.VK_SPACE){ // 如果按下的空格 if (isFail){ // restart isFail = false; init(); }else { isStart = !isStart; // 取反 } repaint(); } // 小蛇移动 if(keyCode == KeyEvent.VK_UP){ fx = "U"; }else if(keyCode == KeyEvent.VK_DOWN){ fx = "D"; }else if(keyCode == KeyEvent.VK_LEFT){ fx = "L"; }else if(keyCode == KeyEvent.VK_RIGHT){ fx = "R"; } } // 事件监听 -- 需要通过固定事件刷新 1s 十次 @Override public void actionPerformed(ActionEvent e) { if (isStart && isFail == false){ // 如果游戏是开始状态 就动起来 // 吃食物 if(snakeX[0] == foodx && snakeY[0] == foody){ // 长度+1 length++; // 分数+10 score = score + 10; // 再次随机食物 foodx = 25 + 25*random.nextInt(34); foody = 75 + 25*random.nextInt(24); } //结束判断,头和身体撞到了 for (int i = 1; i < length; i++) { //如果头和身体碰撞,那就说明游戏失败 if (snakeX[i]==snakeX[0] && snakeY[i]==snakeY[0] ){ isFail = true; } } // Move for (int i = length - 1; i > 0; i--) { // 后一节移到前一节位置 snakeX[1] = snakeX[0]; snakeX[i] = snakeX[i - 1]; snakeY[i] = snakeY[i - 1]; } // 走向 if (fx.equals("R")){ snakeX[0] = snakeX[0] + 25; // 边界判断 if(snakeX[0] > 850){snakeX[0] = 25;} }else if (fx.equals("L")){ snakeX[0] = snakeX[0] - 25; // 边界判断 if(snakeX[0] < 25){snakeX[0] = 850;} }else if (fx.equals("U")){ snakeY[0] = snakeY[0] - 25; // 边界判断 if(snakeY[0] < 75){snakeY[0] = 650;} }else if (fx.equals("D")){ snakeY[0] = snakeY[0] + 25; // 边界判断 if(snakeY[0] > 650){snakeY[0] = 75;} } repaint();// 重画页面 } timer.start(); // 定时器开启 } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } }

StartGame.java

package com; import javax.swing.*; // 游戏的主启动类 public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setBounds(10,10,900,720); frame.setResizable(false); // 窗口大小不可变 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 正常游戏界面都应该在面上 frame.add(new GamePanel()); frame.setVisible(true); } }

__EOF__

本文作者Coder Zjz's blog
本文链接https://www.cnblogs.com/coderzjz/p/13961698.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @ 2020-11-11 23:27  CoderZjz  阅读(362)  评论(0)    收藏  举报
编辑推荐:
· InnoDB为什么不用跳表,Redis为什么不用B+树?
· 记一次 C# 平台调用中因非托管 union 类型导致的内存访问越界
· [EF Core]聊聊“复合”属性
· 那些被推迟的 C# 14 特性及其背后的故事
· 我最喜欢的 C# 14 新特性
阅读排行:
· 博客园出海记-开篇:扬帆启航
· 微软开源的 MCP 教程「GitHub 热点速览」
· 记一次 .NET 某汽车控制焊接软件 卡死分析
· C#中的多级缓存架构设计与实现深度解析
· 技术人日常避坑手册:高效工作,少踩坑
点击右上角即可分享
微信分享提示