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

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

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

游戏界面图如下:

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

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

以后版本更新都将放到 Github: 

https://github.com/JiaxinTse/Snake

另外,第四版的游戏截图请看下一篇文章,比此处的Demo版丰富了很多:

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

 

(注:转载和使用请务必事先向本人声明)

 

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

  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 }

 (注:转载和使用请务必事先向本人声明!)

转载于:https://www.cnblogs.com/journal-of-xjx/p/7173863.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值