数据结构大作业-贪吃蛇

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 }

 

最后游戏的效果如下

技术分享

技术分享

 

  我的代码感觉很繁杂,可读性很差,最后希望路过的大佬们有所指点


以上是关于数据结构大作业-贪吃蛇的主要内容,如果未能解决你的问题,请参考以下文章

python课程作业-贪吃蛇

2017秋-软件工程第七次作业-探路者贪吃蛇阿尔法发布

C语言项目贪吃蛇游戏(下)

2017秋-软件工程第七次作业-探路者贪吃蛇阿尔法发布展示(视频展示)

结对编程项目作业2-贪吃蛇开发环境搭建过程

第四次作业