欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

俄罗斯方块小游戏

程序员文章站 2024-03-18 19:50:52
...

俄罗斯方块小游戏

简单的实现俄罗斯方块,只有一个主代码,很好理解的,有暂停/继续、重新开始、结束游戏的简单功能。这里就不多说实现的原理了,可以在网上进行相关的查询。这里就直接给出了源代码,这个也是我参考网上的,自己进行了相关的更改,增加了一些功能。

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.Timer;


public class MyGame extends JFrame {

	   public MyGame(){
		GameBody gamebody=new GameBody();
		gamebody.setBounds(5,10,500,600);  //
	    gamebody.setOpaque(false);
		gamebody.setLayout(null);
		addKeyListener(gamebody);
		add(gamebody);
		

		int w=Toolkit.getDefaultToolkit().getScreenSize().width;
        int h=Toolkit.getDefaultToolkit().getScreenSize().height;
		JLabel image=new JLabel(new ImageIcon("13.jpg"));
		image.setBounds(0,0,500,600);
	    getLayeredPane().setLayout(null);
		getLayeredPane().add(image,new Integer(Integer.MIN_VALUE));
		((JPanel)getContentPane()).setOpaque(false);

		final JButton login=new JButton(new ImageIcon("login4.PNG"));
		login.setContentAreaFilled(false);
		login.setMargin(new Insets(0,0,0,0));
		login.setBorderPainted(false);
		login.setBounds(340,320,120,26);
		gamebody.add(login);

		login.addActionListener(new ActionListener(){
		   public void actionPerformed(ActionEvent e) {    //登录的按钮
				if(e.getSource()==login){
				requestFocus(true);    //获得焦点,不用失去焦点
				gamebody.resetMap();   //重置地图
				gamebody.drawWall();   //冲重新绘制边界墙体
				gamebody.createshape();   //重新产生新的地图
				gamebody.setStart(false);  //唤醒定时下落的线程
			    gamebody.score=0;       //将分数置为零
			    repaint();
				}
		   }
		});

		final JButton pauselogin=new JButton(new ImageIcon("login6.PNG"));
		pauselogin.setContentAreaFilled(false);
		pauselogin.setMargin(new Insets(0,0,0,0));
		pauselogin.setBorderPainted(false);
		pauselogin.setBounds(340,370,120,26);
		gamebody.add(pauselogin);

		pauselogin.addMouseListener(new MouseListener(){   //暂停的按钮
		  /* public void actionPerformed(ActionEvent e) {   //用事件监听,没用实现再次按暂停键后继续游戏
				//while(true){
				if (e.getSource()==pauselogin)
				{
					gamebody.setStart(true);
					requestFocus(true);

				}if(e.getSource()==login){
					new GameBody.setStart(false);
					requestFocus(true);
				}
				//}
		   }*/

		 //鼠标点击事件,可以分别判断不同的事件,做出不同的反应 
		public void mouseClicked(MouseEvent e){
			if(e.getButton()==e.BUTTON1 ){     //单击左键暂停
				gamebody.setStart(true);   //将自动下落线程关闭
				//requestFocus(true);    //同时整个JFrame失去焦点,无法操作,但可以点击按钮
			}
        else if(e.getButton()==e.BUTTON3 ){   //右击暂停,继续游戏
                gamebody.setStart(false);   //唤醒自动下落线程
				requestFocus(true);
			}
        if(e.getClickCount()==2){     //左键双击,也可以继续游戏
                gamebody.setStart(false);
			    requestFocus(true);
			}
		}
		public void mouseEntered(MouseEvent e){}
		public void mouseExited(MouseEvent e){}
		public void mousePressed(MouseEvent e){}
		public void mouseReleased(MouseEvent e){}
		   
		});

		final JButton overlogin=new JButton(new ImageIcon("login5.PNG"));   //退出的按钮
		overlogin.setMargin(new Insets(0,0,0,0));
		overlogin.setContentAreaFilled(false);
		overlogin.setBounds(340,420,120,26);
		overlogin.setBorderPainted(false);
		add(overlogin);

		overlogin.addActionListener(new ActionListener(){
		   public void actionPerformed(ActionEvent e) {
		      System.exit(1);
		   }
		});
        
		setTitle("俄罗斯方块 V.1.0");
		setResizable(false);
		setFocusable(true);
		setBounds((w-500)/2,(h-600)/2,500,600);
		setLayout(null);

		setVisible(true);
		setDefaultCloseOperation(3);
	}
	public static void main(String[] args) {
		new MyGame();
	}

	//创建需要定义的局部变量和游戏类
	 class GameBody extends JPanel implements KeyListener{
		private int shapeType=-1;  //定义方块的类型  定义的为7中
		private int shapeState=-1; //定义方块为何种状态,每种都有四种状态
		private int nextshapeType=-1;  //定义下一块产生的类型
		private int nextshapeState=-1;  //定义下一块的方块的状态
		private final int CELL=25;   //定义方格的大小
		private int score=0;    //定义显示的成绩
		private int left;       //定义初始图形与两边的墙的距离
		private int top;        //定义初始图形与上下墙的距离
		private int i=0;        //表示列
		private int j=0;        //表示行
		public int flag=0;
		public  volatile boolean start=false;  //暂停的判断条件,为轻量锁,保持同步的
		//public boolean start=false;
		//Timer t;
		Random randomcolor=new Random();
		Random random=new Random();

