数据结构大作业-贪吃蛇
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构大作业-贪吃蛇相关的知识,希望对你有一定的参考价值。
这次数据结构课程我的大作业选择的是贪吃蛇,最初我想了很久到底用什么语言来写贪吃蛇,最后想到java实现图形界面是最方便的,因为JDK里已经有AWT和SWING两个类可以实现图形界面,C语言我会用一个叫easyX的图形库,但是我感觉这个图形库用起来挺麻烦的,c++的话,我还不会用QT,MFC,之类的。这个课程供我们选择的就只有这三门语言,最后我选择了java。
由于我是这学期刚学的java,而且一个星期只有一节java课,一共只学了只有七八周的样子,所以java学的不怎么精,对有些类的理解其实我的理解是错误的,所以,请各位路过的大佬轻喷。
我的想法是先在主函数所在的类建立一个容器JFrame,再建立一个snakePanel类继承JPanel类,通过重写父类的paint()函数来实现整个界面,再通过不停地repaint()来实现图形的变动。
在snakePanel中首先我要自己把各种坐标量好,然后我定义了snakeX和snakeY两个整型数组变量,用来控制蛇的位置,然后我疯狂的在网上找图片,最坑的是蛇头,你们想想,蛇头有四个方向,也就是要找四张图片,还有背景图片,还有蛇身等等,我找图片就在学校图书管找了一个下午。
我又定义了一个lenth变量,每次repaint时通过for循环画lenth-1次蛇身,每次lenth+1就实现了蛇身的增长,还有就是食物,我通过了math类派生出的Rand类随机出食物的X坐标和Y坐标然后paint,当食物的XY坐标和蛇头的XY坐标重合时就吃到了食物,食物此时就重新随机。游戏的失败判定和食物的判定类似,我每次通过一个for循环遍历蛇身,如果蛇身和蛇头重合则游戏失败(我并未设定蛇碰到墙就死的设定)。
最后就是如何动起来的事,我定义了一个IsLive的布尔变量,当蛇存活时未true,蛇死时为false,我全部关于动作的内容全部写在了一个while(isLive)的循环中,中间调用了Sleep函数来实现控制速度。
以上就是我的全部思路。
具体代码如下:
主类snake:
1 package snake; 2 3 import java.awt.*; 4 5 import javax.swing.*; 6 7 public class Snake extends Thread{ 8 public static void main(String[] args) { 9 //主面板 10 JFrame frame = new JFrame("贪食蛇游戏"); 11 frame.setBounds(10, 10, 900, 720); 12 frame.setResizable(false); 13 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 14 15 Snakepanel panel = new Snakepanel(); 16 frame.add(panel); 17 18 19 20 21 22 //计分板 23 JFrame score = new JFrame("计分板"); 24 score.setBounds(980, 10, 256, 180); 25 score.setResizable(false); 26 27 28 ScorePanel sp = new ScorePanel(); 29 sp.label2.setText(String.valueOf(panel.lenth-3)); 30 score.add(sp); 31 sp.tr.start(); 32 33 score.setVisible(true); 34 frame.setVisible(true); 35 36 OverFrame of = new OverFrame(); 37 38 } 39 40 }
snakePanel类:
1 package snake; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.event.KeyEvent; 7 import java.awt.event.KeyListener; 8 import java.util.Random; 9 10 import javax.swing.ImageIcon; 11 import javax.swing.JPanel; 12 13 public class Snakepanel extends JPanel implements KeyListener,Runnable{ 14 ImageIcon up = new ImageIcon("up.png"); 15 ImageIcon down = new ImageIcon("down.png"); 16 ImageIcon left = new ImageIcon("left.png"); 17 ImageIcon right = new ImageIcon("right.png"); 18 ImageIcon title = new ImageIcon("title.jpg"); 19 ImageIcon food = new ImageIcon("food.png"); 20 ImageIcon body = new ImageIcon("body.png"); 21 ImageIcon background = new ImageIcon("background.jpg"); 22 23 24 int[] snakeX = new int[1000];//蛇的X坐标 25 int[] snakeY = new int[1000];//蛇的Y坐标 26 int diriction;//方向,1为上,2为下,3为右,4为左 27 int lenth;//蛇的长度 28 29 int fx,fy;//食物的X轴和Y轴 30 Random rd = new Random(); 31 32 boolean isStart; 33 static boolean isLive; 34 int level;//等级 35 int speed;//速度 36 37 Thread tr = new Thread(this); 38 39 public Snakepanel(){ 40 this.setFocusable(true); 41 this.snakeX[0]=100; 42 this.snakeY[0]=100; 43 this.snakeX[1]=75; 44 this.snakeY[1]=100; 45 this.snakeX[2]=50; 46 this.snakeY[2]=100; 47 this.diriction = 3; 48 this.lenth = 3; 49 this.isLive=true; 50 this.isStart=false; 51 this.addKeyListener(this); 52 this.speed=500; 53 54 fx = rd.nextInt(34)*25+25; 55 fy = rd.nextInt(24)*25+75; 56 } 57 58 public void paint(Graphics g) 59 { 60 super.paint(g); 61 62 //画背景 63 this.setBackground(Color.WHITE); 64 background.paintIcon(this, g, 0, 0); 65 title.paintIcon(this, g, 25, 11); 66 67 g.setColor(new Color(0,0,139,100)); 68 g.fillRect(25, 75, 850, 600); 69 70 71 //画蛇头 72 if(this.diriction==1){ 73 up.paintIcon(this, g, snakeX[0], snakeY[0]); 74 }else if(this.diriction==2){ 75 down.paintIcon(this, g, snakeX[0], snakeY[0]); 76 }else if(this.diriction==3){ 77 right.paintIcon(this, g, snakeX[0], snakeY[0]); 78 }else if(this.diriction==4){ 79 left.paintIcon(this, g, snakeX[0], snakeY[0]); 80 } 81 82 //画蛇身 83 for(int i=1;i<lenth;i++){ 84 body.paintIcon(this, g, snakeX[i], snakeY[i]); 85 } 86 87 if(isStart==false){ 88 g.setColor(new Color(255,0,0)); 89 g.setFont(new Font("宋体",Font.ITALIC,40)); 90 g.drawString("请选择难度", 200, 200); 91 g.drawString("按F1为简单", 200, 260); 92 g.drawString("按F2为普通", 200, 320); 93 g.drawString("按F3为困难", 200, 380); 94 g.drawString("按F4为地狱", 200, 440); 95 }else{ 96 97 } 98 99 100 //画食物 101 102 food.paintIcon(this, g, fx, fy); 103 } 104 105 //添加的键盘事件 106 public void keyPressed(KeyEvent e) { 107 int keycode = e.getKeyCode(); 108 if(keycode==KeyEvent.VK_F1){ 109 this.level=1; 110 this.isStart=true; 111 this.repaint(); 112 this.speed/=this.level; 113 tr.start(); 114 }else if(keycode==KeyEvent.VK_F2){ 115 this.level=3; 116 this.isStart=true; 117 this.repaint(); 118 this.speed/=this.level; 119 tr.start(); 120 }else if(keycode==KeyEvent.VK_F3){ 121 this.level=5; 122 this.isStart=true; 123 this.repaint(); 124 this.speed/=this.level; 125 tr.start(); 126 }else if(keycode==KeyEvent.VK_F4){ 127 this.level=10; 128 this.isStart=true; 129 this.repaint(); 130 this.speed/=this.level; 131 tr.start(); 132 }else if(keycode==KeyEvent.VK_UP){ 133 if(this.diriction!=2){ 134 this.diriction=1; 135 this.repaint(); 136 } 137 138 }else if(keycode==KeyEvent.VK_DOWN){ 139 if(this.diriction!=1) 140 { 141 this.diriction=2; 142 this.repaint(); 143 } 144 145 }else if(keycode==KeyEvent.VK_RIGHT){ 146 if(this.diriction!=4){ 147 this.diriction=3; 148 this.repaint(); 149 } 150 151 }else if(keycode==KeyEvent.VK_LEFT){ 152 if(this.diriction!=3) 153 { 154 this.diriction=4; 155 this.repaint(); 156 } 157 158 } 159 160 161 } 162 public void keyTyped(KeyEvent e) { 163 } 164 public void keyReleased(KeyEvent e) { 165 } 166 167 public void run() { 168 while(isLive) 169 { 170 try { 171 Thread.sleep(speed); 172 } catch (Exception e) { 173 174 } 175 for(int i=lenth;i>0;i--){ 176 snakeX[i]=snakeX[i-1]; 177 snakeY[i]=snakeY[i-1]; 178 } 179 180 if(this.diriction==1){ 181 snakeY[0]=snakeY[0]-25; 182 if(snakeY[0]<75)snakeY[0]=650; 183 }else if(this.diriction==2){ 184 snakeY[0]=snakeY[0]+25; 185 if(snakeY[0]>650)snakeY[0]=75; 186 }else if(this.diriction==3){ 187 snakeX[0]=snakeX[0]+25; 188 if(snakeX[0]>850)snakeX[0]=25; 189 }else if(this.diriction==4){ 190 snakeX[0]=snakeX[0]-25; 191 if(snakeX[0]<25)snakeX[0]=850; 192 } 193 if(snakeX[0]==fx&&snakeY[0]==fy){ 194 ScorePanel.Score++; 195 this.lenth++; 196 fx = rd.nextInt(34)*25+25; 197 fy = rd.nextInt(24)*25+75; 198 } 199 200 for(int i=1;i<this.lenth;i++) 201 { 202 if(snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]) 203 { 204 isLive=false; 205 } 206 } 207 208 209 this.repaint(); 210 } 211 212 } 213 }
ScorePanel类//用于计分
package snake; import javax.swing.*; import java.awt.*; public class ScorePanel extends JPanel implements Runnable{ JLabel label1 = new JLabel("您的分数为"); JLabel label2 = new JLabel(); static int Score; Thread tr = new Thread(this); Font fo = new Font("Times New Roman",Font.ITALIC,40); public ScorePanel() { this.setLayout(null); label1.setBounds(90, 20, 90, 50); label2.setBounds(90, 60, 150, 75); label2.setFont(fo); this.add(label1); this.add(label2); } public void run() { while(true) { try { label2.setText(String.valueOf(Score)); } catch (Exception e) { } } } }
overpanel类
//在游戏结束时弹出
1 package snake; 2 3 import java.awt.*; 4 5 import javax.swing.*; 6 7 public class OverFrame extends JFrame implements Runnable{ 8 9 Thread tr = new Thread(this); 10 JLabel jl = new JLabel(); 11 12 13 public OverFrame(){ 14 15 this.setBounds(300, 300, 256, 180); 16 this.setResizable(false); 17 Font fo = new Font("宋体",Font.ITALIC,40); 18 jl.setFont(fo); 19 jl.setBounds(90, 40, 90, 50); 20 jl.setText("Game Over"); 21 this.add(jl); 22 tr.start(); 23 this.setDefaultCloseOperation(EXIT_ON_CLOSE); 24 } 25 26 27 public void run() { 28 while(true) 29 { 30 if(Snakepanel.isLive==false) 31 { 32 this.setVisible(true); 33 } 34 35 } 36 37 } 38 39 }
最后游戏的效果如下
我的代码感觉很繁杂,可读性很差,最后希望路过的大佬们有所指点
以上是关于数据结构大作业-贪吃蛇的主要内容,如果未能解决你的问题,请参考以下文章