JAVA版贪吃蛇小游戏

这是一篇关于JAVA的贪吃蛇游戏,源代码的部分在下面正文中介绍,图片和音频的部分都放在百度云盘,需要的自行下载。


开发环境

开发工具:eclipse2021-12
JDK版本:JDK15.0.1


一、下载方法

百度云盘
链接:https://pan.baidu.com/s/1P9bwYgXkoRVaKdOOuWvUng
提取码:fcfj
编码格式:GBK

二、运行效果展示

运行代码以后,进入登录页面,点击“进入游戏”。
在这里插入图片描述
进入游戏的画面。此时小蛇还没有移动。
在这里插入图片描述
游戏运行时的画面
在这里插入图片描述
游戏运行时:
点击屏幕上方区域,小蛇转向上方
点击屏幕下方区域,小蛇转向下方
点击屏幕左方区域,小蛇转向左方
点击屏幕右方区域,小蛇转向右方

三、项目结构以及主程序入口

1.项目结构

在这里插入图片描述

2.主程序入口

入口程序在Start.java类中。
在这里插入图片描述

四、代码部分

1.代码如下

代码如下(示例):
Start.java类

package snakeGame;

/* Test类的主要任务是设计程序运行后的界面,包括 程序启动的界面和游戏运行界面。
 * 程序启动的界面包括背景图片和进入运行界面的Button,点击按钮之后程序关闭启动界面进入到运行界面,
 * 运行界面设置在SnakeGame类中,Test类大体设置了运行界面的大小可见与否等。
 */

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Start    extends JFrame implements ActionListener  {
    
    	   
	static  JFrame frame = new  JFrame( );
	public static void main(String[] args) {
    
    
		System.out.print("main");
    	 new  Start();                                         
    }
	public  Start(){
    
                                                     //设置启动界面
		System.out.print("构造函数star");
		 frame.setUndecorated(true);                                //用于取消边框背景
         frame.setLayout (null);
         frame.setSize(1600,900);
         frame.setLocation(300, 100);
         frame.setLocationRelativeTo (null);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
         AddButton();
         AddPicture();            
	}  	
	//定义进入游戏按钮	
	public  void  AddButton() {
    
    	                                      
		RButton  enterButton =new RButton("进入游戏");
        enterButton.setFont(new Font("华文行楷", Font.BOLD, 35));
        enterButton.setForeground(Color.red);
        enterButton.setBounds (700,  600 , 200, 100);
        enterButton.setBackground(Color.white);      
        frame.add(enterButton);
        enterButton.addActionListener(this); 
        //定义按键         
	}
  //加入背景图片
	public  void  AddPicture() {
    
    	                                           	
		ImageIcon img = new ImageIcon("src\\image\\timg.jpg");
        JLabel Label= new JLabel(img);
        Label.setBounds(0,0,img.getIconWidth(),img.getIconHeight());            //设置大小
        frame.getLayeredPane().add(Label,new Integer(Integer.MIN_VALUE));      //设置图片底层和按钮在容器中的顺序   
        JPanel  jp  =(JPanel)frame.getContentPane();   
        jp.setOpaque(false);                                                   //设置透明与否
	}
	
	/*设置按钮的监听器事件
	 * 进入按钮的监听器事件的主要功能是当点击按钮以后,程序关掉启动界面,并转入运行界面。
	 * 主要实现原理是定义一个新界面的类,作为运行界面,然后定义一个关掉启动界面的方法,然后在监听器事件中,
	 * 调用关掉界面的方法,实例化运行界面 
	 */
	@Override
	 
	public void actionPerformed(ActionEvent e) {
    
                                      
		new  pushButtonMusic ();		 
		// TODO 自动生成的方法存根
		closeThis();		                                                       //关掉新界面的方法
	    try {
    
    	    
			new Frame2 ();                                                         //实例化运行界面
		} catch (InterruptedException e1) {
    
    
			// TODO 自动生成的 catch 块
			e1.printStackTrace();
		}  //创建新的窗体,以达到切换窗体的效果
	}	
	 private void closeThis() {
    
    
		// TODO 自动生成的方法存根
		 frame.dispose();
	}
	 /*
	  * 游戏运行界面,实例化SnakeGame类,并加入到运行界面中
	  */
	 class  Frame2 extends JFrame      {
    
      		 	 		   		  			  
		     JFrame    frame1 = new  JFrame(); //游戏图形界面            
		      public   Frame2() throws InterruptedException{
    
    			  				 					    		  		  
			  frame1.setUndecorated(true);
			  frame1.setBounds(200,70,1600,900);		           		 
			//  frame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			  frame1.setVisible(true);			  
	          SnakeGame sn = new SnakeGame();	         
	          frame1.add(sn);
	          sn.requestFocus();//布局的中间	         	         
			}			 
      }	 
}

