Java實現貪吃蛇遊戲【代碼】

花了兩個下午寫了一個貪吃蛇小遊戲,本人想寫這遊戲很長時間了。做爲之前諾基亞手機上的經典遊戲,貪吃蛇和俄羅斯方塊同樣,都曾經在咱們的童年給咱們帶來了不少樂趣。世間萬物斗轉星移,諾基亞曾經做爲手機業的龍頭老大,現現在也一步步走向衰落,被收購,再過不久估計就要退出手機業務了,而貪吃蛇這款遊戲也基本上沒人玩了,甚至在新一代人的印象中都已毫無記憶了。。。可是,這款遊戲在它基礎上通過改造其實能夠弄出不少花樣,也確實能夠在必定程度上鍛鍊本身的編程能力。前不久十分火熱的貪吃蛇大做戰其實就能夠看作是在這款遊戲的基礎上進行的改造。因此,我也但願本身能夠嘗試如下,作個有意思的版本。html

目前這個版本只是爲了後期版本的一個測試版本,因此只有一些基本功能,原本是打算這個版本實現了移動,吃食物增加,判斷撞牆和撞本身的身體就好了,無奈以爲有點單調,因而在此基礎上加上了一個計時器,記分功能,從新開始,開始暫停以及音效。白白又多了幾百行代碼。原來的基本代碼也就300行。java

遊戲界面圖以下:git

注意運行時請附帶如下文件:github

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

之後版本更新都將放到 Github: dom

https://github.com/JiaxinTse/Snakeide

另外,第四版的遊戲截圖請看下一篇文章,比此處的Demo版豐富了不少:佈局

http://www.cnblogs.com/journal-of-xjx/p/7217799.html測試

 

(注:轉載和使用請務必事先向本人聲明)this

 

------------------------------------------------------------如下是代碼區-----------------------------------------------------------------

  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行,加上一些顯示,計時和音效後多了幾百行。\n"
 42             + "遊戲界面按上下左右鍵實現移動,按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 pause = 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                     if(isrun && current_direction != "L")
