小游戏项目-贪吃蛇
贪吃蛇
项目结构
StartGame
1 package com.luckylu.gui.snake; 2 3 import javax.swing.*; 4 5 public class StartGame { 6 public static void main(String[] args) { 7 JFrame jframe = new JFrame(); 8 jframe.setTitle("曈曈爸的小游戏-贪吃蛇"); 9 jframe.setBounds(100,100,900,770); //窗口位置&大小 10 jframe.setResizable(false); //窗口不可调 11 jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //关闭窗口 12 jframe.setVisible(true); // 可见 13 jframe.add(new GamePanel()); //加载GamePanel类 14 } 15 16 }
Data
1 package com.luckylu.gui.snake; 2 3 import javax.swing.*; 4 import java.net.URL; 5 6 //数据中心 7 public class Data { 8 9 //相对路径 tx.jpg 10 //绝对路径 / 相当于当前的项目 11 public static URL headerURL = Data.class.getResource("statics/header.png"); 12 public static ImageIcon header = new ImageIcon(headerURL); 13 public static URL upURL = Data.class.getResource("statics/up.png"); 14 public static URL downURL = Data.class.getResource("statics/down.png"); 15 public static URL leftURL = Data.class.getResource("statics/left.png"); 16 public static URL rightURL = Data.class.getResource("statics/right.png"); 17 public static ImageIcon up = new ImageIcon(upURL); 18 public static ImageIcon down = new ImageIcon(downURL); 19 public static ImageIcon left = new ImageIcon(leftURL); 20 public static ImageIcon right = new ImageIcon(rightURL); 21 public static URL bodyURL = Data.class.getResource("statics/body.png"); 22 public static ImageIcon body = new ImageIcon(bodyURL); 23 public static URL foodURL = Data.class.getResource("./statics/food.png"); 24 public static ImageIcon food = new ImageIcon(foodURL); 25 26 }
GamePanel
1 package com.luckylu.gui.snake; 2 3 import javax.swing.*; 4 import java.awt.*; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7 import java.awt.event.KeyEvent; 8 import java.awt.event.KeyListener; 9 import java.util.Random; 10 11 // 画板 ,执行监听器,按键监听KeyListener,事件监听ActionListener 12 public class GamePanel extends JPanel implements KeyListener, ActionListener { 13 14 // 定义蛇的数据结构 15 int length; //蛇的长度; 16 int[] snakeX = new int[600]; //蛇的x坐标 17 int[] snakeY = new int[500]; // 蛇的y坐标 18 String direction; // 定义方向 19 20 //定义食物的坐标 21 int foodX; 22 int foodY; 23 Random random= new Random(); //定义一个随机数 24 25 //定义成绩 26 int score; // 27 28 29 30 //游戏当前状态 31 boolean isStart = false; // 定义布尔值 默认停止 32 boolean isFail = false; // 定义布尔值 默认不失败 33 34 35 //定时器,以毫米为单位 36 Timer timer = new Timer(200,this); //100毫米执行一次 37 38 //构造器 39 public GamePanel() { 40 init(); 41 //获取焦点和键盘事件 42 this.setFocusable(true); //获得焦点事件:鼠标激活; 43 this.addKeyListener(this); // 获得当前类的键盘监听; 44 timer.start(); // 游戏一开始定时器就启动 45 46 } 47 48 //初始化 49 public void init(){ 50 //小蛇 51 length = 3; 52 snakeX[0]=150;snakeY[0]=150; //头 53 snakeX[1]=125;snakeY[1]=150; //身体1 54 snakeX[2]=100;snakeY[2]=150; //身体2 55 direction = "R"; //初始方向为右 56 //食物 57 foodX = 25 + 25 * random.nextInt(33); // 随机数的边界框内 850/25-1 58 foodY = 125 + 25 * random.nextInt(23); // 随机数的边界框内 600/25-1 59 score = 0; 60 } 61 62 // 画笔 画板上画 63 //alt + insert ==> ctrl + o 64 @Override 65 protected void paintComponent(Graphics g) { //调用画笔 66 super.paintComponent(g); // 清屏 67 this.setBackground(Color.white); 68 Data.header.paintIcon(this,g,25,25); // 头部广告栏 69 g.fillRect(25,125,850,600);//默认游戏界面 70 71 //画食物 72 Data.food.paintIcon(this,g,foodX,foodY); 73 74 //把小蛇画上去 75 //头部 76 if(direction.equals("R")) { 77 Data.right.paintIcon(this, g, snakeX[0], snakeY[0]); //头-右 78 }else if(direction.equals("U")) { 79 Data.up.paintIcon(this, g, snakeX[0], snakeY[0]); //头-右 80 }else if(direction.equals("D")) { 81 Data.down.paintIcon(this, g, snakeX[0], snakeY[0]); //头-右 82 }else if(direction.equals("L")) { 83 Data.left.paintIcon(this, g, snakeX[0], snakeY[0]); //头-右 84 } 85 // 身体 86 /* 初始小蛇的身体[静态] 87 Data.body.paintIcon(this,g,snakeX[1],snakeY[1]); //身体 88 Data.body.paintIcon(this,g,snakeX[2],snakeY[2]); // 身体 89 */ 90 91 // 动态小蛇的身体 0是头部,1开始为身体 92 for (int i = 1; i <length; i++) { 93 Data.body.paintIcon(this,g,snakeX[i],snakeY[i]); //动态身体 94 } 95 96 //游戏状态 97 if (isStart ==false){ 98 g.setColor(Color.white); 99 g.setFont(new Font("微软雅黑",Font.BOLD,32));//设置字体 100 g.drawString("按下空格 - 开始游戏",300,500); 101 } 102 if (isFail == true){ 103 g.setColor(Color.red); 104 g.setFont(new Font("微软雅黑",Font.BOLD,60));//设置字体 105 g.drawString("游戏结束",350,300); 106 g.setFont(new Font("微软雅黑",Font.BOLD,32));//设置字体 107 g.drawString("按空格重新开始",350,500); 108 } 109 110 g.setColor(Color.white); 111 g.setFont(new Font("微软雅黑",Font.BOLD,12));//设置字体 112 g.drawString("长度:"+length,680,100); 113 g.drawString("分数:"+score,750,100); 114 115 } 116 117 //键盘监听事件 118 @Override 119 public void keyPressed(KeyEvent e) { 120 int keyCode = e.getKeyCode();//获得键盘按键是哪一个 121 if(keyCode == KeyEvent.VK_SPACE ){ 122 if (isFail){ 123 isFail =false; //重新开始 124 init(); //初始化 125 }else { 126 isStart = !isStart; //取反 127 } 128 repaint(); //重画 129 } 130 //小蛇移动 并且反向操作无效 131 if(keyCode == KeyEvent.VK_UP && direction != "D"){ //不等于向下状态时按上执行 132 direction = "U"; 133 }else if (keyCode == KeyEvent.VK_DOWN && direction != "U"){ 134 direction = "D"; 135 }else if (keyCode == KeyEvent.VK_LEFT && direction != "R"){ 136 direction = "L"; 137 }else if (keyCode == KeyEvent.VK_RIGHT && direction != "L"){ 138 direction = "R"; 139 } 140 } 141 142 //移动事件监听 需要设置刷新频率,1秒10次 143 @Override 144 public void actionPerformed(ActionEvent e) { 145 if(isStart == true && isFail == false){ // 如果isStart为真,小蛇动起来 146 147 //吃食物 148 if (snakeX[0] == foodX & snakeY [0] == foodY){ 149 length++; //长度加一 150 //分数增加10 151 score = score+10; 152 //食物再次随机 153 foodX = 25 + 25 * random.nextInt(33); // 随机数的边界框内 850/25-1 154 foodY = 125 + 25 * random.nextInt(23); // 随机数的边界框内 600/25-1 155 } 156 157 //移动 头部要放到身体后,不然会被身体覆盖掉 158 159 // 身体 后一节的身体移动到前一节身体的位置形成移动 160 for (int i = length-1; i >0 ; i--) { 161 snakeX[i]=snakeX[i-1]; 162 snakeY[i]=snakeY[i-1]; 163 } 164 //头 走向 165 if (direction.equals("R")){ 166 snakeX[0] =snakeX[0]+25; 167 if(snakeX[0]>850){snakeX[0]=25;} //边界判断 168 }else if (direction.equals("L")){ 169 snakeX[0] =snakeX[0]-25; 170 if(snakeX[0]<25){snakeX[0]=850;} //边界判断 171 }else if (direction.equals("U")){ 172 snakeY[0] =snakeY[0]-25; 173 if(snakeY[0]<125){snakeY[0]=700;} //边界判断 174 }else if (direction.equals("D")){ 175 snakeY[0] =snakeY[0]+25; 176 if(snakeY[0]>700){snakeY[0]=125;} //边界判断 177 } 178 179 //失败判定 180 for (int i = 1; i <length; i++) { 181 if(snakeX[0] == snakeX[i]&&snakeY[0] == snakeY[i]){ 182 isFail = true; 183 } 184 } 185 186 repaint(); //画一次 187 } 188 timer.start(); //移动一次 189 } 190 191 192 @Override 193 public void keyTyped(KeyEvent e) { 194 195 } 196 @Override 197 public void keyReleased(KeyEvent e) { 198 199 } 200 201 }
结果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统