SnakeNode.java类

package snakeGame;
/*
 * 定义一个类,用来描述贪吃蛇游戏中的蛇,蛇身上的每一个点,通过建立snakeNode的对象,指定不同的X轴和Y轴的值,就能组成一个蛇身。
 * 同时可以获得蛇身上的x和y点坐标,和颜色
 */
import java.awt.Color;

public class SnakeNode {
    
        //定义蛇身集合中的各个元素点,x,y。以及颜色三个蛇的关键组成
    private int x;
    private int y;
    private Color color;
	 
	public int setX=20;
	public int setY=20;
	 
    public SnakeNode() {
    
    
        super();

    }
    public SnakeNode(int x, int y, Color color) {
    
    
        super();
        this.x = x;
        this.y = y;
        this.color = color;
    }
    public int getX() {
    
    
        return x;
    }
    public void setX(int x) {
    
    
        this.x = x;
    }
    public int getY() {
    
    
        return y;
    }
    public void setY(int y) {
    
    
        this.y = y;
    }
    public Color getColor() {
    
    
        return color;
    }
    public void setColor(Color color) {
    
    
        this.color = color;
    }
}

SnakeGame.java类

package snakeGame;

/*
 * SnakeGame类来设计贪吃蛇小游戏的运行界面,运行界面是贪吃蛇游戏的主体部分,  界面主要包括两个方面的内容,
 * 一方面是运行界面的内容,贪吃蛇长度显示,游戏说明,速度控制,游戏开始,暂停退出等按钮。
 * 另一方面,主要包括贪吃蛇的形状和移动,贪吃蛇移动区域,随机点的定义
 * 运行界面的过程是这样的:在开始姐爱你点击进入游戏按钮以后,程序运行到运行界面,开始播放背景音乐。
 * 点击游戏说明按钮,弹出一个对话框,说明游戏运行的操作过程。点击开始按钮以后,
 * 贪吃蛇开始向上移动,鼠标在向上区域点击,贪吃蛇向上,向左区域点击,贪吃蛇向左,依次赖推。
 * 当贪吃蛇碰到草莓时,吃掉它,蛇身变长,并有背景音乐显示,长度显示加一,
 * 点击暂停按钮游戏暂停,点击退出按钮后,退出游戏。
 * 当贪吃蛇撞到自己或者墙体的时候,贪吃蛇会死亡,然后弹出一个界面,重启界面,用来决定游戏继续进行或者退出游戏。
 * 贪吃蛇的形状和移动通过数组的形式实现,在界面中,定义一个x轴和y轴定义的坐标系,定义一个数组,数组的移动就是贪吃蛇的移动,
 * 移动方式是贪吃蛇坐标的改变,可以通过鼠标控制或键盘控制来实现贪吃蛇的移动,
 * 随机点产生是在坐标系中产生随机数来实现,
 */
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JApplet;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.Timer;

 

public class SnakeGame extends JPanel  implements ActionListener   {
    
    	 
      private final int length = 15;//定义活动范围
      private final int width = 25;//定义活动范围
      private final int unit = 45;//定义单位长度
      private final  int GameLOCX=40;
      private final  int  GameLOCY=40;
      private  final int GameWidth=width*unit;
      private  final  int GameLength=length*unit;
      //随机点坐标   
      int newY1 =0 ; 
      int newX1 = 0 ;  
      
      int mousex=1;
      int mousey=1;
      //播放背景音乐
		AudioClip christmas = loadSound("src/Music/backgroundMusic.wav");
      int direction = 1;//定义一个按下按钮后要去的方向                 
      private ArrayList<SnakeNode> snake = new ArrayList<SnakeNode>();//定义蛇身的数组集合
      private int Direction;//定义蛇头的方向
      private int Length ;//定义蛇身的长度
      private SnakeNode newNode = new SnakeNode(1,1,Color.BLACK);//定义随机点
          
       boolean  startFlag  =false;
      //定义按钮,速度控制,开始暂停退出按钮等
       RButton   SspeedButton , TspeedButton,FspeedButton,THspeedButton ,ShowButton; 
       RButton    startButton , stopButton , quitButton  ,reStartButton,closeButton;
       //定义标签,长度显示,方向显示,按钮提示等   
       JLabel  snakeScore, label1,  label3,label4;
       //初始速度控制
       private static int Difficult_Degree=1;
       //蛇的移动控制,利用线程来实现用鼠标控制,利用计时器来实现用键盘控制。
      Thread  tr= new Thread(new ThingsListener());
      Timer time = new Timer(1000, new ThingsListener1());//定义一个定时器对象,这里我们还要创建一个ThingsListener事件
      
