首页 > 代码库 > Java实现贪吃蛇游戏【代码】

Java实现贪吃蛇游戏【代码】

花了两个下午写了一个贪吃蛇小游戏,本人想写这游戏很长时间了。作为以前诺基亚手机上的经典游戏,贪吃蛇和俄罗斯方块一样,都曾经在我们的童年给我们带来了很多乐趣。世间万物斗转星移,诺基亚曾经作为手机业的龙头老大,现如今也一步步走向衰落,被收购,再过不久估计就要退出手机业务了,而贪吃蛇这款游戏也基本上没人玩了,甚至在新一代人的印象中都已毫无记忆了。。。但是,这款游戏在它基础上经过改造其实可以弄出很多花样,也确实可以在一定程度上锻炼自己的编程能力。前不久十分火热的贪吃蛇大作战其实就可以看做是在这款游戏的基础上进行的改造。所以,我也希望自己可以尝试以下,做个有意思的版本。

目前这个版本只是为了后期版本的一个测试版本,所以只有一些基本功能,本来是打算这个版本实现了移动,吃食物增长,判断撞墙和撞自己的身体就行了,无奈觉得有点单调,于是在此基础上加上了一个计时器和记分功能以及音效。白白又多了几百行代码。原来的基本代码也就300行。

游戏界面图如下:

技术分享

注意运行时请附带以下文件:

 http://files.cnblogs.com/files/journal-of-xjx/SnakeDemo.rar

说明,按空格开始和暂停功能还在思考怎么实现,暂时没做,不过这样已经可以玩了,嘿嘿