108                     {
109                         direction = "R";
110                     }
111                 }
112                 if(e.getKeyCode() == KeyEvent.VK_LEFT)
113                 {
114                     if(isrun && current_direction != "R")
115                     {
116                         direction = "L";
117                     }
118                 }
119                 if(e.getKeyCode() == KeyEvent.VK_UP)
120                 {
121                     if(isrun && current_direction != "D")
122                     {
123                         direction = "U";
124                     }
125                 }
126                 if(e.getKeyCode() == KeyEvent.VK_DOWN)
127                 {
128                     if(isrun && current_direction != "U")
129                     {
130                         direction = "D";
131                     }
132                 }
133                 if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
134                 {
135                     direction = "R";//默認向右走
136                     current_direction = "R";//當前方向
137                     first_launch = false;
138                     iseaten = false;
139                     isrun = true;
140                     body_length = 5;
141                     head = new Tile(227,100);
142                     Score.setText("6");
143                     hour =0;
144                     min =0;
145                     sec =0 ;
146                     for(int i = 0; i < MAX_SIZE;i++)
147                     {
148                         body[i].x = 0;
149                         body[i].y = 0;
150                     }
151                     
152                     run = new Thread();
153                     run.start();
154                     System.out.println("Start again");
155                 }
156                 if(e.getKeyCode() == KeyEvent.VK_SPACE)//按空格鍵開始和暫停暫時沒作,還在思考中
157                 {
158                     if(!pause)//暫停
159                     {
160                         pause = true;
161                         isrun = false;
162                     }
163                     else//開始
164                     {
165                         pause = false;
166                         isrun = true;
167                     }
168                 }
169             }
170         });
171         
172         new Timer();
173         
174         setFocusable(true);
175     }
176     
177     public void paintComponent(Graphics g1){
178         super.paintComponent(g1);
179         Graphics2D g = (Graphics2D) g1;
180         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
181         g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_NORMALIZE);
182         
183         //畫頭部
184         g.setColor(Color.red);
185         g.fillRoundRect(head.x, head.y, 20, 20, 10, 10);
186         
187         g.setPaint(new GradientPaint(115,135,Color.CYAN,230,135,Color.MAGENTA,true));
188         if(!first_launch)
189         {
190             //初始化身體
191             int x = head.x;
192             for(int i = 0;i < body_length;i++)
193             {
194                 x -= 22;//相鄰兩個方塊的間距爲2個像素,方塊寬度都爲20像素
195                 body[i].x = x;
196                 body[i].y = head.y;
197                 g.fillRoundRect(body[i].x, body[i].y, 20, 20, 10, 10);
198             }
199             //初始化食物位置
200             ProduceRandom();
201             g.fillOval(randomx, randomy, 19, 19);
202         }
203         else
204         {
205             //每次刷新身體
206             for(int i = 0;i < body_length;i++)
207             {
208                 g.fillRoundRect(body[i].x, body[i].y, 20, 20, 10, 10);
209             }
210             
211             if(EatFood())//被吃了從新產生食物
212             {
213                 ProduceRandom();
214                 g.fillOval(randomx, randomy, 19, 19);
215                 iseaten = false;
216             }
217             else
218             {
219                 g.fillOval(randomx, randomy, 19, 19);
220             }
221         }
222         first_launch = true;
223         //
224         g.setStroke( new BasicStroke(4,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
225         g.setBackground(Color.black);
226         g.drawRect(2, 7, 491, 469);
227         
228         //網格線
229         for(int i = 1;i < 22;i++)
230         {
231             g.setStroke( new BasicStroke(1,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
232             g.setColor(Color.black);
233             g.drawLine(5+i*22,9,5+i*22,472);
234             if(i <= 20)
235             {
236                 g.drawLine(4,10+i*22,491,10+i*22);
237             }
238         }
239     }
240     
241     public void ProduceRandom(){
242         boolean flag = true;
243         Random rand = new Random();
244         randomx = (rand.nextInt(21) + 1) * 22 + 7;
245         randomy = (rand.nextInt(20) + 1) *22 + 12;
246         while(flag)
247         {
248             for(int i = 0;i < body_length; i++)
249             {
250                 if(body[i].x == randomx && body[i].y == randomy)
251                 {
252                     randomx = (rand.nextInt(21) + 1) * 22 + 7;
253                     randomy = (rand.nextInt(20) + 1) *22 + 12;
254                     flag = true;
255                     break;
256                 }
257                 else
258                 {
259                     if(i == body_length - 1)
260                     {
261                         flag = false;
262                     }
263                 }
264             }
265         }
266     }
267     
268     public void HitWall(){//判斷是否撞牆
269         if(current_direction == "L")
270         {
271             if(head.x < 7)
272             {
273                 new AePlayWave("over.wav").start();
274                 isrun = false;
275                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
276                 if(result==JOptionPane.YES_NO_OPTION)
277                 {
278                     direction = "R";//默認向右走
279                     current_direction = "R";//當前方向
280                     first_launch = false;
281                     iseaten = false;
282                     isrun = true;
283                     body_length = 5;
284                     head = new Tile(227,100);
285                     Score.setText("6");
286                     hour =0;
287                     min =0;
288                     sec =0 ;
289                     for(int i = 0; i < MAX_SIZE;i++)
290                     {
291                         body[i].x = 0;
292                         body[i].y = 0;
293                     }
294                     
295                     run = new Thread();
296                     run.start();
297                     System.out.println("Start again");
298                 }
299                 else
300                 {
301                     run.stop();
302                 }        
303             }
304         }
305         if(current_direction == "R")
306         {
307             if(head.x > 489)
308             {
309                 new AePlayWave("over.wav").start();
310                 isrun = false;
311                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
312                 if(result==JOptionPane.YES_NO_OPTION)
313                 {
314                     direction = "R";//默認向右走
315                     current_direction = "R";//當前方向
316                     first_launch = false;
317                     iseaten = false;
318                     isrun = true;
319                     body_length = 5;
320                     head = new Tile(227,100);
321                     Score.setText("6");
322                     hour =0;
323                     min =0;
324                     sec =0 ;
325                     for(int i = 0; i < MAX_SIZE;i++)
326                     {
327                         body[i].x = 0;
328                         body[i].y = 0;
329                     }
330                     
331                     run = new Thread();
332                     run.start();
333                     System.out.println("Start again");
334                 }
335                 else
336                 {
337                     run.stop();
338                 }
339             }
340         }
341         if(current_direction == "U")
342         {
343             if(head.y < 12)
344             {
345                 new AePlayWave("over.wav").start();
346                 isrun = false;
347                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
348                 if(result==JOptionPane.YES_NO_OPTION)
349                 {
350                     direction = "R";//默認向右走
351                     current_direction = "R";//當前方向
352                     first_launch = false;
353                     iseaten = false;
354                     isrun = true;
355                     body_length = 5;
356                     head = new Tile(227,100);
357                     Score.setText("6");
358                     hour =0;
359                     min =0;
360                     sec =0 ;
361                     for(int i = 0; i < MAX_SIZE;i++)
362                     {
363                         body[i].x = 0;
364                         body[i].y = 0;
365                     }
366                     
367                     run = new Thread();
368                     run.start();
369                     System.out.println("Start again");
370                 }
371                 else
372                 {
373                     run.stop();
374                 }
375             }
376         }
377         if(current_direction == "D")
378         {
379             if(head.y > 472)
380             {
381                 new AePlayWave("over.wav").start();
382                 isrun = false;
383                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
384                 if(result==JOptionPane.YES_NO_OPTION)
385                 {
386                     direction = "R";//默認向右走
387                     current_direction = "R";//當前方向
388                     first_launch = false;
389                     iseaten = false;
390                     isrun = true;
391                     body_length = 5;
392                     head = new Tile(227,100);
393                     Score.setText("6");
394                     hour =0;
395                     min =0;
396                     sec =0 ;
397                     for(int i = 0; i < MAX_SIZE;i++)
398                     {
399                         body[i].x = 0;
400                         body[i].y = 0;
401                     }
402                     
403                     run = new Thread();
404                     run.start();
405                     System.out.println("Start again");
406                 }
407                 else
408                 {
409                     run.stop();
410                 }
411             }
412         }
413     }
414     
415     public void HitSelf(){//判斷是否撞到本身身上
416         for(int i = 0;i < body_length; i++)
417         {
418             if(body[i].x == head.x && body[i].y == head.y)
419             {
420                 new AePlayWave("over.wav").start();
421                 isrun = false;
422                 int result=JOptionPane.showConfirmDialog(null, "Game over! Try again?", "Information", JOptionPane.YES_NO_OPTION);
423                 if(result==JOptionPane.YES_NO_OPTION)
424                 {
425                     direction = "R";//默認向右走
426                     current_direction = "R";//當前方向
427                     first_launch = false;
428                     iseaten = false;
429                     isrun = true;
430                     body_length = 5;
431                     head = new Tile(227,100);
432                     Score.setText("6");
433                     hour =0;
434                     min =0;
435                     sec =0 ;
436                     for(int j = 0; j < MAX_SIZE;j++)
437                     {
438                         body[j].x = 0;
439                         body[j].y = 0;
440                     }
441                     
442                     run = new Thread();
443                     run.start();
444                     System.out.println("Start again");
445                 }
446                 else
447                 {
448                     run.stop();
449                 }
450                 break;
451             }
452         }
453     }
454     
455     public boolean  EatFood(){
456         if(head.x == randomx && head.y == randomy)
457         {
458             iseaten = true;
459             return true;
460         }
461         else
462         {
463             return false;
464         }
465     }
466     
467     public void Thread(){
468         long millis = 300;//每隔300毫秒刷新一次
469         run = new Thread() {
470             public void run() {
471                 while (true) 
472                 {
473                     try {
474                         Thread.sleep(millis);
475                     } catch (InterruptedException ex) {
476                         ex.printStackTrace();
477                     }
478                     
479                     if(!pause)
480                     {    
481                         temp.x = head.x;
482                         temp.y = head.y;
483                         //頭部移動
484                         if(direction == "L")
485                         {
486                             head.x -= 22;
487                         }
488                         if(direction == "R")
489                         {
490                             head.x += 22;
491                         }
492                         if(direction == "U")
493                         {
494                             head.y -= 22;
495                         }
496                         if(direction == "D")
497                         {
498                             head.y += 22;
499                         }
500                         current_direction = direction;//刷新當前前進方向
501                         //身體移動
502                         for(int i = 0;i < body_length;i++)
503                         {
504                             temp2.x = body[i].x;
505                             temp2.y = body[i].y;
506                             body[i].x = temp.x;
507                             body[i].y = temp.y;
508                             temp.x = temp2.x;
509                             temp.y = temp2.y;
510                         }
511                         
512                         if(EatFood())
513                         {
514                             body_length ++;
515                             body[body_length-1].x = temp2.x;
516                             body[body_length-1].y = temp2.y;
517                             Score.setText("" + (body_length+1) );
518                             new AePlayWave("eat.wav").start();
519                         }
520                         
521                         repaint();
522                         
523                         HitWall();
524                         HitSelf();
525                     }
526                 }
527             }
528         };
529         
530         run.start();
531     }
532     
533     public static void main(String[] args) {
534         SnakeDemo t = new SnakeDemo();
535         t.Thread();
536         
537         JFrame game = new JFrame();
538         Image img=Toolkit.getDefaultToolkit().getImage("title.png");//窗口圖標
539         game.setIconImage(img);
540         game.setTitle("Snake By XJX");
541         game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
542 //        game.setSize(502, 507);
543         game.setSize(602, 507);
544         game.setResizable(false);
545         game.setLocationRelativeTo(null);
546        
547         game.add(t);
548         game.setVisible(true);
549     }
550     
551     //計時器類
552     class Timer extends Thread{  
553             public Timer(){
554                 this.start();
555             }
556             @Override
557             public void run() {
558                 // TODO Auto-generated method stub
559                 while(true){
560                     if(isrun){
561                         sec +=1 ;
562                         if(sec >= 60){
563                             sec = 0;
564                             min +=1 ;
565                         }
566                         if(min>=60){
567                             min=0;
568                             hour+=1;
569                         }
570                         showTime();
571                     }
572          
573                     try {
574                         Thread.sleep(1000);
575                     } catch (InterruptedException e) {
576                         // TODO Auto-generated catch block
577                         e.printStackTrace();
578                     }
579                      
580                 }
581             }
582 
583             private void showTime(){
584                 String strTime ="" ;
585                 if(hour < 10)
586                     strTime = "0"+hour+":";
587                 else
588                     strTime = ""+hour+":";
589                  
590                 if(min < 10)
591                     strTime = strTime+"0"+min+":";
592                 else
593                     strTime =strTime+ ""+min+":";
594                  
595                 if(sec < 10)
596                     strTime = strTime+"0"+sec;
597                 else
598                     strTime = strTime+""+sec;
599                  
600                 //在窗體上設置顯示時間
601                 Time.setText(strTime);
602             }
603         }    
604 }
605 
606 class AePlayWave extends Thread {      
607     private String filename;
608     private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb 
609 
610     public AePlayWave(String wavfile) { 
611         filename = wavfile;
612     } 
613             
614     public void run() { 
615         File soundFile = new File(filename); 
616         AudioInputStream audioInputStream = null;
617         try { 
618             audioInputStream = AudioSystem.getAudioInputStream(soundFile);
619         } catch (UnsupportedAudioFileException e1) { 
620             e1.printStackTrace();
621             return;
622         } catch (IOException e1) { 
623             e1.printStackTrace();
624             return;
625         } 
626  
627         AudioFormat format = audioInputStream.getFormat();
628         SourceDataLine auline = null;
629         DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
630  
631         try { 
632             auline = (SourceDataLine) AudioSystem.getLine(info);
633             auline.open(format);
634         } catch (LineUnavailableException e) { 
635             e.printStackTrace();
636             return;
637         } catch (Exception e) { 
638             e.printStackTrace();
639             return;
640         } 
641 
642         auline.start();
643         int nBytesRead = 0;
644         byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
645  
646         try { 
647             while (nBytesRead != -1) { 
648                 nBytesRead = audioInputStream.read(abData, 0, abData.length);
649                 if (nBytesRead >= 0) 
650                     auline.write(abData, 0, nBytesRead);
651             } 
652         } catch (IOException e) { 
653             e.printStackTrace();
654             return;
655         } finally { 
656             auline.drain();
657             auline.close();
658         } 
659     } 
660 }

 (注:轉載和使用請務必事先向本人聲明!)

相關文章
相關標籤/搜索