      public SnakeGame() {
    
    //初始化区域
    	 //循环播放背景音乐
    	  christmas.loop ();
    	  
    	 // time.start(); 
         tr.start();   	 
    	  //定义按键
         //在容器中添加按钮标签等的时候,需要说明布局管理为空,不然的话,加进去的按钮会按照一定的布局来实现,
    	  this.setLayout (null);
    	  //定义按钮
         startButton = new  RButton("开始游戏"); 	 
		  stopButton =new  RButton("暂停游戏");
		  quitButton =new  RButton("退出游戏");
		  
		  FspeedButton =new  RButton("速度一");		          
		  SspeedButton =new  RButton("速度二");
		  TspeedButton=new  RButton("速度三");
		  THspeedButton=new  RButton("速度四");		
	      ShowButton  =new   RButton("游戏指南");
		  	
	      //定义标签
		  snakeScore =new  JLabel("3");
		  label1 =new  JLabel("当前长度");
		   		 
		  label3 =new  JLabel("速度设置");
		  label4 =new  JLabel( );
          
		  //设置字体
		  startButton.setFont(new Font("华文行楷", Font.BOLD, 35));
		  stopButton.setFont(new Font("华文行楷", Font.BOLD, 35));
		  quitButton.setFont(new Font("华文行楷", Font.BOLD, 35));
		 
		  FspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
		  TspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
		  SspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
		  THspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
		 
		  ShowButton.setFont(new Font("华文行楷", Font.BOLD, 30));
		  
		  label1.setFont(new Font("华文行楷", Font.BOLD, 35));
		  snakeScore.setFont(new Font("华文行楷", Font.BOLD, 50));
		  		 	 
		  label3.setFont(new Font("华文行楷", Font.BOLD, 30));
		  label4.setFont(new Font("华文行楷", Font.BOLD, 35));
		 //定义按钮标签位置
	      startButton.setBounds (1390, 500 , 190, 90);
	      stopButton.setBounds (1390,  600 , 190, 90);
	      quitButton.setBounds (1390,  700 , 190, 90);
	      snakeScore.setBounds(1450, 70, 150, 90);
	      label1.setBounds(1390, 10, 190, 90);
	      
	      ShowButton.setBounds(1390, 170, 190, 90);
	     
	      label3.setBounds(1390, 270, 190, 90);
	      label4.setBounds(0, 0, 190, 90);
          
	      FspeedButton.setBounds (1390, 350 , 85, 60);
	      SspeedButton.setBounds (1500,350 , 85, 60);
	      TspeedButton.setBounds (1390, 420 , 85, 60);
	      THspeedButton.setBounds (1500, 420 , 85, 60);
	     
	      THspeedButton.setBackground(Color.green);
		  SspeedButton.setBackground(Color.blue);
		  TspeedButton.setBackground(Color.red);
	      FspeedButton.setBackground(Color.red);
		  	      
	     // 添加 按钮和标签,用this关键字指向当前容器
	   
         this.add(startButton);
         this.add(stopButton);
         this.add(quitButton);

         this.add(FspeedButton);
         this.add(SspeedButton);
         this.add(TspeedButton);
         this.add(THspeedButton);
                          
         this.add(label1);
         this.add(snakeScore);        
         this.add( ShowButton);
         this.add(label3);
         this.add(label4);
         
        // 添加三个按键的监听事件
         startButton.addActionListener(this);
         stopButton.addActionListener(this);
         quitButton.addActionListener(this);
             
         THspeedButton.addActionListener(this);
         SspeedButton.addActionListener(this);
         TspeedButton.addActionListener(this);
         FspeedButton.addActionListener(this);
          ShowButton.addActionListener(this);
            
         snake.add(new SnakeNode(width/2,length/2 ,Color.red));
         snake.add(new SnakeNode(width/2,length/2+1 ,Color.blue));
         snake.add(new SnakeNode(width/2,length/2+2 ,Color.green));
    	 
          Direction = 1;//定义初始方向为向上
          Length = 3;//蛇身长度为3
          CreateNode1();//产生随机点
         // CreateNode2();
     /*//采用键盘控制的控制模式,利用键盘的上下左右键,来实现让·direction的变化,从而使贪吃蛇能够按照键盘的控制来实现移动
        this.addKeyListener(new KeyAdapter() {//捕捉键盘的按键事件 设置监听器
            public void keyPressed(KeyEvent e) {
            	 
                switch(e.getKeyCode()) {
                    case KeyEvent.VK_UP://按下向上,返回1
                        direction = 1;
                        break;
                    case KeyEvent.VK_DOWN://按下向下,返回-1
                        direction = -1;
                        break;
                    case KeyEvent.VK_LEFT://按下相左,返回2
                        direction = 2;
                        break;
                    case KeyEvent.VK_RIGHT://按下向右,返回-2
                        direction = -2;
                        break;
                    default:
                        break;
                }
                if(direction + Direction !=0) {//不能反向运动
                    Direction = direction;
                    Move(direction);
                    repaint();
                }
            }
        });
        */
             
        //采用 鼠标控制的控制模式     通过监听鼠标在容器中的位置,点击上下左右区域,改变direction的值,即可实现贪吃蛇的移动,
          this.addMouseListener(new MouseAdapter(){
    
      //匿名内部类,鼠标事件
              public void  mousePressed(MouseEvent e){
    
     
            	  int a=0;//鼠标完成点击事件
                     //e.getButton就会返回点鼠标的那个键,左键还是右健,3代表右键
                       mousex = e.getX();  //得到鼠标x坐标
                       mousey = e.getY();  //得到鼠标y坐标
                       double  k=0.6;            //直线斜率
                       double  Y1=0.6*mousex;
                       double  Y2=-0.6*mousex+810;
                       double   X1=1.6*mousey;
                       double   X2=-1.6*mousey+1350;
                       if(mousex > X1&&mousex<X2&&mousey>0&&mousey<405) {
    
       //第一象限  		向上
                    	   label4.setText( "向上" );
                       	a=1;   	 
                       }
                       if(mousex>X2&&mousex<X1&&mousey>405&&mousey<810) {
    
      // 第二象限             向下
                    	   label4.setText( "  向下" );
                       	 a=2;
                           }
                 if(mousex>0&&mousex<675&&mousey>Y1&&mousey<Y2) {
    
        //第三象限     向左
                    	   label4.setText( " 向左" );
                       	 a=3;
                            }   
                       if(mousex>675&&mousex<1350&&mousey>Y2&&mousey<Y1) {
    
       //第四象限    向右
                    	   label4.setText( "  向右" );
                           a=4;
                           } 
                
                      switch( a) {
    
    
                      case  1://按下向上,返回1
                          direction = 1;
                          break;
                      case 2://按下向下,返回-1
                          direction = -1;
                          break;
                      case 3://按下相左,返回2
                          direction = 2;
                          break;
                      case 4://按下向右,返回-2
                          direction = -2;
                          break;
                      default:
                          break;
                  }
                      
                      if(direction + Direction !=0) {
    
    //不能反向运动
                          Direction = direction;
                          Move(direction);
                            repaint();
                  }
                }
               
          });         
      } 
   /*定义蛇移动的方法  
    *   贪吃蛇的移动方法主要包括方向控制,碰到随机点,碰到自己,碰到边界以及设计贪吃蛇从前向后的移动
    * 
    */
      public void Move(int direction) {
    
                     	 
        int FirstX = snake.get(0).getX();            //获取蛇第一个点的横坐标
        int FirstY = snake.get(0).getY();            //获取蛇第一个点的纵坐标                  
        if(!startFlag) 
            return ; 
        //方向控制
        switch(direction) {
    
    
            case 1:
                FirstY--;
                break;
            case -1:
                FirstY++;
                break;
            case 2: 
                FirstX--;
                break;
            case -2:
                FirstX++;
                break;
            default:
                break;
        }
      //当碰到随机点时
        if(FirstX == newNode.getX()&&FirstY == newNode.getY()) {
    
     
        	new  eatFoodMusic();
            getNode();
            return;
        }
      //当碰到蛇身自己时
        for(int x = 0; x < Length; x++) {
    
     
            if((FirstX==snake.get(x).getX())&&(FirstY == snake.get(x).getY())) {
    
    
            	startFlag=false;
            	new  DeadMusic();
            	 new  Restart();   
            	 christmas.stop ();
            }
        }
         //当贪吃蛇撞到边界
        if(FirstX < 1  || FirstX >29  || FirstY < 1 || FirstY >18) {
    
            	
        	startFlag=false;
        	new  DeadMusic();
        	new  Restart();
        	 christmas.stop ();
        //	new  Test();
        } 
        //定义循环,使得贪吃蛇从前向后移动
        for(int x = Length - 1; x > 0; x--) {
    
    
            snake.get(x).setX(snake.get(x-1).getX());
            snake.get(x).setY(snake.get(x-1).getY());
        }
        snake.get(0).setX(FirstX);
        snake.get(0).setY(FirstY);
        repaint();
    }    
      //获取随机点
	public void getNode() {
    
                                
        snake.add(new SnakeNode());
        Length++;
        
        for(int x = Length-1; x >0; x--) {
    
    
            snake.get(x).setX(snake.get(x-1).getX());
            snake.get(x).setY(snake.get(x-1).getY());
            snake.get(x).setColor(snake.get(x-1).getColor());
        }
        snakeScore.setText( ""+( Length ));         //定义蛇的长度
        snake.get(0).setX(newNode.getX());
        snake.get(0).setY(newNode.getY());
        snake.get(0).setColor(newNode.getColor());
        CreateNode1();//产生随机点
       // CreateNode2();
        repaint();
        //当长度超过10的时候,产生鼓掌声
        if(Length==10) {
    
    
        	new  applauseMusic();
        }
    }
   