		//定义地图的大小,创建二位的数组
		int[][] map=new int[13][23];

		//初始化地图
		public void resetMap(){
		  for(i=0;i<12;i++){
		     for(j=0;j<22;j++){  //遍历的范围不能小
			  map[i][j]=0;
			}
		  }
		}

		//画围墙的方法
		public void drawWall(){
		  for(j=0;j<22;j++)  //0到21行
		  {
			map[0][j]=2;
			map[11][j]=2;    //第0行和第11行为墙
		  }
		  for(i=0;i<12;i++){  //0到11列
		    map[i][21]=2;    //第21行划墙
		  }
		}


		//定义随机的图形种类
		private final int[][][] shapes=new int[][][]{
			// i
	          {       { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
	                  { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 } },
	          // s
	          {		{ 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } },
	          // z
	          {		{ 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } },
	          // j
	          {		{ 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
	                  { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
	          // o
	          {		{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
	          // l
	          {		{ 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
	                  { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
	          // t
	          {		{ 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
	                  { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	                  { 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } }
		};


		//产生新图形的方法
		public void createshape(){
			if(shapeType==-1&&shapeState==-1){
			  shapeType = random.nextInt(shapes.length);
			  shapeState = random.nextInt(shapes[0].length);
			}else{
			  shapeType=nextshapeType;
			  shapeState=nextshapeState;
			}
			  nextshapeType = random.nextInt(shapes.length);
              nextshapeState = random.nextInt(shapes[0].length);
			//shapeType=(int)(Math.random()*1000)%7;   //在7中类型中随机选取
			//shapeState=(int)(Math.random()*1000)%4;  //在四种状态中随机选取 
			left=4; top=0;  //图形产生的初始位置为(4,0)\
			if(gameOver(left,top)==1){ 
			//判断游戏
			  resetMap();
			  drawWall();
			  score=0;
	        JOptionPane.showMessageDialog(null, "GAME OVER");
			}
		}

		//遍历[4][4]数组产生的方块并判断状态
		public int judgeState(int left,int top,int shapeType,int shapeState){
			for(int a=0;a<4;a++){
			  for(int b=0;b<4;b++){
			    if(((shapes[shapeType][shapeState][a*4+b]==1 &&   //遍历数组中为1的个数,即判断是否有图形
					map[left+b+1][top+a]==1))||                   //判断地图中是否还有障碍物
					((shapes[shapeType][shapeState][a*4+b]==1 &&   //遍历数组中为1的个数,即判断是否有图形
					map[left+b+1][top+a]==2))){                   //判断是否撞墙
					      return 0;    //表明无法不能正常运行
					}                 
			  }
			}
		    return 1;
		}


		//创建键盘事件监听
		public void keyPressed(KeyEvent e){
		//if (start){
		  switch(e.getKeyCode()){
			case KeyEvent.VK_LEFT:
			leftMove();//调用左移的方法
			repaint();
			break;
			case KeyEvent.VK_RIGHT:
			rightMove();//调用右移的方法
			repaint();
			break;
			case KeyEvent.VK_DOWN:
			downMove();//调用左移的方法
			repaint();
			break;
			case KeyEvent.VK_UP:
			turnShape();//调用变形的方法
			repaint();
			break;
		  }
		// }
		}
	  public void keyReleased(KeyEvent e) {
	  }
	  public void keyTyped(KeyEvent e) {
	  }



	  //创建左移的方法
		public void leftMove(){
			if(judgeState(left-1,top,shapeType,shapeState)==1){
				left-=1;
				}
		}
		//创建右移的方法
	  public void rightMove(){
		    if(judgeState(left+1,top,shapeType,shapeState)==1){
				left+=1;
				};
			
		}
		//创建下移的方法
		public void downMove(){
		    if(judgeState(left,top+1,shapeType,shapeState)==1){  //判断有图形
				top+=1;
				deleteLine();   //判断下移后是否有满行
				}
			if(judgeState(left,top+1,shapeType,shapeState)==0){   //判断没有图形
			    
				addshape(left,top,shapeType,shapeState);
				createshape();
				deleteLine();
			}
		}


		//创建旋转变形的方法
		public void turnShape(){
		  int tempshape=shapeState;
		  shapeState=(shapeState+1)%4; //在四中的状态中选取
		  if(judgeState(left,top,shapeType,shapeState)==1){
			  
		  }
		  if(judgeState(left,top,shapeType,shapeState)==0){
		        shapeState=tempshape;   //没有图形,不能进行旋转,还原原来状态
		  }
				repaint();
		}

		//绘图方法
		public void paintComponent(Graphics g){
		   super.paintComponent(g);
		   int t=randomcolor.nextInt(5);
		   int count=randomcolor.nextInt(5);
		   Color[] color=new Color[]{Color.pink,Color.green,Color.red,Color.yellow,Color.blue};
		  /* Image image = null;
		try {
			image = ImageIO.read(new File("1.jpg"));
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
			g.drawImage(image, 0, 0,this);
		}*/
		   
		  //绘制围墙
		   for(j=0;j<22;j++){
		     for(i=0;i<12;i++){
			   if(map[i][j]==2){//判断是否为墙并绘制
				 g.setColor(Color.blue);
			     g.fill3DRect(i*CELL,j*CELL,CELL,CELL,true);
			   }
               if(map[i][j]==0){//判断是否为墙并绘制
				 g.setColor(Color.red);
			     g.drawRoundRect(i*CELL,j*CELL,CELL,CELL,6,6);}
			 }
		   }
		   
		   //绘制正在下落的图形
		   for(int k=0;k<16;k++){
		     if(shapes[shapeType][shapeState][k]==1){
			   g.setColor(Color.red);
			   g.fill3DRect((left+k%4+1)*CELL,(top+k/4)*CELL,CELL,CELL,true);  //left\top为左上角的坐标
			 }
		   }

		   //绘制落下的图形
		   for(j=0;j<22;j++){  
		     for(i=0;i<12;i++){
			   if(map[i][j]==1){
				 g.setColor(Color.green);
			     g.fill3DRect(i*CELL,j*CELL,CELL,CELL,true);
			   }
			 }
		   }   

           //显示右边预览图形
		   for(int i = 0; i < 4; i++) {
			 for(int j = 0; j < 4; j++){
				if(shapes[nextshapeType][nextshapeState][i*4+j] == 1) {
					g.setColor(Color.red);
					g.fill3DRect(375+(j*(CELL-10)),190+(i*(CELL-10)), CELL-10, CELL-10,true);
					}
				 }
			}
			//添加右边预览图形方格
			for(int i = 0; i < 5; i++) {
			 for(int j = 0; j < 5; j++){
					g.setColor(Color.blue);
					g.drawRoundRect(360+(j*(CELL-10)),175+(i*(CELL-10)),CELL-10, CELL-10,3,3);
				 }
			}
		   g.setFont(new Font("楷书",Font.BOLD,20));
		   g.setColor(Color.BLUE);
		   g.drawString("游戏分数:", 310, 70);
		   g.setColor(Color.RED);
		   g.drawString(score+"  ", 420, 70);
		   g.setColor(Color.BLUE);
		   g.drawString("  分", 450, 70);

		}


	//创建添加新图形到地图的方法、
		public void addshape(int left,int top,int shapeType,int shapeState){
	     int temp=0;
		   for(int a=0;a<4;a++){
		     for(int b=0;b<4;b++){   //对存储方块队的[4][4]数组遍历
				if(map[left+b+1][top+a]==0){ //表明[4][4]数组没有方块
					
				    map[left+b+1][top+a]=shapes[shapeType][shapeState][temp];
				}
				temp++;
			 }	 
		   }
		}


	  

		//创建消行的方法,即将满行以上的部分整体下移
	  public void deleteLine(){
		  int tempscore=0;      //定义满行的列个数满足1
		  for(int a=0;a<22;a++){   //对地图进行遍历
		    for(int b=0;b<12;b++){
			  if(map[b][a]==1){    //表示找到满行
			     tempscore++;     // 记录一行有多少个1
				 if(tempscore==10){
				   score+=10;
				 for(int k=a;k>0;k--){     //从满行开始回历
				   for(int c=1;c<12;c++){
				      map[c][k]=map[c][k-1];  //将图形整体下移一行
				   }
				 }
				 }
			}
		  }
			tempscore=0;
		  }
		}



	  //判断游戏结束,1、判断新块的状态是否不存在,即judgeState()==0
		//2、判断初始产生的位置是否一直为1;
		public int gameOver(int left,int top){
		  if(judgeState(left,top,shapeType,shapeState)==0){
		     return 1;
		  }
		  return 0;
		}

		//创建构造方法
		public GameBody(){
			resetMap();
			drawWall();
			createshape();
			//Timer timer=new Timer(1000,new TimeListener());
			Thread timer=new Thread(new	TimeListener());
			timer.start();
		}

		public void setStart(boolean start){   //改变start值的方法
			this.start=start;
		}

		//创建定时下落的监听器
		class TimeListener implements Runnable{
		  public void run(){
			  while(true){
				if(!start){
			  try{
				repaint();
				if(judgeState(left,top+1,shapeType,shapeState)==1){
				      top+=1;
				      deleteLine();}
				if(judgeState(left,top+1,shapeType,shapeState)==0){
					if(flag==1){
					  addshape(left,top,shapeType,shapeState);
					  deleteLine();
					  createshape();
					  flag=0;
					}
					flag=1;
				}
				Thread.sleep(800);
		  }catch(Exception e){
			e.getMessage();
			   }
			 } 
			}
		  }
	    }	
   } 	 
} //外层

下面是游戏演示的一些界面效果图:
俄罗斯方块小游戏
这里说一下,我是把图片和源代码直接放在了一个文件夹下,对于初学者很好理解,这也是很好的练手项目。图片什么的大家可以在网上直接找一个,然后重命名一下就可了。