精华内容
下载资源
问答
  • JAVA手机游戏编程源代码

    千次下载 2008-02-13 21:51:10
    几个JAVA手机游戏编程源代码
  • 7个Java小游戏源代码

    千次下载 热门讨论 2007-11-10 17:34:03
    7个Java小游戏源代码 解压密码是:yykings
  • JAVA贪吃蛇小游戏源代码系列

    万次阅读 多人点赞 2018-12-15 11:00:15
    Java贪吃蛇小游戏之启动界面 package snakeGame; /* * ReStart类的功能和start相类似,设计程序运行后的界面,包括程序重启界面和游戏运行界面。运行界面和start类运行的一样, * 重启界面包括包括两个按钮和...

    源代码加图片加背景音乐
    链接:https://pan.baidu.com/s/1Ll_vVsBC-lYNpLrSRAz5ew
    提取码:h2ds
    复制这段内容后打开百度网盘手机App,操作更方便哦

    源代码链接:https://pan.baidu.com/s/1_15FmYYbl1nhydKbkCyfRQ
    提取码:kl56
    复制这段内容后打开百度网盘手机App,操作更方便哦

    贪吃蛇小游戏运行结果如下:
    启动界面:
    在这里插入图片描述
    运行界面:
    在这里插入图片描述
    重启界面:
    在这里插入图片描述
    源代码框架如下:
    在这里插入图片描述
    注:在运行程序的时候,得重新设计窗体的大小,以适合自己的电脑,其次,图片类和音乐类都保存在我自己电脑的F盘的相应路径下,在运行程序的时候需要将图片类和音乐类保存到自己的本地磁盘路径中,然后在程序中改变路径。

    Java贪吃蛇小游戏之启动界面

    package snakeGame;
    
    /* Test类的主要任务是设计程序运行后的界面,包括 程序启动的界面和游戏运行界面。
     * 程序启动的界面包括背景图片和进入运行界面的Button,点击按钮之后程序关闭启动界面进入到运行界面,
     * 运行界面设置在SnakeGame类中,Test类大体设置了运行界面的大小可见与否等。
     */
    
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.Frame;
    import java.awt.Label;
    import java.awt.Panel;
    import java.awt.TextField;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    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) {	
        	 new  Start();                                         
        }
    	public  Start(){                                                 //设置启动界面
    		 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("F:\\MYJAVA\\Myprogram\\Snakeexample\\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();//布局的中间	         	         
    			}			 
          }	 
    }
    

    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.Rectangle;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;
    import java.io.File;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.sql.Time;
    import java.util.Date;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Scanner;
    import java.util.TimerTask;
    
    import javax.swing.JApplet;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    import javax.swing.Timer;
    
    import java.applet.AudioClip;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.swing.JApplet;
    
    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 ("F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\Music\\backgroundMusic.wav");
          int direction = 1;//定义一个按下按钮后要去的方向                 
          private ArrayList<SnakeNode> snake = new ArrayList<>();//定义蛇身的数组集合
          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("F:\\MYJAVA\\Myprogram\\Snakeexample\\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( "F:\\MYJAVA\\Myprogram\\Snakeexample\\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( "F:\\MYJAVA\\Myprogram\\Snakeexample\\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( "F:\\MYJAVA\\Myprogram\\Snakeexample\\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( "F:\\MYJAVA\\Myprogram\\Snakeexample\\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( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\food.png");
            g.drawImage(food,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);       
            
            Toolkit tool2 = this.getToolkit();
            Image food1=  tool2.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\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( "F:\\MYJAVA\\Myprogram\\Snakeexample\\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" 
                         );			 
    		     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();
        }
     	 
    }
    
     
    

    Java贪吃蛇小游戏之重启界面:

    package snakeGame;
    /*
     * ReStart类的功能和start相类似,设计程序运行后的界面,包括程序重启界面和游戏运行界面。运行界面和start类运行的一样,
     * 重启界面包括包括两个按钮和一个背景图片,点击重启游戏按钮游戏进入运行界面,点击退出按钮后结束游戏。
     */
    
    import java.awt.Color;
    import java.awt.Component;
    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.JDialog;
    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("F:\\MYJAVA\\Myprogram\\Snakeexample\\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();//布局的中间		  								 
    	   }			 
        }
    }
    

    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;
        }
    }
    
    展开全文
  • JAVA小游戏之扫雷的源代码

    万次阅读 多人点赞 2017-05-29 17:10:03
    老师讲的扫雷小游戏,因为基础还不扎实,所以还写不出扫雷游戏,大家可以看看尝试去写写。 ———————————————————————————————————— //测试类 package com.titan.test; import ...

    老师讲的扫雷小游戏,因为基础还不扎实,所以还写不出扫雷游戏,大家可以看看尝试去写写。

    ————————————————————————————————————
    //测试类
    package com.titan.test;
    
    import java.util.Scanner;
    
    import com.titan.core.Game;
    
    public class Test1 {
    	public static void main(String[] args) {
    		 //获得游戏核心类的对象
    		 Game g=new Game();
    		 //调用添加格子对象的方法3
    		 g.addGrid();
    		 //布雷方法调用
    		 g.setMine();
    		 //添加雷数的调用
    		 g.setNumber();
    		 
    		 Scanner s=new Scanner(System.in);
    		 g.paint();
    		 while(true){
    			 System.out.println("请输入X坐标");
    			 int x=s.nextInt();
    			 System.out.println("请输入Y坐标");
    			 int y=s.nextInt();
    			 g.stamp(x, y);
    			 //调用绘制界面的方法
    			 g.paint();
    		 }		 
    	}
    }
    ————————————————————————————————————
    //游戏核心类
    package com.titan.core;
    
    import java.awt.Point;
    import java.util.Random;
    
    import com.titan.bean.Grid;
    
    /**
     * 游戏核心类
     * @author Administrator
     * 雷区(游戏界面)
     */
    public class Game {
    	
    	//定义一个存放格子对象的二维数组
    	Grid[][] grid=new Grid[9][9];
    	
    	//定义一个存放雷数的属性
    	int count=10;
    	//定义一个随机数工具的属性
    	Random r=new Random();
    	
    	//添加格子对象到二维数组中
    	public void addGrid(){
    		//通过循环的方式来为二维数组中添加格子对象
    		for(int i=0;i<grid.length;i++){
    			for(int j=0;j<grid[i].length;j++){
    				//将二维数组中的每个格子上赋值格子对象
    				grid[i][j]=new Grid();
    				//设置内容
    				grid[i][j].setContent(' ');
    				//设置状态
    				grid[i][j].setState(false);
    				//设置坐标
    				grid[i][j].setPoint(new Point(i,j));
    			}
    		}
    	}
    	
    	
    	//创建一个绘制游戏界面的方法
    	public void paint(){
    		for(int i=0;i<grid.length;i++){
    			for(int j=0;j<grid[i].length;j++){
    				if(grid[i][j].isState()){
    					System.out.print(grid[i][j].getContent()+" ");
    				}else{
    					System.out.print("■ ");
    				}
    			}
    			System.out.println();
    		}
    	}
    	
    	//添加一个布雷的方法
    	public void setMine(){
    		int i=0;
    		//通过循环的方式来获得10个格子对象
    		do{
    			//获得一个随机的行坐标
    			int x=r.nextInt(9); 
    			//获得一个随机的列坐标
    			int y=r.nextInt(9);
    			//判断当前随机位置的格子内容是否是雷,如果不是就布雷
    			if(grid[x][y].getContent()!='*'){
    				//获得当前坐标位置的格子对象
    				grid[x][y].setContent('*');
    				i++;
    			}
    		}while(i<count);
    	}
    	
    	
    	//获得当前坐标位置的8个方向坐标对象
    	public Point[] getPoint(int x,int y){
    		//创建一个坐标数组
    		Point[] point=new Point[8];
    		//为左边的位置赋值坐标
    		point[0]=new Point(x-1,y);
    		//为左上的位置赋值坐标
    		point[1]=new Point(x-1,y-1);
    		//为上面的位置赋值坐标
    		point[2]=new Point(x,y-1);
    		//为右上的位置赋值坐标
    		point[3]=new Point(x+1,y-1);
    		//为右边的位置赋值坐标
    		point[4]=new Point(x+1,y);
    		//为右下的位置赋值坐标
    		point[5]=new Point(x+1,y+1);
    		//为下面的位置赋值坐标
    		point[6]=new Point(x,y+1);
    		//为左下的位置赋值坐标
    		point[7]=new Point(x-1,y+1);
    		return point;
    	}
    	
    	
    	//雷数字添加
    	public void setNumber(){
    		//遍历所有的格子对象
    		for(int i=0;i<grid.length;i++){
    			for(int j=0;j<grid[i].length;j++){
    				
    				//定义统计当前位置方向中雷数的计数器
    				int sum=0;
    				
    				//判断是否当前位置是雷,如果是雷就进入下一个坐标
    				if(grid[i][j].getContent()=='*'){
    					//结束当前的循环,进入下一次循环
    					continue;
    				}else{
    					
    					//进入当前位置的8个方向的扫描
    					Point[] point=getPoint(i, j);
    					//通过循环遍历来获得当前坐标的方向对象
    					for(int k=0;k<point.length;k++){
    						//定义一个坐标对象来获得当前循环到的坐标
    						Point p=point[k];
    						if(p.x>=0 && p.y>=0 && p.x<9 && p.y<9){
    							//判断当前有效范围内的格子是否是雷
    							if(grid[p.x][p.y].getContent()=='*'){
    								sum++;
    							}
    						}
    					}
    				}
    				
    				//判断雷数的计数器是否发生改变,如果改变就将值填充到
    				//当前坐标的格子当中
    				if(sum>0){
    					grid[i][j].setContent((char)(48+sum));
    				}
    			}
    		}
    	}
    	
    	
    	//踩雷
    	public void stamp(int x,int y){
    		//判断当前位置是否存在雷
    		if(grid[x][y].getContent()=='*'){
    			System.out.println("游戏结束");
    		}else{
    			//将当前的格子内容状态改成已打开
    			grid[x][y].setState(true);
    			//判断当前的格子内容必须是空格的时候才执行辐射
    			if(grid[x][y].getContent()==' '){
    				//获得当前格子的8个方向坐标对象
    				Point[] point=getPoint(x,y);
    				//循环遍历获得每个方向的对象
    				for(int k=0;k<point.length;k++){
    					Point p=point[k];
    					//判断当前坐标对象是否越界
    					if(p.x>=0 && p.y>=0 && p.x<9 && p.y<9){
    						//判断当前方向的格子内容是否为空格,如果为空格
    						//就执行辐射操作  --递归调用
    						if(grid[p.x][p.y].getContent()==' ' 
    									&& grid[p.x][p.y].isState()==false){
    							stamp(p.x,p.y);
    						}else if(grid[p.x][p.y].getContent()!=' '){
    							//如果当前位置为数字就将数字显示出来
    							grid[p.x][p.y].setState(true);
    						}
    					}
    				}
    			}
    		}
    	}
    }
    ————————————————————————————————————
    //格子类
    package com.titan.bean;
    
    import java.awt.Point;
    
    /**
     * 格子类
     * @author Administrator
     * 格子的内容、格子的状态、格子的坐标
     */
    public class Grid {
    	//格子内容
    	char content;
    	//格子状态
    	boolean state;
    	//格子的坐标
    	Point point;
    	public char getContent() {
    		return content;
    	}
    	public void setContent(char content) {
    		this.content = content;
    	}
    	public boolean isState() {
    		return state;
    	}
    	public void setState(boolean state) {
    		this.state = state;
    	}
    	public Point getPoint() {
    		return point;
    	}
    	public void setPoint(Point point) {
    		this.point = point;
    	} 
    }
    
    
    
    


    展开全文
  • 经典的java小程序源代码合集

    千次下载 热门讨论 2011-12-21 08:43:48
    164个完美程序,五子棋,俄罗斯方块,扫雷,聊天程序
  • Java编程五子棋小游戏(全代码

    万次阅读 多人点赞 2019-08-07 16:47:25
    这是这三天自己跟着学习完成的简单五子棋小游戏的全部代码,通过这个小游戏,我学到了很多,包括程序的设计以及怎么将自己想实现的功能转化成代码,用代码编写出来,对我的Java学习之路又有一个新的提升。...

    这是这三天自己跟着学习完成的简单五子棋小游戏的全部代码,通过这个小游戏,我学到了很多,包括程序的设计以及怎么将自己想实现的功能转化成代码,用代码编写出来,对我的Java学习之路又有一个新的提升。
    需要注意的是里面有很多数字是要根据自己的实际情况来设置的,比如主窗体的大小等等,详情请看前两篇博客

    Test类测试代码:包含主方法

    package org.liky.game.test;
    import org.liky.game.frame.FiveChessFrame;
    public class Test {
    	public static void main(String[] args) {
    		FiveChessFrame ff = new FiveChessFrame();	
    	}
    }
    

    FiveChessFrame功能实现代码:包括了整个五子棋小游戏的所有功能

    package org.liky.game.frame;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Toolkit;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    
    public class FiveChessFrame extends JFrame implements MouseListener, Runnable {
    	// 取得屏幕大小,屏幕的高度和宽度
    	int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    	int height = Toolkit.getDefaultToolkit().getScreenSize().height;
    	// 背景图片
    	BufferedImage bgImage = null;
    	// 用来保存棋子的坐标
    	int x = 0;
    	int y = 0;
    	// 保存之前下过的全部棋子的坐标
    	// 0:表示这个点并没有棋子 1:表示这个点是黑子 2:表示这个点是白子
    	int[][] allChess = new int[19][19];
    	// 标识当前应该是黑棋还是白棋下下一步
    	boolean isBlack = true;
    	// 标识当前游戏是否可以继续
    	boolean canPlay = true;
    	// 保存显示的提示信息
    	String message = "黑方先行";
    	// 保存最多拥有多少时间(秒)
    	int maxTime = 0;
    	// 做倒计时的线程类
    	Thread t = new Thread(this);
    	// 保存黑方与白方的剩余时间
    	int blackTime = 0;
    	int whiteTime = 0;
    	// 保存双方剩余时间的显示信息
    	String blackMessage = "无限制";
    	String whiteMessage = "无限制";
    
    	public FiveChessFrame() {
    		// 设置标题
    		this.setTitle("五子棋");
    		// 设置窗体大小
    		this.setSize(500, 530);
    		// 设置窗体出现位置
    		this.setLocation((width - 500) / 2, (height - 500) / 2);
    		// 将窗体设置为大小不可变
    		this.setResizable(false);
    		// 将窗体的关闭方式设置为默认关闭后程序结束
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		// 为窗体加入监听器
    		this.addMouseListener(this);
    		// 将窗体显示出来
    		this.setVisible(true);
    
    		t.start();
    		t.suspend();
    
    		// 将背景图片显示到窗体中
    		try {
    			bgImage = ImageIO.read(new File("e:/Image/Five.jpg"));
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	public void paint(Graphics g) {
    		// 双缓冲技术防止屏幕闪烁
    		BufferedImage bi = new BufferedImage(500, 530, BufferedImage.TYPE_INT_ARGB);
    		Graphics g2 = bi.createGraphics();
    		g2.setColor(Color.BLACK);
    		// 绘制背景
    		g2.drawImage(bgImage, 0, 30, this);
    		// 输出标题信息
    		g2.setFont(new Font("黑体", Font.BOLD, 14));
    		g2.drawString("游戏信息:" + message, 10, 50);
    		// 输出时间信息
    		g2.setFont(new Font("宋体", 0, 17));
    		g2.drawString("黑方时间:" + blackMessage, 60, 490);
    		g2.drawString("白方时间:" + whiteMessage, 290, 490);
    		// 绘制棋盘
    		for (int i = 0; i < 19; i++) {
    			g2.drawLine(21, 84 + 20 * i, 377, 84 + 20 * i);
    			g2.drawLine(20 + 20 * i, 85, 20 + 20 * i, 441);
    		}
    		// 标注点位
    		g2.fillOval(78, 140, 6, 6);
    		g2.fillOval(317, 140, 6, 6);
    		g2.fillOval(317, 380, 6, 6);
    		g2.fillOval(78, 380, 6, 6);
    		g2.fillOval(198, 261, 6, 6);
    
    		// 绘制全部棋子
    		for (int i = 0; i < 19; i++) {
    			for (int j = 0; j < 19; j++) {
    				if (allChess[i][j] == 1) {
    					// 黑子
    					int tempX = i * 20 + 21;
    					int tempY = j * 20 + 84;
    					g2.fillOval(tempX - 7, tempY - 7, 14, 14);
    
    				}
    				if (allChess[i][j] == 2) {
    					// 白子
    					int tempX = i * 20 + 21;
    					int tempY = j * 20 + 84;
    					g2.setColor(Color.WHITE);
    					g2.fillOval(tempX - 7, tempY - 7, 14, 14);
    					g2.setColor(Color.BLACK);
    					g2.drawOval(tempX - 7, tempY - 7, 14, 14);
    				}
    			}
    		}
    		g.drawImage(bi, 0, 0, this);
    	}
    
    	public void mouseClicked(MouseEvent e) {}
    	public void mousePressed(MouseEvent e) {
    		// 利用点击监听操作得到各个点的坐标
    		if (canPlay == true) {
    			x = e.getX();
    			y = e.getY();
    			if (x >= 20 && x <= 377 && y >= 84 && y <= 441) {
    				x = (x - 20) / 20;
    				y = (y - 84) / 20;
    				if (allChess[x][y] == 0) {
    					// 判断当前要下的是什么演的的棋子
    					if (isBlack == true) {
    						allChess[x][y] = 1;
    						isBlack = false;
    						message = "轮到白方";
    					} else {
    						allChess[x][y] = 2;
    						isBlack = true;
    						message = "轮到黑方";
    					}
    					// 判断这个棋子是否和其他的棋子连成5连,即判断游戏是否结束
    					boolean winFlag = this.checkWin();
    					if (winFlag == true) {
    						JOptionPane.showMessageDialog(this, "游戏结束," + (allChess[x][y] == 1 ? "黑方" : "白方") + "获胜!");
    						canPlay = false;
    					}
    				} else {
    					JOptionPane.showMessageDialog(this, "当前位置已经有棋子,请重新落子!");
    				}
    				this.repaint();
    			}
    		}
    		// 点击开始游戏按钮
    		if (e.getX() >= 400 && e.getX() <= 480 && e.getY() >= 87 && e.getY() <= 122) {
    			int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏?");
    			if (result == 0) {
    				// 现在重新开始游戏
    				// 重新开始所要做的操作:
    				// 1、把棋盘清空,将allChess这个数组中的全部数据归0;
    				// 2、将游戏信息:的显示改回到开始位置
    				// 3、将下一步下棋的人改为黑方
    				for (int i = 0; i < 19; i++) {
    					for (int j = 0; j < 19; j++) {
    						allChess[i][j] = 0;
    					}
    				}
    				message = "黑方先行";
    				isBlack = true;
    				blackTime = maxTime;
    				whiteTime = maxTime;
    				if (maxTime > 0) {
    					blackMessage = maxTime / 3600 + ":" + (maxTime / 60 - maxTime / 3600 * 60) + ":"
    							+ (maxTime - maxTime / 60 * 60);
    					whiteMessage = maxTime / 3600 + ":" + (maxTime / 60 - maxTime / 3600 * 60) + ":"
    							+ (maxTime - maxTime / 60 * 60);
    					t.resume();
    				} else {
    					blackMessage = "无限制";
    					whiteMessage = "无限制";
    				}
    				this.canPlay = true;
    				this.repaint();
    			}
    		}
    		// 点击游戏设置按钮
    		if (e.getX() >= 400 && e.getX() <= 480 && e.getY() >= 150 && e.getY() <= 180) {
    			String input = JOptionPane.showInputDialog("请输入游戏的最大时间(单位:分钟),如果输入0表示没有时间限制");
    			try {
    				maxTime = Integer.parseInt(input) * 60;
    				if (maxTime < 0) {
    					JOptionPane.showMessageDialog(this, "请输入正确信息,不允许输入负数");
    				}
    				if (maxTime == 0) {
    					int result = JOptionPane.showConfirmDialog(this, "设置完成,是否重新开始游戏?");
    					if (result == 0) {
    						for (int i = 0; i < 19; i++) {
    							for (int j = 0; j < 19; j++) {
    								allChess[i][j] = 0;
    							}
    						}
    						message = "黑方先行";
    						isBlack = true;
    						blackTime = maxTime;
    						whiteTime = maxTime;
    						blackMessage = "无限制";
    						whiteMessage = "无限制";
    						this.canPlay = true;
    						this.repaint();
    					}
    				}
    				if (maxTime > 0) {
    					int result = JOptionPane.showConfirmDialog(this, "设置完成,是否重新开始游戏?");
    					if (result == 0) {
    						for (int i = 0; i < 19; i++) {
    							for (int j = 0; j < 19; j++) {
    								allChess[i][j] = 0;
    							}
    						}
    						message = "黑方先行";
    						isBlack = true;
    						blackTime = maxTime;
    						whiteTime = maxTime;
    						blackMessage = maxTime / 3600 + ":" + (maxTime / 60 - maxTime / 3600 * 60) + ":"
    								+ (maxTime - maxTime / 60 * 60);
    						whiteMessage = maxTime / 3600 + ":" + (maxTime / 60 - maxTime / 3600 * 60) + ":"
    								+ (maxTime - maxTime / 60 * 60);
    						t.resume();
    						this.canPlay = true;
    						this.repaint();
    					}
    				}
    			} catch (NumberFormatException e1) {
    				JOptionPane.showMessageDialog(this, "请输入大于等于零的数字");
    				e1.printStackTrace();
    			}
    		}
    		// 点击游戏说明按钮
    		if (e.getX() >= 400 && e.getX() <= 480 && e.getY() >= 210 && e.getY() <= 245) {
    			JOptionPane.showMessageDialog(this, "这是一个五子棋游戏程序,黑白双方轮流下棋,当某一方连到五子时游戏结束。");
    		}
    		// 点击认输按钮
    		if (e.getX() >= 400 && e.getX() <= 480 && e.getY() >= 280 && e.getY() <= 310) {
    			int result = JOptionPane.showConfirmDialog(this, "是否确认认输");
    			if (result == 0) {
    				if (isBlack) {
    					JOptionPane.showMessageDialog(this, "黑方已经认输,游戏结束");
    				} else {
    					JOptionPane.showMessageDialog(this, "白方已经认输,游戏结束");
    				}
    				canPlay = false;
    			}
    		}
    		// 点击关于按钮
    		if (e.getX() >= 400 && e.getX() <= 480 && e.getY() >= 340 && e.getY() <= 370) {
    			JOptionPane.showMessageDialog(this, "本游戏由邢洪浩制作,有相关问题可以加微信:xhh19980926");
    		}
    		// 点击退出按钮
    		if (e.getX() >= 400 && e.getX() <= 480 && e.getY() >= 400 && e.getY() <= 427) {
    			JOptionPane.showMessageDialog(this, "游戏结束");
    			System.exit(0);
    		}
    		x = (x - 20) / 20;
    		y = (y - 84) / 20;
    	}
    
    	public void mouseReleased(MouseEvent e) {}
    
    	public void mouseEntered(MouseEvent e) {}
    
    	public void mouseExited(MouseEvent e) {}
    
    	public boolean checkWin() {
    		boolean flag = false;
    		// 保存共有相同颜色多少棋子相连
    		int count = 1;
    		// 判断横向的是否有5个棋子相连,特点 纵坐标是相同的,即allChess[x][y]中y值是相同的
    		int color = allChess[x][y];
    		// 判断横向
    		count = this.checkCount(1, 0, color);
    		if (count >= 5) {
    			flag = true;
    		} else {
    			// 判断纵向
    			count = this.checkCount(0, 1, color);
    			if (count >= 5) {
    				flag = true;
    			} else {
    				// 判断右上、左下
    				count = this.checkCount(1, -1, color);
    				if (count >= 5) {
    					flag = true;
    				} else {
    					// 判断右下、左上
    					count = this.checkCount(1, 1, color);
    					if (count >= 5) {
    						flag = true;
    					}
    				}
    			}
    		}
    		return flag;
    	}
    
    	// 判断棋子连接的数量
    	private int checkCount(int xChange, int yChange, int color) {
    		int count = 1;
    		int tempX = xChange;
    		int tempY = yChange;
    		while (x + xChange >= 0 && x + xChange <= 18 && y + yChange >= 0 && y + yChange <= 18
    				&& color == allChess[x + xChange][y + yChange]) {
    			count++;
    			if (xChange != 0)
    				xChange++;
    			if (yChange != 0) {
    				if (yChange > 0)
    					yChange++;
    				else {
    					yChange--;
    				}
    			}
    		}
    		xChange = tempX;
    		yChange = tempY;
    		while (x - xChange >= 0 && x - xChange <= 18 && y - yChange >= 0 && y - yChange <= 18
    				&& color == allChess[x - xChange][y - yChange]) {
    			count++;
    			if (xChange != 0)
    				xChange++;
    			if (yChange != 0) {
    				if (yChange > 0)
    					yChange++;
    				else {
    					yChange--;
    				}
    			}
    		}
    		return count;
    	}
    
    	public void run() {
    		// 判断是否有时间限制
    		if (maxTime > 0) {
    			while (true) {
    				if (isBlack) {
    					blackTime--;
    					if (blackTime == 0) {
    						JOptionPane.showMessageDialog(this, "黑方超时,游戏结束!");
    					}
    				} else {
    					whiteTime--;
    					if (whiteTime == 0) {
    						JOptionPane.showMessageDialog(this, "白方超时,游戏结束!");
    					}
    				}
    				blackMessage = blackTime / 3600 + ":" + (blackTime / 60 - blackTime / 3600 * 60) + ":"
    						+ (blackTime - blackTime / 60 * 60);
    				whiteMessage = whiteTime / 3600 + ":" + (whiteTime / 60 - whiteTime / 3600 * 60) + ":"
    						+ (whiteTime - whiteTime / 60 * 60);
    				this.repaint();
    				try {
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				System.out.println(blackTime + " -- " + whiteTime);
    			}
    		}
    	}
    }
    
    
    展开全文
  • 2048小游戏Java)源码解析及源代码打包

    万次阅读 多人点赞 2015-05-18 23:01:27
    数据结构课程设计写的2048小游戏,答辩完了就开源了,因为这次的技术文档任性地写成了傻瓜式教程了,就干脆也放出来了,供参考,源代码打包在最后面会附上。 一 实现方案 二 具体代码及程序框图分析 三 参考资料一、...

    数据结构课程设计写的2048小游戏,答辩完了就开源了,因为这次的技术文档任性地写成了傻瓜式教程了,就干脆也放出来了,供参考,源代码打包在最后面会附上。

    一、 实现方案

    本游戏采用Java语言编写,使用Eclipse编译器, jdk1.7.0_51编译环境。
    游戏的UI主要运用Java图形界面编程(AWT),实现窗口化可视化的界面。
    游戏的后台通过监听键盘方向键来移动数字方块,运用随机数的思想随机产生一个2或4的随机数,显示在随机方块中,运用二维数组存储、遍历查找等思想,在每次移动前循环查找二维数组相邻的移动方向的行或列可以合并与否,如果没有可以合并的数字方块同时又没有空余的空间产生新的数字则游戏宣告结束,同时,当检测到合并的结果中出现2048,也宣告游戏结束。
    游戏设计了非常简单的交互逻辑,流程如下:
    这里写图片描述
    为了增加游戏的用户体验,后期加入了操作音效(音效文件提取自百度移动应用商店——2048),在移动和合并方块时播放不同声音。

    二、 具体代码及程序框图分析

    整个游戏有三个类,分别为游戏的主类Game.class、事件处理类MyListener.class、声音处理类PlaySound.class,下面对Game.class和MyListener.class进行说明。
    Game.class的简单程序框图如下:
    这里写图片描述
    游戏的主类Game.class是窗体程序JFrame的扩展类,主要负责界面的搭建,完成界面绘图的工作。该类作为主类,主方法public static void main(String[] args)中先新建一个该类的对象,接着调用用与创建界面控件的方法IntUI(),代码如下:

    public static void main(String[] args) {
            Game UI = new Game();
            UI.IntUI();
        }

    IntUI()方法用于JFrame控件及界面框架的搭建,代码解析如下:
    首先创建一个窗体,标题为“2048小游戏”,把坐标固定在屏幕的x=450,y=100的位置,把窗体大小设置为宽400像素高500像素,然后把JPlane的布局管理器设置为空,具体代码如下:

    this.setTitle("2048小游戏");
    this.setLocation(450, 100);
    this.setSize(400, 500);
    this.setLayout(null);
    

    接下来分别是【新游戏】、【帮助】、和【退一步】的按钮,以【新游戏】按钮为例,创建一个新游戏的图片按钮,图片相对路径为res/start.png,为了达到更美观的显示效果,把聚焦,边线等特征设置为false,把相对窗体的坐标设置为(5, 10),大小设置为宽120像素高30像素,具体代码如下:

    ImageIcon imgicon = new ImageIcon("res/start.png");
    JButton bt = new JButton(imgicon);
    bt.setFocusable(false);
    bt.setBorderPainted(false);
    bt.setFocusPainted(false);
    bt.setContentAreaFilled(false);
    bt.setBounds(-15, 10, 120, 30);
    this.add(bt);
    

    而分数显示控件与按钮控件类似,不再赘述。
    布置好控件后,为了彻底结束进程,不再占用内存,使用 System exit 方法退出应用程序,同时由于按钮都是相对窗体固定坐标的,所以不允许用户随意改变窗体大小,最后把界面设置为可见,具体代码如下:

    this.setDefaultCloseOperation(3);
    this.setResizable(false);
    this.setVisible(true);
    

    对于按钮的监听,是在MyListener.class中处理的,在IntUI中只是新建一个对象来引用该类,该类具体后面会有说明,这里引用的代码如下:

    MyListener cl = new MyListener(this, Numbers, lb, bt, about,back);
    bt.addActionListener(cl);
    about.addActionListener(cl);
    back.addActionListener(cl);
    this.addKeyListener(cl);
    

    IntUI方法至此结束。
    接下来便是游戏中大方框和数字小方框的绘制,这里用到了paint方法来绘制容器。
    paint方法不需要调用,只需要重写。
    在继承父类的方法后,先绘制出大矩形框,为了美观,这里绘制圆角矩形框,底色的16进制值为:0xBBADA0,边长为370像素,在窗口的相对位置为x=15像素,y=110像素,上下弧度为15,代码如下:

    super.paint(g);
    g.setColor(new Color(0xBBADA0));
    g.fillRoundRect(15, 110, 370, 370, 15, 15);
    

    接下来,通过双重循环,绘制4*4的小方框,关于小方框的绘制的相对位置这里有个关键的算法,因为每一个小方框都要距离边框及相邻边框的大小相等才能达到相对美观的效果,以水平方向为例,分析如下:
    因为总的宽度为370像素,假如让每个小方框的间距为10像素,那么在370像素里面除去5个小方框距离的像素值10*5=50像素外,还剩下320像素,一行4个方框,正好80像素一个小方框。在写这双重循环前,可以先绘制了一个简单的位置图如下:

    这里写图片描述
    以第一行的横坐标为例,每绘制完一个小方框,绘制下一个小方框时就要加上前一个方框的宽度,再加上边框之前的距离,所以绘制4*4颜色为0xCDC1B4的小边框的双重循环的代码如下:

    g.setColor(new Color(0xCDC1B4));
    for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 4; j++) {
                    g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 15, 15); 
                }
            }
    

    由于2048游戏里面可能显示的数值有2、4、8、16等等不同的数值,同样是为了美观考虑,我们给显示不同数值的方框绘制不同的颜色,同样,由于一位数字2与两位数字16甚至多位数字128或1024等来说,如果显示的位置与大小相同,那么2等一位数字的显示是完美的,但是2048这些数字的显示就会超出小方框,影响观感所以还要对数字的相对位置和大小做一定的调整,这里的具体代码如下:

    for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (Numbers[j][i] != 0) {
                        int FontSize = 30;
                        int MoveX = 0, MoveY = 0;
                        switch (Numbers[j][i]) {
                        case 2:
                            g.setColor(new Color(0xeee4da));
                            FontSize = 30;
                            MoveX = 0;
                            MoveY = 0;
                            break;
                        case 4:
                            g.setColor(new Color(0xede0c8));
                            FontSize = 30;
                            MoveX = 0;
                            MoveY = 0;
                            break;
                        case 8:
                            g.setColor(new Color(0xf2b179));
                            FontSize = 30;
                            MoveX = 0;
                            MoveY = 0;
                            break;
                        case 16:
                            g.setColor(new Color(0xf59563));
                            FontSize = 29;
                            MoveX = -5;
                            MoveY = 0;
                            break;
                        case 32:
                            g.setColor(new Color(0xf67c5f));
                            FontSize = 29;
                            MoveX = -5;
                            MoveY = 0;
                            break;
                        case 64:
                            g.setColor(new Color(0xf65e3b));
                            FontSize = 29;
                            MoveX = -5;
                            MoveY = 0;
                            break;
                        case 128:
                            g.setColor(new Color(0xedcf72));
                            FontSize = 28;
                            MoveX = -10;
                            MoveY = 0;
                            break;
                        case 256:
                            g.setColor(new Color(0xedcc61));
                            FontSize = 28;
                            MoveX = -10;
                            MoveY = 0;
                            break;
                        case 512:
                            g.setColor(new Color(0xedc850));
                            FontSize = 28;
                            MoveX = -10;
                            MoveY = 0;
                            break;
                        case 1024:
                            g.setColor(new Color(0xedc53f));
                            FontSize = 27;
                            MoveX = -15;
                            MoveY = 0;
                            break;
                        case 2048:
                            g.setColor(new Color(0xedc22e));
                            FontSize = 27;
                            MoveX = -15;
                            MoveY = 0;
                            break;
                        default:
                            g.setColor(new Color(0x000000));
                            break;
                        }
    
        g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 10, 10);
        g.setColor(new Color(0x000000));
        g.setFont(new Font("Arial", Font.PLAIN, FontSize));
        g.drawString(Numbers[j][i] + "", 25 + i * 90 + 30 + MoveX,
    120 + j * 90 + 50 + MoveY);
            }
        }
    }
    

    至此,Game.class的分析结束,下面是对按钮监听及时间处理的MyListener.class的分析。
    MyListener.class是一个键盘监听事件的扩展类,该类的简单程序框图如下:
    这里写图片描述
    在该类的开始,先声明一些变量,如用于接收传递进来的数组Numbers[][],随机数rand,备份数组用的BackUp[][],BackUp2[][]等等,代码如下:

    private Game UI; 
    private int Numbers[][];
    private Random rand = new Random();
    private int BackUp[][]= new int[4][4]; 
    private int BackUp2[][]= new int[4][4]; 
    public JLabel lb;
    int score = 0;
    int tempscore,tempscore2; 
    public JButton bt,about,back;
    private boolean isWin=false,relive=false,hasBack=false,isSound=true;

    然后是MyListener的构造方法,把来自Game类中传进来的参数接收,代码如下:

    public MyListener(Game UI, int Numbers[][], JLabel lb,JButton bt,JButton about,JButton back,JCheckBox isSoundBox) {
            this.UI = UI;
            this.Numbers = Numbers;
            this.lb = lb;
            this.bt=bt;
            this.about=about;
            this.back=back;
            this.isSoundBox=isSoundBox;
        }
    

    接下来是按钮的监听,通过e.getSource()取得按钮相应的值,进行相应的处理,下面分别解析下【新游戏】按钮和【退一步】按钮的代码:
    【新游戏】按钮作为游戏的开始,将会在按下该按钮是初始化很多数据,例如游戏胜利标志,分数值,4*4的二维数组等,该按钮的控制代码的工作逻辑是这样的:先把胜利标志置为false,然后通过双重循环,把所有的小方格的数据初始化为0,接着把分数值置为0,接下来分别定义四个4以内的随机数整型变量,两两为行数和列数,当它们组合相等时再重新产生两个新的,直到不相等为止,然后生成2个2或者4的数字赋值到对应的位置,完成赋值后,重写一次paint函数,把数组的非零元素绘制在对应位置的小方框内,代码如下:

    if(e.getSource() ==bt ){
        isWin=false;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            Numbers[i][j] = 0;
    score = 0; 
    lb.setText("分数:" + score);
    int r1 = rand.nextInt(4);
    int r2 = rand.nextInt(4);
    int c1 = rand.nextInt(4);
    int c2 = rand.nextInt(4);
    while (r1 == r2 && c1 == c2) {
        r2 = rand.nextInt(4);
        c2 = rand.nextInt(4);
        }
         int value1 = rand.nextInt(2) * 2 + 2;
    int value2 = rand.nextInt(2) * 2 + 2;
    Numbers[r1][c1] = value1;
    Numbers[r2][c2] = value2;
    UI.paint(UI.getGraphics());
    }
    

    【退一步】按钮分了两种情况考虑,为了出现退一步继续按【退一步】按钮出现异常情况,加了一个是否已经进行过一次回退操作了的标志hasBack,进入回退按钮的操作后,先判断是否是起死回生类型的回退,如果不是起死回生类型的回退则把非起死回生分数备份的变量tempscore赋值回记录分数的变量score,然后循环调用java.util.Arrays.copyOf()方法复制数组,把备份的数组复制回去Numbers数组;如果是起死回生类型的回退,重新复制等操作和前面是一样的,不同点在于起死回生类型的回退在操作后,把起死回生回退的标志relive重新置为false。在完成这些操作后,重新绘图,代码如下:

    else if(e.getSource()==back&&hasBack==false){
        hasBack=true;
        if(relive==false){
        score=tempscore;
        lb.setText("分数:" + score);
        for(int i=0;i<BackUp.length;i++){
            Numbers[i]=Arrays.copyOf(BackUp[i], BackUp[i].length);
        }
        }
        else{
                score=tempscore2;
                lb.setText("分数:" + score);
                for(int i=0;i<BackUp2.length;i++){
            Numbers[i]=Arrays.copyOf(BackUp2[i], BackUp2[i].length);
                }
                relive=false;
        }
        UI.paint(UI.getGraphics()); 
    }
    

    下面是按键监听的解析,按键监听通过相应的键值识别按键,然后运用switch开关语句控制不同按键的事件。在处理所有时间之前,先定义三个整型变量,用于计数,然后判断BackUp数组是否为空,因为第一次运行时用于普通数组备份的BackUp数组是没有任何东西的,直接拿来备份会报异常。在备份好数组后,就是对应的键值的监听,以按下方向键左为例(其它三个方向键处理方式基本相同,只是行列及方向的区别),向左移动时,采用三个双重循环,三个循环均为外循环的变量h控制行数,内循环变量l控制列数。在第一个双重循环中,内循环先遍历每一列,判断该列的前一列是否为0,如果前一列为0,则把该列赋值给一个临时变量,把临时变量的值赋值给前一列,然后把该列置0;外循环是遍历行数,每完成一行的操作转至下一行继续重复操作。该操作的代码如下:

    for (int h = 0; h < 4; h++)
        for (int l = 0; l < 4; l++)
            if (Numbers[h][l] != 0) {
                int temp = Numbers[h][l];
                int pre = l - 1;
            while (pre >=0 && Numbers[h][pre] == 0) {
                Numbers[h][pre] = temp;
                Numbers[h][pre + 1] = 0;
                pre--;
                Counter++;
    }
    }
    

    在完成一次靠左移动后,接下来的双重循环使用来合并小方格中数字相同的元素的,把他们相加并放到靠左的方格中,同样外循环是用来控制行数,内循环控制列数,在内循环中加了一个判断条件,当列数加1小于4时(因为只需循环到第三列即可完成该操作),同时该列与该列+1的那一列的元素值相等且它们都不等于0时,即可进行合并操作,合并后,把该列的值置为两元素相加的结果,并把该列+1列置为0,然后把统计是否移动了的计数器进行一个自增操作。完成该操作的代码如下:

    for(int h=0;h<4;h++)
            for(int l=0;l<4;l++)
                if(l+1<4&&(Numbers[h][l]==Numbers[h][l+1])&&(Numbers[h][l]!=0||Numbers[h][l+1]!=0)){
    new PlaySound("merge.wav").start();
    Numbers[h][l]=Numbers[h][l]+Numbers[h][l+1];
    Numbers[h][l+1]=0;
    Counter++;
    score+=Numbers[h][l];
    if(Numbers[h][l]==2048){
    isWin=true;
        }
    }
    

    在完成该操作后,为了避免合并后,出现方块不在最左边的情况,还需要一次整体遍历左移,这次整体遍历左移和第一次的双重循环一样,所以这里不再分析。
    在完成移动及合并操作后,要判断相邻的方块是否还能合并,因为有可能出现移动后,相邻的方块又能进行新的合并,如果不加这个判断的话,当所有的方块全部填满时会无判断游戏结束。
    这里判断相邻的新的方块是否能进一步合并也是用到双重循环,外循环控制行数,内循环控制列数,逐个判断下和右是否能进一步合并,如果能则相邻方块的计数器做自增操作,代码如下:

    for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
            if (Numbers[i][j] == Numbers[i][j + 1]&& Numbers[i][j] != 0) {
                    NumNearCounter++;
            }
    if (Numbers[i][j] == Numbers[i + 1][j]&& Numbers[i][j] != 0) {
                   NumNearCounter++;
            }
    if (Numbers[3][j] == Numbers[3][j + 1]&& Numbers[3][j] != 0) {
                   NumNearCounter++;
            }
    if (Numbers[i][3] == Numbers[i + 1][3]&& Numbers[i][3] != 0) {
                   NumNearCounter++;
                }
            }
    }
    

    在完成上述操作后,在判断非0元素的个数,应为当非零元素个数为0时,即代表所有的小方块中已经有元素存在了,16个方块全部都满了,这里的代码如下:

    for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (Numbers[i][j] != 0) {
                    NumCounter++;
                }
            }
        }
    

    在完成统计空格个数后,如果按下按键后发生了移动,就完成分数的更新,因为要移动一次后在随机的空的格子(这里指元素值为0的格子)里面产生新的基于2或者4的随机数,代码如下:

    if (Counter > 0) {
    lb.setText("分数:" + score);
        int r1 = rand.nextInt(4);
        int c1 = rand.nextInt(4);
        while (Numbers[r1][c1] != 0) {
            r1 = rand.nextInt(4);
            c1 = rand.nextInt(4);
        }
        int value1 = rand.nextInt(2) * 2 + 2;
        Numbers[r1][c1] = value1;
    }
    

    接下来判断这次移动后,有没有出现isWin == true的情况,如果出现了,就弹出游戏胜利的标志,代码如下:

    if (isWin == true){
                    UI.paint(UI.getGraphics());
                    JOptionPane.showMessageDialog(UI, "恭喜你赢了!\n您的最终得分为:" + score);
                }
    

    然后,判断是否是16个格子全满了同时相邻的方格不能进一步合并了,如果是则把可以进行起死回生操作的标志relive置为true,同时弹出游戏结束的提示语,代码如下:

    if (NumCounter == 16 && NumNearCounter == 0) {
            relive = true;
            JOptionPane.showMessageDialog(UI, "没地方可以合并咯!!"
                    + "\n很遗憾,您输了~>_<~" + "\n悄悄告诉你,游戏有起死回生功能哦,不信你“退一步”试试?"
    + "\n说不定能扭转乾坤捏 (^_~)");
        }
    

    最后,重新绘制图形。
    MyListener类的分析到此结束。

    三、 参考资料

    Java API1.6.0中文版
    Java从入门到精通(第三版)

    源代码下载:http://download.csdn.net/detail/kevinwu93/8714079

    展开全文
  • 小游戏面向对象 一,问题分析 计算机输出字符串,玩家根据计算输出的内容重复输入,如果输入正确,进入一下关的练习 该过程记录玩家的积分,定义游戏的关卡,定义游戏的规则 1.1定义游戏的规则 游戏的关卡 1关 每...
  • 软件工程一课中,我们开发斗地主小游戏,能够实现联机,以下为我们的源代码和开发过程 https://github.com/Zongziyu/Software-course PS:持续更新中
  • 德国人Fabian Birzele 编写的游戏开发指南书 网站:http://www.javacooperation.gmxhome.de/ 源码及指南动画展示下载:http://www.javacooperation.gmxhome.de/Downloads/Tutorial.zip 现在流行的游戏似乎都是用C或
  • /*博弈游戏:三个骰子,约定三个骰子的点数1-6,  最大点数:18  最小点数:3  求三个色子点数的和  3---9 输出   10—18 输出 大*/ //手动输入三颗骰子的值 import java.util.Scanner; ...
  • Java开发数独游戏,源程序与源代码全部开放

    千次阅读 多人点赞 2020-03-28 17:23:16
    如何用Java语言开发出一个带有界面的数独游戏? 这篇文章将带你从零开始写出完整的游戏小项目。
  • java swing游戏编程高仿金山打字教程-拯救苹果 源代码下载地址:http://www.zuidaima.com/share/1786650901515264.htm
  • 桌球小游戏java编程

    千次阅读 2019-02-25 14:06:58
    桌球游戏小项目 项目需求: 桌球在球桌中按照一定线路和角度移动,遇到边框会自动弹回。如图: 项目中用到的两个小图片,如下: 开发步骤: 目标:创建项目、创建窗口。 创建项目并拷贝图片: 在项目名MyPro01上...
  • Java游戏编程初步

    千次阅读 2008-07-23 19:29:00
    Java游戏编程初步 现在流行的游戏似乎都是用C或C++来开发的。在java平台上几乎没有很大型及可玩的流行游戏。由于java是个新生语言,他的许多特性还有待大家的发掘,但是我们不能否认Java游戏编程方面的强大性。...
  • Java飞机小游戏代码详解

    千次阅读 2019-02-20 23:47:36
    在做Java项目时我们要有面向对象的思想,将具有某一功能或者说某一个可以看做是一体的代码,我们要学会封装起来,一方面偏于调用,另一方面便于维护。这里我们可以创建一个GameObject类,这个类是游戏中所有物体的...
  • 如何阅读java项目的源代码

    万次阅读 2012-09-19 18:51:28
    比如说 你看书看累了 写个程序放松下(一般别人是玩游戏放松)- -这样你就可以了解你要看的代码的功能和所用的框架技术,这样在熟悉的基础上就能得心应手了。   不过,我可不相信什么一天敲多少行的代码,你要...
  • FlappyBird安卓JAVA源代码

    千次阅读 2014-04-11 17:06:37
    3.游戏是依据flappybird的游戏过程重新写的算法,功能与原版游戏相似,可能有些地方不足,完全是学习练习编程而已,做的不好见谅 4.程序游戏中使用到的图片我会尽量上传上去*/ public class MainActiv
  • 做好以后,总觉得这种控制台的界面看着不舒服,自己又会一些GUI界面的知识,然后就做了个这么个小游戏.(本程序全部源代码已上传,需要的可以去下载) 编程最重要的是思路,让我们先把思路理清楚: 首先是了解一下扫雷规则...
  • 2008年的时候,在学习Java how to program第五版的时候,写过一个猜数字小游戏,是用Applet写的; 现在,我要用Swing重写这个小游戏,同时,加入一些新功能,如:背景颜色(红色表示偏高,蓝色表示偏低)、弹框、...
  • JAVA五子棋小游戏

    万次阅读 多人点赞 2018-08-10 18:05:20
    学完Java基础书时总想着要自己编写出小游戏,事情并非如自己所愿,每次鼓起勇气来编写时,总是不知道该怎么写,写到一半就开始放弃。因为自己习惯跟着视屏去看和编写,思路和方法都是老师教,自己根本无法去考虑那么...
  • 分享16款Java小游戏源码Java applet小游戏源码

    万次阅读 多人点赞 2018-02-06 16:33:49
    给大家分享本人收集整理的16款Java小游戏源码,大部分是applet小程序,下面把每个游戏做个截图,最下面会有下载地址: 目录结构: 下载地址:...
  • Java2游戏编程读书笔记(9-1)

    千次阅读 2007-03-06 20:17:00
    第三篇. 面向大众的Java游戏“道存在于电子游戏中吗?...本篇中将进一步学习如何在游戏编程中应用这些技术,还会看到如何运用面向对象原则来为游戏创建可重用的游戏对象。在接下来的几章中,我们将专注于2-D游戏的
  • 截图: 代码过长不在此贴出,所有的代码都打包在以下链接中压缩包里,包括背景图片。 源代码下载链接: http://download.csdn.net/detail/destiny19960207/9763751
  • java小游戏大鱼吃小鱼入门(15min写一个小游戏)

    千次阅读 多人点赞 2018-09-23 18:44:57
    代码前分析下游戏的各个部分 1.游戏构成: 大鱼吃小鱼=主角鱼+其他各种鱼(自由鱼)+游戏按钮+游戏背景 2.游戏过程: 主角鱼遇到比自己的鱼:吃掉–&amp;amp;amp;gt;自身size变大 主角鱼遇到比自己大的鱼...
  • Java石头剪刀布小游戏代码

    万次阅读 2016-01-22 16:51:25
    importjava.util.Scanner; publicclass Game {  public Person person; //类类型的属性  public Computer computer;  public int count;//对战次数  public int scount=0;    //初始化...
  • Java小游戏——贪吃蛇

    千次阅读 2020-01-27 14:59:55
    Java小游戏之贪吃蛇 系统目标 贪吃蛇是一个益智类游戏,通过本游戏的设计和实现,可以提升Java技术能力,提升自己独立开发的能力及掌握项目的开发流程。 开发环境 系统环境:Windows 开发工具:Eclipse Mars、JDK1.8...
  • java gui编程介绍

    千次阅读 2016-08-28 15:41:22
    java GUI编程java体系中相对比较不受重视的一个部分 ,相比较其他语言中的图形界面,GUI没有什么优势,所以这个GUI看起来似乎并...在介绍完这部分的大致内容时,我会上传一个简单的小游戏flappy bird供大家练练手。
  • Java2游戏编程读书笔记(4-1)

    千次阅读 2006-12-20 09:48:00
    第4章 Java API为你服务:常用Java类4.1 Java.lang包Java.lang包中含有Java语言的基本类,其中包括系统工具,原始数据类型的封闭类,数学工具和线程管理。4.1.1 Java.lang.ObjectObject类是所有Java类的基类。这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,905
精华内容 12,762
关键字:

java小游戏编程源代码

java 订阅