	public void CreateNode1() {
    
                         //创造随机点的方法                 
                            
           Boolean flag = true;
           while(flag) {
    
    
        	  newY1 = new Random().nextInt(15)+1;     
        	  newX1= new Random().nextInt(25)+1; 
        	  for(int x = 0; x < Length; x++) {
    
    
        	        if(snake.get(x).getX() == newX1 && snake.get(x).getY() == newY1) {
    
    
        	        flag = true;
        	        break;
        	        }
        	        flag = false; 
        	    }
        	//随机点不能超出面板,并且不能出现在蛇身上
                   
              for(int i = 0; i < Length; i++) {
    
    
                  if(snake.get(i).getX()> 5&& snake.get(i).getX()<newX1  &&snake.get(i).getY() > 5
                		  && snake.get(i).getY()<newY1) {
    
        
                      flag = true;
                      break;
                     }
                    flag= false;
              }
        }
                
       Color color = new Color(new Random().nextInt(255),new Random().nextInt(255),new Random().nextInt(255));
        newNode.setColor(color);
        newNode.setX(newX1);                                
        newNode.setY(newY1);                  
    }
	
/*
 * 这里是自己新建一个事件处理,每隔Timer的时间间隔,就开始移动Directon的位置,
 * 由因为Direction的位置是构造方法中定义好的,所以就会自动地移动方向。而每当玩家使用键盘时,Direction的值变化,之后每次自动移动的方向也随之变化。
 * 
 * 
 */
	//定义内部类,贪吃蛇不断移动
	