------------------------------------------------------------以下是代码区--------------------------------------------------------------

  1 import java.awt.*;
  2 import java.awt.event.*;
  3 import java.io.File;
  4 import java.io.IOException;
  5 import java.util.Random;
  6 import javax.sound.sampled.*;
  7 import javax.swing.*;
  8 
  9 class Tile{
 10     int x;
 11     int y;
 12     
 13     public Tile(int x0,int y0){
 14         x = x0;
 15         y = y0;
 16     }
 17 }
 18 
 19 public class SnakeDemo extends JComponent{
 20     /**
 21      * 
 22      */
 23     private static final long serialVersionUID = 3794762291171148906L;
 24     private final int MAX_SIZE = 400;//蛇身体最长为400节
 25     private Tile temp = new Tile(0,0);
 26     private Tile temp2 = new Tile(0,0);
 27     private Tile head = new Tile(227,100);//头部的位置初始化为(227,100)
 28     private Tile[] body = new Tile[MAX_SIZE];
 29     private String direction = "R";//默认向右走
 30     private String current_direction = "R";//当前方向
 31     private boolean first_launch = false;
 32     private boolean iseaten = false;
 33     private boolean isrun = true;
 34     private int randomx,randomy;
 35     private int body_length = 5;//身体长度初始化为5
 36     private Thread run;
 37     private JLabel label = new JLabel("当前长度:");
 38     private JLabel label2 = new JLabel("所花时间:");
 39     private JLabel label3 = new JLabel("说          明:");
 40     private JTextArea explain = new JTextArea("此游戏是一个贪吃蛇Demo版本,实现简单地移动,得分,判断撞墙和自己的功能,"
 41             + "初始长度为6,头部为红色,身体颜色渐变。注意蛇走动的时候原路返回当做撞自己的身体。游戏本身代码只有300行,"
 42             + "加上一些显示,计时和音效后多了几百行。\n按上下左右键实现移动,按ESC重新开始");
 43     private JLabel Score = new JLabel("6");
 44     private JLabel Time = new JLabel("");
 45     private Font f = new Font("微软雅黑",Font.PLAIN,15);
 46     private Font f2 = new Font("微软雅黑",Font.PLAIN,13);
 47     private JPanel p = new JPanel();
 48     private int hour =0;
 49     private int min =0;
 50     private int sec =0 ;
 51     private boolean suspended = false;
 52     
 53     public SnakeDemo(){
 54         String lookAndFeel =UIManager.getSystemLookAndFeelClassName();
 55         try {
 56             UIManager.setLookAndFeel(lookAndFeel);
 57         } catch (ClassNotFoundException e1) {
 58             // TODO 自动生成的 catch 块
 59             e1.printStackTrace();
 60         } catch (InstantiationException e1) {
 61             // TODO 自动生成的 catch 块
 62             e1.printStackTrace();
 63         } catch (IllegalAccessException e1) {
 64             // TODO 自动生成的 catch 块
 65             e1.printStackTrace();
 66         } catch (UnsupportedLookAndFeelException e1) {
 67             // TODO 自动生成的 catch 块
 68             e1.printStackTrace();
 69         }
 70         
 71         //布局
 72         add(label);
 73         label.setBounds(500, 10, 80, 20);
 74         label.setFont(f);
 75         add(Score);
 76         Score.setBounds(500, 35, 80, 20);
 77         Score.setFont(f);
 78         add(label2);
 79         label2.setBounds(500, 60, 80, 20);
 80         label2.setFont(f);
 81         add(Time);
 82         Time.setBounds(500, 85, 80, 20);
 83         Time.setFont(f);
 84         add(p);
 85         p.setBounds(498, 110, 93, 1);
 86         p.setBorder(BorderFactory.createLineBorder(Color.black));
 87         
 88         add(label3);
 89         label3.setBounds(500, 115, 80, 20);
 90         label3.setFont(f);
 91         add(explain);
 92         explain.setBounds(498, 138, 100, 350);
 93         explain.setFont(f2);
 94         explain.setLineWrap(true);
 95         explain.setOpaque(false); 
 96         
 97         for(int i = 0; i < MAX_SIZE;i++)
 98         {
 99             body[i] = new Tile(0,0);
100         }
101         
102         addKeyListener(new KeyAdapter() {
103             public void keyPressed(KeyEvent e) {
104                 super.keyPressed(e);
105                 if(e.getKeyCode() == KeyEvent.VK_RIGHT)
106                 {
107                     direction = "R";
108                 }
109                 if(e.getKeyCode() == KeyEvent.VK_LEFT)
110                 {
111                     direction = "L";
112                 }
113                 if(e.getKeyCode() == KeyEvent.VK_UP)
114                 {
115                     direction = "U";
116                 }
117                 if(e.getKeyCode() == KeyEvent.VK_DOWN)
118                 {
119                     direction = "D";
120                 }
121                 if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
122                 {
123                     direction = "R";//默认向右走
124                     current_direction = "R";//当前方向
125                     first_launch = false;
126                     iseaten = false;
127                     isrun = true;
128                     body_length = 5;
129                     head = new Tile(227,100);
130                     Score.setText("6");
131                     hour =0;
132                     min =0;
133                     sec =0 ;
134                     for(int i = 0; i < MAX_SIZE;i++)
135                     {
136                         body[i].x = 0;
137                         body[i].y = 0;
138                     }
139                     
140                     run = new Thread();
141                     run.start();
142                     System.out.println("Start again");
143                 }
144 //                if(e.getKeyCode() == KeyEvent.VK_SPACE)//按空格键开始和暂停暂时没做,还在思考中
145 //                {
146 //                    if(!suspended)
147 //                    {
148 //                        synchronized(run)
149 //                        {
150 //                            try {
151 //                                run.wait();
152 //                            } catch (InterruptedException e1) {
153 //                                e1.printStackTrace();
154 //                            }
155 //                        }
156 //                    }
157 //                    //notify();
158 //                }
159             }
160         });
161         
162         new Timer();
163         
164         setFocusable(true);
165     }
166     
167     public void paintComponent(Graphics g1){
168         super.paintComponent(g1);
169         Graphics2D g = (Graphics2D) g1;
170         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
171         g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_NORMALIZE);
172         
173         //画头部
174         g.setColor(Color.red);
175         g.fillRoundRect(head.x, head.y, 20, 20, 10, 10);
176         
177         g.setPaint(new GradientPaint(115,135,Color.CYAN,230,135,Color.MAGENTA,true));
178         if(!first_launch)
179         {
180             //初始化身体
181             int x = head.x;
182             for(int i = 0;i < body_length;i++)
183             {
184                 x -= 22;//相邻两个方块的间距为2个像素,方块宽度都为20像素
185                 body[i].x = x;
186                 body[i].y = head.y;
187                 g.fillRoundRect(body[i].x, body[i].y, 20, 20, 10, 10);
188             }
189             //初始化食物位置
190             ProduceRandom();
191             g.fillOval(randomx, randomy, 19, 19);
192         }
193         else
194         {
195             //每次刷新身体
196             for(int i = 0;i < body_length;i++)
197             {
198                 g.fillRoundRect(body[i].x, body[i].y, 20, 20, 10, 10);
199             }
200             
201             if(EatFood())//被吃了重新产生食物
202             {
203                 ProduceRandom();
204                 g.fillOval(randomx, randomy, 19, 19);
205                 iseaten = false;
206             }
207             else
208             {
209                 g.fillOval(randomx, randomy, 19, 19);
210             }
211         }
212         first_launch = true;
213         //
214         g.setStroke( new BasicStroke(4,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
215         g.setBackground(Color.black);
216         g.drawRect(2, 7, 491, 469);
217         
218         //网格线
219         for(int i = 1;i < 22;i++)
220         {
221             g.setStroke( new BasicStroke(1,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
222             g.setColor(Color.black);
223             g.drawLine(5+i*22,9,5+i*22,472);
224             if(i <= 20)
225             {
226                 g.drawLine(4,10+i*22,491,10+i*22);
227             }
228         }
229     }
230     
231     public void ProduceRandom(){
232         boolean flag = true;
233         Random rand = new Random();
234         randomx = (rand.nextInt(21) + 1) * 22 + 7;
235         randomy = (rand.nextInt(20) + 1) *22 + 12;
236         while(flag)
237         {
238             for(int i = 0;i < body_length; i++)
239             {
240                 if(body[i].x == randomx && body[i].y == randomy)
241                 {
242                     randomx = (rand.nextInt(21) + 1) * 22 + 7;
243                     randomy = (rand.nextInt(20) + 1) *22 + 12;
244                     flag = true;
245                     break;
246                 }
247                 else
248                 {
249                     if(i == body_length - 1)
250                     {
251                         flag = false;
252                     }
253                 }
254             }
255         }
256     }
257     
258     public void HitWall(){//判断是否撞墙
259         if(current_direction == "L")
260         {
261             if(head.x < 7)
262             {
263                 new AePlayWave("over.wav").start();
264                 isrun = false;
265                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
266                 if(result==JOptionPane.YES_NO_OPTION)
267                 {
268                     direction = "R";//默认向右走
269                     current_direction = "R";//当前方向
270                     first_launch = false;
271                     iseaten = false;
272                     isrun = true;
273                     body_length = 5;
274                     head = new Tile(227,100);
275                     Score.setText("6");
276                     hour =0;
277                     min =0;
278                     sec =0 ;
279                     for(int i = 0; i < MAX_SIZE;i++)
280                     {
281                         body[i].x = 0;
282                         body[i].y = 0;
283                     }
284                     
285                     run = new Thread();
286                     run.start();
287                     System.out.println("Start again");
288                 }
289                 else
290                 {
291                     run.stop();
292                 }        
293             }
294         }
295         if(current_direction == "R")
296         {
297             if(head.x > 489)
298             {
299                 new AePlayWave("over.wav").start();
300                 isrun = false;
301                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
302                 if(result==JOptionPane.YES_NO_OPTION)
303                 {
304                     direction = "R";//默认向右走
305                     current_direction = "R";//当前方向
306                     first_launch = false;
307                     iseaten = false;
308                     isrun = true;
309                     body_length = 5;
310                     head = new Tile(227,100);
311                     Score.setText("6");
312                     hour =0;
313                     min =0;
314                     sec =0 ;
315                     for(int i = 0; i < MAX_SIZE;i++)
316                     {
317                         body[i].x = 0;
318                         body[i].y = 0;
319                     }
320                     
321                     run = new Thread();
322                     run.start();
323                     System.out.println("Start again");
324                 }
325                 else
326                 {
327                     run.stop();
328                 }
329             }
330         }
331         if(current_direction == "U")
332         {
333             if(head.y < 12)
334             {
335                 new AePlayWave("over.wav").start();
336                 isrun = false;
337                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
338                 if(result==JOptionPane.YES_NO_OPTION)
339                 {
340                     direction = "R";//默认向右走
341                     current_direction = "R";//当前方向
342                     first_launch = false;
343                     iseaten = false;
344                     isrun = true;
345                     body_length = 5;
346                     head = new Tile(227,100);
347                     Score.setText("6");
348                     hour =0;
349                     min =0;
350                     sec =0 ;
351                     for(int i = 0; i < MAX_SIZE;i++)
352                     {
353                         body[i].x = 0;
354                         body[i].y = 0;
355                     }
356                     
357                     run = new Thread();
358                     run.start();
359                     System.out.println("Start again");
360                 }
361                 else
362                 {
363                     run.stop();
364                 }
365             }
366         }
367         if(current_direction == "D")
368         {
369             if(head.y > 472)
370             {
371                 new AePlayWave("over.wav").start();
372                 isrun = false;
373                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
374                 if(result==JOptionPane.YES_NO_OPTION)
375                 {
376                     direction = "R";//默认向右走
377                     current_direction = "R";//当前方向
378                     first_launch = false;
379                     iseaten = false;
380                     isrun = true;
381                     body_length = 5;
382                     head = new Tile(227,100);
383                     Score.setText("6");
384                     hour =0;
385                     min =0;
386                     sec =0 ;
387                     for(int i = 0; i < MAX_SIZE;i++)
388                     {
389                         body[i].x = 0;
390                         body[i].y = 0;
391                     }
392                     
393                     run = new Thread();
394                     run.start();
395                     System.out.println("Start again");
396                 }
397                 else
398                 {
399                     run.stop();
400                 }
401             }
402         }
403     }
404     
405     public void HitSelf(){//判断是否撞到自己身上
406         for(int i = 0;i < body_length; i++)
407         {
408             if(body[i].x == head.x && body[i].y == head.y)
409             {
410                 new AePlayWave("over.wav").start();
411                 isrun = false;
412                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
413                 if(result==JOptionPane.YES_NO_OPTION)
414                 {
415                     direction = "R";//默认向右走
416                     current_direction = "R";//当前方向
417                     first_launch = false;
418                     iseaten = false;
419                     isrun = true;
420                     body_length = 5;
421                     head = new Tile(227,100);
422                     Score.setText("6");
423                     hour =0;
424                     min =0;
425                     sec =0 ;
426                     for(int j = 0; j < MAX_SIZE;j++)
427                     {
428                         body[j].x = 0;
429                         body[j].y = 0;
430                     }
431                     
432                     run = new Thread();
433                     run.start();
434                     System.out.println("Start again");
435                 }
436                 else
437                 {
438                     run.stop();
439                 }
440                 break;
441             }
442         }
443     }
444     
445     public boolean  EatFood(){
446         if(head.x == randomx && head.y == randomy)
447         {
448             iseaten = true;
449             return true;
450         }
451         else
452         {
453             return false;
454         }
455     }
456     
457     public void Thread(){
458         long millis = 300;//每隔300毫秒刷新一次
459         run = new Thread() {
460             public void run() {
461                 while (true) 
462                 {
463                     try {
464                         Thread.sleep(millis);
465                     } catch (InterruptedException ex) {
466                         ex.printStackTrace();
467                     }
468                     
469                     temp.x = head.x;
470                     temp.y = head.y;
471                     //头部移动
472                     if(direction == "L")
473                     {
474                         head.x -= 22;
475                     }
476                     if(direction == "R")
477                     {
478                         head.x += 22;
479                     }
480                     if(direction == "U")
481                     {
482                         head.y -= 22;
483                     }
484                     if(direction == "D")
485                     {
486                         head.y += 22;
487                     }
488                     current_direction = direction;//刷新当前前进方向
489                     //身体移动
490                     for(int i = 0;i < body_length;i++)
491                     {
492                         temp2.x = body[i].x;
493                         temp2.y = body[i].y;
494                         body[i].x = temp.x;
495                         body[i].y = temp.y;
496                         temp.x = temp2.x;
497                         temp.y = temp2.y;
498                     }
499                     
500                     if(EatFood())
501                     {
502                         body_length ++;
503                         body[body_length-1].x = temp2.x;
504                         body[body_length-1].y = temp2.y;
505                         Score.setText("" + (body_length+1) );
506                         new AePlayWave("eat.wav").start();
507                     }
508                     
509                     repaint();
510                     
511                     HitWall();
512                     HitSelf();
513                 }
514             }
515         };
516         
517         run.start();
518     }
519     
520     public static void main(String[] args) {
521         SnakeDemo t = new SnakeDemo();
522         t.Thread();
523         
524         JFrame game = new JFrame();
525         Image img=Toolkit.getDefaultToolkit().getImage("title.png");//窗口图标
526         game.setIconImage(img);
527         game.setTitle("Snake By XJX");
528         game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
529 //        game.setSize(502, 507);
530         game.setSize(602, 507);
531         game.setResizable(false);
532         game.setLocationRelativeTo(null);
533        
534         game.add(t);
535         game.setVisible(true);
536     }
537     
538     //计时器类
539     class Timer extends Thread{  
540             public Timer(){
541                 this.start();
542             }
543             @Override
544             public void run() {
545                 // TODO Auto-generated method stub
546                 while(true){
547                     if(isrun){
548                         sec +=1 ;
549                         if(sec >= 60){
550                             sec = 0;
551                             min +=1 ;
552                         }
553                         if(min>=60){
554                             min=0;
555                             hour+=1;
556                         }
557                         showTime();
558                     }
559          
560                     try {
561                         Thread.sleep(1000);
562                     } catch (InterruptedException e) {
563                         // TODO Auto-generated catch block
564                         e.printStackTrace();
565                     }
566                      
567                 }
568             }
569 
570             private void showTime(){
571                 String strTime ="" ;
572                 if(hour < 10)
573                     strTime = "0"+hour+":";
574                 else
575                     strTime = ""+hour+":";
576                  
577                 if(min < 10)
578                     strTime = strTime+"0"+min+":";
579                 else
580                     strTime =strTime+ ""+min+":";
581                  
582                 if(sec < 10)
583                     strTime = strTime+"0"+sec;
584                 else
585                     strTime = strTime+""+sec;
586                  
587                 //在窗体上设置显示时间
588                 Time.setText(strTime);
589             }
590         }    
591 }
592 
593 class AePlayWave extends Thread {      
594     private String filename;
595     private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb 
596 
597     public AePlayWave(String wavfile) { 
598         filename = wavfile;
599     } 
600             
601     public void run() { 
602         File soundFile = new File(filename); 
603         AudioInputStream audioInputStream = null;
604         try { 
605             audioInputStream = AudioSystem.getAudioInputStream(soundFile);
606         } catch (UnsupportedAudioFileException e1) { 
607             e1.printStackTrace();
608             return;
609         } catch (IOException e1) { 
610             e1.printStackTrace();
611             return;
612         } 
613  
614         AudioFormat format = audioInputStream.getFormat();
615         SourceDataLine auline = null;
616         DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
617  
618         try { 
619             auline = (SourceDataLine) AudioSystem.getLine(info);
620             auline.open(format);
621         } catch (LineUnavailableException e) { 
622             e.printStackTrace();
623             return;
624         } catch (Exception e) { 
625             e.printStackTrace();
626             return;
627         } 
628 
629         auline.start();
630         int nBytesRead = 0;
631         byte[] abData = http://www.mamicode.com/new byte[EXTERNAL_BUFFER_SIZE];
632  
633         try { 
634             while (nBytesRead != -1) { 
635                 nBytesRead = audioInputStream.read(abData, 0, abData.length);
636                 if (nBytesRead >= 0) 
637                     auline.write(abData, 0, nBytesRead);
638             } 
639         } catch (IOException e) { 
640             e.printStackTrace();
641             return;
642         } finally { 
643             auline.drain();
644             auline.close();
645         } 
646     } 
647 }

 

Java实现贪吃蛇游戏【代码】