	public class ThingsListener1 implements ActionListener {
    
    
	    public void actionPerformed(ActionEvent e) {
    
    
	        Move(direction);
	        }
	    }// 

	public AudioClip loadSound ( String filename )
    {
    
    
     URL url = null;
      try
   {
    
    
    url = new URL ("file:" + filename);
    }
   catch (MalformedURLException e)
   {
    
    }
   return JApplet.newAudioClip (url);
   }
	
	/*
	 * 当startflag为真的时候,贪吃蛇在线程时间的脉冲下继续移动,这个过程包含在if语句块中,当程序启动时,每隔1.2s就有一个响应, 
	 *上一个方法采用Timer, Timer的构造方法是Timer(int delay, ActionListner listener)通俗的说就是创建一个每 delay秒触发一次动作的计时器,
	 * 每隔特定的时间就会触发特定的事件。可以使用start方法启动计时器。
	 * 优点在于形式简单,缺点在于当采用速度控制的时候不易控制,而同样作为时间触发作用的线程控制可以实现这个目的,即通过控制时间来控制贪吃蛇的移动速度
	 * 之所以之前的设计有错误,在于while后面没有用if进行startflag的检验,即startflag只有在真的条件下才可以移动,时间脉冲触发下才可以移动。
	 * 
	 * 	 
	*/
	//定义线程类,使得贪吃蛇能够在线程的控制下不断移动
    class ThingsListener  implements  Runnable   {
    
    
		@Override
		public void run() {
    
    
			// TODO 自动生成的方法存根
			while( true) {
    
    
				if(startFlag) {
    
          
				Move(Direction);
				repaint();
				}
				try {
    
    					
					Thread.sleep(1200/Difficult_Degree);
				}catch(InterruptedException  e){
    
    
					e.printStackTrace();
				}
			}	 		
		}//设置一个监听器事件,用来控制蛇的不断移动       
    }
   //定义图像类,画出贪吃蛇移动的运行界面,如贪吃蛇的形状,背景图片,蛇头蛇尾等      
   //描述蛇函数的主体形状,随机点的形状和蛇的形状 
   
    protected void paintComponent(Graphics g) {
    
    
        super.paintComponent(g);//加背景
        Image  im=Toolkit.getDefaultToolkit().getImage("src/image/background1.jpg");
        g.drawImage(im, 0, 0, this.getWidth(), this.getHeight(), this);//画出蛇头
      		if(direction ==1||Direction==1){
    
          			
      			
      			Toolkit toolup = this.getToolkit();
      	        Image headup =  toolup.getImage( "src/image/up.png");
      	        g.drawImage(headup,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);     	        
      		}else if(direction ==-1){
    
    
     			      	
      			 Toolkit tooldown = this.getToolkit();
      	        Image headdown =  tooldown.getImage( "src/image/down.png");
      	        g.drawImage(headdown,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
      	        
      		}else if(direction ==2){
    
    
            	Toolkit toolleft = this.getToolkit();
      	        Image headleft =  toolleft.getImage( "src/image/left.png");
      	        g.drawImage(headleft,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);      		
      		}else if(direction ==-2){
    
         			 
      			Toolkit toolright = this.getToolkit();
      	        Image headright =  toolright.getImage( "src/image/right.png");
      	        g.drawImage(headright,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
      	     	}      	      		
      	//画出食物的形状	      	 
        Toolkit tool1 = this.getToolkit();
        Image food=  tool1.getImage( "src/image/food.png");
        g.drawImage(food,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);       
        
        Toolkit tool2 = this.getToolkit();
        Image food1=  tool2.getImage( "src/image/food.png");
        g.drawImage(food1,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this); 
                        
      //绘制指定矩形的边框。矩形的左边和右边位于 x 和 x + width。顶边和底边位于 y 和 y + height。使用图形上下文的当前颜色绘制该矩形。
        g.drawRect(40, 30, 1350, 810 );             
        for(int x = 1; x < Length-1; x++) {
    
                       //利用循环,来绘制蛇的形状
            g.setColor(snake.get(x).getColor());
            g.fillOval(snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit, unit);   //给蛇的每一个节点画椭圆                  
        }                     
          for(int x = Length-1; x < Length; x++) {
    
            	       
        Toolkit toolright = this.getToolkit();
          Image headright =  toolright.getImage( "src/image/body.png");
  	       g.drawImage(headright,snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit,unit,this);//利用循环,来绘制蛇的形状           
        }
   }  
                  
    //设置按钮的监听器事件
	@Override
	public void actionPerformed(ActionEvent e) {
    
    
		// TODO 自动生成的方法存根
		//按开始键
		if(e.getSource() == startButton) {
    
    
			new  pushButtonMusic ();
            startFlag = true;
            startButton.setEnabled(false);
            stopButton.setEnabled(true); 
            
        }//按暂停键
        if(e.getSource() == stopButton) {
    
    
        	new  pushButtonMusic ();
            startFlag = false;
            startButton.setEnabled(true);
            stopButton.setEnabled(false);             
     }
          //        退出程序
        if(e.getSource() == quitButton) {
    
    
        	 
            System.exit(0);
        }//按游戏指南建
        if(e.getSource() ==  ShowButton) {
    
    
        	new  pushButtonMusic ();
        	 JDialog frame = new JDialog();//构造一个新的JFrame,作为新窗口。
             frame.setBounds( 600,300,815,515 );             
             JTextArea  Myarea=new  JTextArea(3,10);
				Myarea.setText("嗨,你好,欢迎体验贪吃蛇小游戏!\n "
                     +"这个小游戏点击开始按钮后贪吃蛇开始移动,你身体的前后左右移动\n"+"会使贪吃蛇也前后左右移动。\n"
                     + "你的任务是通过控制蛇的移动来吃掉小草莓,这样贪吃蛇就长大了。\n"
                     +"点击暂停游戏按钮可以使得贪吃蛇停止移动,"
                     +"点击退出游戏按钮自然游\n"+"戏就结束啦!\n"
                     + "点击速度一,速度二等按钮就可以控制贪吃蛇的移动速度,以提高\n"+"康复效率!\n"
                     +"此游戏素材部分来源于网络,如果有侵犯到您的利益 \n"+"请立刻联系我们,任何单位或个人不准用于商业用途。");			 
		     frame.setLayout(null);              
              Myarea.setBounds( 10,10,815,350);             			 
             Myarea.setFont(new Font("华文行楷",Font.BOLD,25));          
             frame.add(Myarea);           
             frame.setModalityType(JDialog.ModalityType.APPLICATION_MODAL);    // 设置模式类型。
             frame.setVisible(true);              
     }//按速度一键
        if(e.getSource() == FspeedButton) {
    
    
        	new speedButtonMusic ();
        	  Difficult_Degree= 2;                      	
     }//按速度二键
        if(e.getSource() == SspeedButton) {
    
    
        	new speedButtonMusic ();
             
        	 Difficult_Degree=  3;        	
     }//按速度三键
        if(e.getSource() == TspeedButton) {
    
    
        	new speedButtonMusic ();
        	 Difficult_Degree= 4;        	        	
     }//按速度四键
        if(e.getSource() == THspeedButton) {
    
    
        	new  speedButtonMusic ();
        	 Difficult_Degree= 5;      	
     }
        this.requestFocus();
    }
 	 
}

Restart.java类

package snakeGame;
/*
 * ReStart类的功能和start相类似,设计程序运行后的界面,包括程序重启界面和游戏运行界面。运行界面和start类运行的一样,
 * 重启界面包括包括两个按钮和一个背景图片,点击重启游戏按钮游戏进入运行界面,点击退出按钮后结束游戏。
 */

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

class Restart   extends  JFrame   implements ActionListener{
    
    
	public  static  void main(String [] args) {
    
    
		new  Restart();	
	   }
	   JFrame frame2=new JFrame(); 
	   JButton reStartButton=new  JButton("重新开始");
	   JButton  closeButton =new JButton("结束游戏");
	
	   
	//定义界面按钮等内容。		   
	public  Restart() {
    
    
    	frame2.setUndecorated(true);  //用于取消边框背景	
		frame2.setSize(800,480);
		frame2.setLocation(600,300);
		//frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame2.setVisible(true);
		frame2.setLayout(null);	
		
		//设置按钮颜色
		
		Color  color2=new  Color(124,252,0);
		reStartButton.setBackground(color2);				
		Color color1 = new Color(124,252,0 );
		closeButton.setBackground(color1 );
		//设置按钮大小和位置			 
		reStartButton.setBounds(140, 364, 120, 110);
		closeButton.setBounds(280,270,120,110);
		//设置按钮颜色和字体
		reStartButton.setFont(new Font("华文行楷", Font.BOLD, 20));
		closeButton.setFont(new Font("华文行楷", Font.BOLD, 20));
		//在容器中加入按钮
		frame2.add(reStartButton);
		frame2.add(closeButton);
	    addPicture();
	    reStartButton.addActionListener(this);
	    closeButton.addActionListener(this);
        }
	
	   //设置背景图片
		 public  void  addPicture() {
    
          //游戏结束时弹出的界面的背景
				ImageIcon deadPicture = new ImageIcon("src/image/restartPicture.jpg");
		    JLabel  pictureLabel  =new  JLabel(deadPicture);
			pictureLabel.setBounds(0, 0,deadPicture.getIconWidth(), deadPicture.getIconHeight());
			frame2.getLayeredPane().add(pictureLabel,new Integer(Integer.MIN_VALUE));
			JPanel  jp1=(JPanel)frame2.getContentPane();
			jp1.setOpaque(false);
		}
	 //按钮加入监听器事件
		@Override
		public void actionPerformed(ActionEvent e) {
    
    
			// TODO 自动生成的方法存根
			if(e.getSource()==reStartButton) {
    
    
				 closeThis();
	             new  Frame3();	            	
	  	            }				 			
			if(e.getSource()==closeButton) {
    
    
				System.exit(0);
 	        }		
	     }
		private void closeThis() {
    
    
			// TODO 自动生成的方法存根
			frame2.dispose();
	}
	
	//	游戏运行界面,实例化SnakeGame类,并加入到运行界面中			
   class  Frame3 extends JFrame      {
    
      	  
	    JFrame  frame1 = new JFrame(); //游戏图形界面            
	  public   Frame3(){
    
     
		   frame1.setUndecorated(true);  //用于取消边框背景
		   frame1.setBounds(200,70,1600,900);		           		 
		 /// frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		   frame1.setVisible(true);			  
	        SnakeGame   sn  =new  SnakeGame();    
	        frame1.add(sn);
	        sn.requestFocus();//布局的中间		  								 
	   }			 
    }
}

RButton.java类

package snakeGame;
/*在Java  swing中的button无法设置圆角按钮,为了一定程度上完善游戏界面,故而设置了圆角按钮。
 * 定义圆角按钮;
 */
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;

public class RButton extends JButton {
    
    
    private static final long serialVersionUID = 39082560987930759L;
    public static final Color BUTTON_COLOR1 = new Color(205, 255, 205);     //设置按钮的第一种颜色
    public static final Color BUTTON_COLOR2 = new Color(51, 55, 47);        //设置按钮的第二种颜色
    // public static final Color BUTTON_COLOR1 = new Color(125, 161, 237);
    // public static final Color BUTTON_COLOR2 = new Color(91, 118, 173);
    public static final Color BUTTON_FOREGROUND_COLOR = Color.WHITE;
    private boolean hover;

    public RButton(String name) {
    
    
        this.setText(name);   //添加名字
        setFont(new Font("system", Font.PLAIN, 12)); //设置字体
        setBorderPainted(false);               //设置边界可见否
          setForeground(BUTTON_COLOR2);           //设置前景色
         setFocusPainted(false);                   
          setContentAreaFilled(false);  
          //定义鼠标事件,即当鼠标进入到按钮界面时,按钮颜色会发生变化,鼠标离开按钮区域时也会发生变化
        addMouseListener(new MouseAdapter() {
    
    
            @Override
            public void mouseEntered(MouseEvent e) {
    
    
                setForeground(BUTTON_FOREGROUND_COLOR);
                hover = true;
                repaint();
            }

            @Override
            public void mouseExited(MouseEvent e) {
    
    
                setForeground(BUTTON_COLOR2);
                hover = false;
                repaint();
            }
        });
    }
   //设置按钮圆角
    @Override
    protected void paintComponent(Graphics g) {
    
    
        Graphics2D g2d = (Graphics2D) g.create();
        int h = getHeight();
        int w = getWidth();
        float tran = 1F;
        if (!hover) {
    
    
            tran = 0.3F;
        }

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        GradientPaint p1;
        GradientPaint p2;
        //当点击按钮之后,按钮颜色和字体会发生变化
        if (getModel().isPressed()) {
    
    
            p1 = new GradientPaint(0, 0, new Color(0, 0, 0), 0, h - 1,
                    new Color(100, 100, 100));
            p2 = new GradientPaint(0, 1, new Color(0, 0, 0, 50), 0, h - 3,
                    new Color(255, 255, 255, 100));
        } else {
    
    
            p1 = new GradientPaint(0, 0, new Color(100, 100, 100), 0, h - 1,
                    new Color(0, 0, 0));
            p2 = new GradientPaint(0, 1, new Color(255, 255, 255, 100), 0,
                    h - 3, new Color(0, 0, 0, 50));
        }
        
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                tran));
        RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0, w - 1,
                h - 1, 20, 20);
        Shape clip = g2d.getClip();
        g2d.clip(r2d);
        GradientPaint gp = new GradientPaint(0.0F, 0.0F, BUTTON_COLOR1, 0.0F,
                h, BUTTON_COLOR2, true);
     
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, w, h);
        g2d.setClip(clip);
        g2d.setPaint(p1);
        g2d.drawRoundRect(0, 0, w - 1, h - 1, 20, 20);
        g2d.setPaint(p2);
        g2d.drawRoundRect(1, 1, w - 3, h - 3, 18, 18);
        g2d.dispose();
        super.paintComponent(g);
    }
}

applauseMusic.java类

package snakeGame;
/*
 * 设置程序运行背景音乐,包括 点击按钮音乐,鼓励音,撞墙音乐,吃食物音乐等等,
 * 音乐类的设置可以在snakeGame类中实现,由于音乐太多,故而集中到一起,可以在需要添加的地方实例化即可。
 */
import java.applet.AudioClip;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.JApplet;
//添加鼓励音 
class   applauseMusic      
        {
    
             
			AudioClip christmas = loadSound("src/music/applauseMusic.wav");
            public applauseMusic  ()
               {
    
                 
                  christmas.play ();
                }
         public AudioClip loadSound ( String filename )
             {
    
    
            URL url = null;
           try
             {
    
    
             url = new URL ("file:" + filename);
               }
              catch (MalformedURLException e)
              {
    
    }
            return JApplet.newAudioClip (url);
             }
           }
//添加吃到食物的音乐
class eatFoodMusic       
        {
    
             
			AudioClip christmas = loadSound("src/music/eatFoodMusic.wav");
            public eatFoodMusic  ()
               {
    
                 
                  christmas.play ();
                }
         public AudioClip loadSound ( String filename )
             {
    
    
            URL url = null;
                try
             {
    
    
             url = new URL ("file:" + filename);
               }
              catch (MalformedURLException e)
              {
    
    }
            return JApplet.newAudioClip (url);
             }
           }

//添加撞墙音乐
class DeadMusic        
    {
    
             
		AudioClip christmas = loadSound("src/music/DeadMusic.wav");
        public  DeadMusic   ()
          {
    
                 
          christmas.play ();
            }
 public AudioClip loadSound ( String filename )
          {
    
    
            URL url = null;
           try
         {
    
    
          url = new URL ("file:" + filename);
       }
      catch (MalformedURLException e)
      {
    
    }
    return JApplet.newAudioClip (url);
     }
   }

//添加 按键音乐
class  pushButtonMusic       
     {
    
             
			AudioClip christmas = loadSound("src/music/pushButtonMusic.wav");
        public pushButtonMusic  ()
           {
    
                 
              christmas.play ();
           }
      public AudioClip loadSound ( String filename )
          {
    
    
            URL url = null;
            try
          {
    
    
            url = new URL ("file:" + filename);
           }
          catch (MalformedURLException e)
             {
    
    }
         return JApplet.newAudioClip (url);
          }
        }
// 添加速度控制音乐
class    speedButtonMusic{
    
             
	AudioClip christmas = loadSound("src/music/encouragMusic.wav");
       public speedButtonMusic()
         {
    
                 
          christmas.play ();
        }
      public AudioClip loadSound ( String filename )
         {
    
    
           URL url = null;
           try
         {
    
    
        url = new URL ("file:" + filename);
          }
        catch (MalformedURLException e)
        {
    
    }
      return JApplet.newAudioClip (url);
       }
     }

总结

游戏有声音,就是音频有点吓人,其他都还好,如果不喜欢,可以换成自己喜欢的音频。
附上百度云盘下载连接地址:
链接:https://pan.baidu.com/s/1P9bwYgXkoRVaKdOOuWvUng
提取码:fcfj
欢迎交流,共同进步。

猜你喜欢

转载自blog.csdn.net/weixin_45345143/article/details/128361734