JAVA——拼图小游戏

大三Java程序设计课老师让做的大实验,我做了拼图游戏,参考了https://blog.csdn.net/A1344714150/article/details/84888599这个博主的代码,我的没有实现存储记录和难度选择功能。

运行结果:

主要组成:HelpPanel和GamePanel页面。

源码如下:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
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.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class JigsawPuzzle {
	
	public final static int N = 3;//3*3的拼图
	
	public static void main(String[] args) {
		  MyFrame frame= new MyFrame();
	      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	      frame.setVisible(true);//使界面可视
	}
	
	static class MyFrame extends JFrame
	{
		private static final long serialVersionUID = 1L;
		private int num=0;//生成随机数
		private Image[] pictures;//存储分割后的图片
		private int [][] arr;//存储打乱的图片顺序
		private int [][] FinalArr;//未打乱正确的图片顺序
		int blank_x,blank_y;//记录空白块的下标
		int step=0;//记录所走步数
		public static HelpPanel panel7;
		public static GamePanel panel8;
		
		//构造函数
		public MyFrame()
		{
			num = (int) ( Math.random () * 7 + 1 );//生成随机数,传参,选取图片
			setTitle("JigsawPuzzle");
			setSize(600,360);
			panel7=new HelpPanel(num);
			panel8=new GamePanel(num);
		    add(panel8,"Center");
		    add(panel7,"East");
		}
		
		//右边的帮助页面
		public class HelpPanel extends JPanel{
			
			Font font2=new Font("宋体",Font.PLAIN,17);//定义一个字体样式
			//定义上,下,左,右,换一张图,退出按钮
			JButton UpButton = new JButton("上");
		    JButton LeftButton = new JButton("左");
		    JButton DownButton = new JButton("下");
		    JButton RightButton = new JButton("右");
		    JButton ChangeButton = new JButton("换一张图");
		    JButton ExitButton = new JButton("退出");
		    
		    JPanel panel1=new JPanel(new BorderLayout());
		    JPanel panel2=new JPanel(new GridLayout(1,3,10,30));
		    JPanel panel4=new JPanel();
		    JPanel panel5=new JPanel();
		    
		    //帮助页面构造函数
		    public HelpPanel(int nume) {
		    	this.setLayout(new BorderLayout());
		    	PicturePanel panel3=new PicturePanel(nume);
		    	UpButton.setFont(font2);
			    LeftButton.setFont(font2);
			    DownButton.setFont(font2);
			    RightButton.setFont(font2);
			    ChangeButton.setFont(font2);
			    ExitButton.setFont(font2);
			    
			    //帮助页面的布局为Borderlayout,有三个面板panel1,panel2,panel3,分别在为North,South,Center位置
			    //panel1放“上”,“下”,“左”,“右”按钮;panel2放“换一张图”,“退出”按钮;panel3放正确的帮助图片;
			    //panel1又分为两个面板panel4,panel5;panel4添加“左”,“下”,“右”按钮,放在panel1的South位置;panel5添加“上”按钮,放在panel1的North位置
			    panel5.add(UpButton);
		    	panel1.add(panel5,BorderLayout.NORTH);
		    	panel4.add(LeftButton);
		    	panel4.add(DownButton);
		    	panel4.add(RightButton);
		    	panel1.add(panel4, BorderLayout.SOUTH);
			    panel2.add(ChangeButton);
			    panel2.add(ExitButton);
			    this.add(panel1,BorderLayout.NORTH);
			    this.add(panel3,BorderLayout.CENTER);
			    this.add(panel2,BorderLayout.SOUTH);
			    
			    
			    //添加更换图片事件监听器
			    ChangeButton.addActionListener(new ActionListener()
		           {
		              public void actionPerformed(ActionEvent event)
		              {
		            	  num = (int) ( Math.random () * 7 + 1 );//生成随机数
		            	  MyFrame.panel7=new HelpPanel(num);
		            	  MyFrame.panel8.GetPictures(num);
		            	  step=0;
		            	  repaint();
		            	  MyFrame.panel8.requestFocus();
		            	  //点击按钮后焦点到按钮上了,原有键盘监听器的组件失去焦点,requestFocus()使焦点重新回到组件panel8上
		              }
	            });
			    
			    //添加退出事件监听器
			    ExitButton.addActionListener(new ActionListener()
		           {
		              public void actionPerformed(ActionEvent event)
		              {
		            	  System.exit(0);
		              }
	            });
			    
			    //添加上移事件监听器
			    UpButton.addActionListener(new ActionListener()
		           {
		              public void actionPerformed(ActionEvent event)
		              {
		            	  if(blank_x!=N-1)
		            	  {
		            		  MoveUp();
		            		  MyFrame.panel8.draw();
		            	  }
		            	  else
		            		  return ;
		            	  IsSuccessful();
		            	  MyFrame.panel8.requestFocus();
		            		  
		              }
	            });
			    
			    //添加下移事件监听器  
			    DownButton.addActionListener(new ActionListener()
		           {
		              public void actionPerformed(ActionEvent event)
		              {
		            	  if(blank_x!=0)
		            	  {
		            		  MoveDown();
		            		  MyFrame.panel8.draw();
		            	  }
		            	  else
		            		  return ;
		            	  IsSuccessful();
		            	  MyFrame.panel8.requestFocus();
		              }
	            });
			    
			    //添加左移事件监听器
			    LeftButton.addActionListener(new ActionListener()
		           {
		              public void actionPerformed(ActionEvent event)
		              {
		            	  if(blank_y!=N-1)
		            	  {
		            		  MoveLeft();
		            		  MyFrame.panel8.draw();
		            	  }
		            	  else
		            		  return ;
		            	  IsSuccessful();
		            	  MyFrame.panel8.requestFocus();
		              }
	            });
			    
			    //添加右移事件监听器
			    RightButton.addActionListener(new ActionListener()
		           {
		              public void actionPerformed(ActionEvent event)
		              {
		            	  if(blank_y!=0)
		            	  {
		            		  MoveRight();
		            		  MyFrame.panel8.draw();
		            	  }
		            	  else
		            		  return ;
		            	  IsSuccessful();
		            	  MyFrame.panel8.requestFocus();
		              }
	            });
			    
		    }
		}
		
		//把图片分成N*N形式从上往下,从左往右赋值为1-9
		public void setArr(){
			arr=new int [N][N];
			for(int i=0;i<N;i++)
			{
				for(int j=0;j<N;j++)
				{
					arr[i][j]=3*i+j+1;//表示把图片分成3*3形式从上往下,从左往右赋值为1-9
				}
			}
			arr[N-1][N-1]=-1;//右下角为空格,值设置为-1;
		}
		
		//把图片分成N*N形式从上往下,从左往右赋值为1-9
		public void setFinalArr(){
			FinalArr=new int [N][N];
			for(int i=0;i<N;i++)
			{
				for(int j=0;j<N;j++)
				{
					FinalArr[i][j]=3*i+j+1;//表示把图片分成3*3形式从上往下,从左往右赋值为1-9
				}
			}
			FinalArr[N-1][N-1]=-1;//右下角为空格,值设置为-1;
		}
		
		//空白块与下面的方块交换,即有图片的方块上移
		private void MoveUp() {
			arr[blank_x][blank_y]=arr[blank_x+1][blank_y];
			arr[blank_x+1][blank_y]=-1;
			blank_x=blank_x+1;
			step++;
		}
		
		//空白块与上面的方块交换,即有图片的方块下移
		private void MoveDown() {
			arr[blank_x][blank_y]=arr[blank_x-1][blank_y];
			arr[blank_x-1][blank_y]=-1;
			blank_x=blank_x-1;
			step++;
		}
		
		//空白块与右面的方块交换,即有图片的方块左移
		private void MoveLeft() {
			arr[blank_x][blank_y]=arr[blank_x][blank_y+1];
			arr[blank_x][blank_y+1]=-1;
			blank_y=blank_y+1;
			step++;
		}
		
		//空白块与左面的方块交换,即有图片的方块右移
		private void MoveRight() {
			arr[blank_x][blank_y]=arr[blank_x][blank_y-1];
			arr[blank_x][blank_y-1]=-1;
			blank_y=blank_y-1;
			step++;
		}
		
		//帮助页面的正确图片页面
 		public class PicturePanel extends JPanel{
 			
			int W=40;//小方块的大小40*40
			
			//构造函数
			public PicturePanel(int nume) {
				
				BufferedImage bufferedImage=null;
				int width=0,height=0;
				try {
					bufferedImage=ImageIO.read(new File("src/picture"+nume+".png"));
					System.out.println("选取图片"+nume);
					width = bufferedImage.getWidth();
		            height = bufferedImage.getHeight();
				}
				catch(IOException e){
					e.printStackTrace();
				}
				pictures=new Image[N*N];
				setArr();
				int w=width/N,h=height/N;//arr中存储的图片的大小
				
				//裁剪小图
				for(int i=0;i<N*N-1;i++) {
					int x=i%N*w;
					int y=i/N*h;
					pictures[i]=bufferedImage.getSubimage(x,y,w,h);
				}
			}
			
			//显示正确图像pictures[]
			public void paint(Graphics g)
			{
				int tag=0;
				for(int i=0;i<N;i++)
				{
					for(int j=0;j<N;j++)
					{
							g.drawImage(pictures[tag++], j*W, i*W, W, W,this);//按顺序显示
					}
				}
			}
			
		}
		
 		//左边的游戏页面
 		public class GamePanel extends JPanel implements ActionListener,MouseListener,KeyListener{
 			
			int W=100;
			public GamePanel(int nume) {
				setSize(300,300);
				
				//给控件添加监听器
				this.addKeyListener(this);
				this.addMouseListener(this);
				this.setFocusable(true);
				this.setVisible(true);
				setFinalArr();//保存正确的图片顺序,方便后面判断是否拼图成功
				blank_x=blank_y=N-1;//初始化空白块为右下角
				GetPictures(nume);
			}
			
			//做10000次移动打乱顺序
			private void WrongOrderArr() {
				
				blank_x=blank_y=N-1;//这里必须重新把空白快定位到右下角,否则已经对图片进行操作之后再点击更换图片会出现两个空白块
	
				int i=0;
				while(i<10000) {
					
					int j=(int)(Math.random()*100);
					if(j<25&&blank_x!=N-1)//空白块不在最后一行时,空白块与下面的方块交换
					{
						MoveUp();
						i++;
					}
					else if(j<50&&blank_x!=0)//空白快不在第一行时,空白块与上面的方块交换
					{
						MoveDown();
						i++;
					}
					if(j<75&&blank_y!=N-1)//空白块不在最后一列时,空白块与右面的方块交换
					{
						MoveLeft();
						i++;
					}
					else if(j<100&&blank_y!=0)//空白块不在第一列时,空白块与左面的方块交换
					{
						MoveRight();
						i++;
					}
				}
				
				//把空白块移到右下角
				while(blank_x<N-1){
					MoveUp();
				}
				
				while(blank_y<N-1){
					MoveLeft();
				}
				step=0;
			}
			
			//画待拼的图
			public void GetPictures(int nume) {
				WrongOrderArr();
				BufferedImage bufferedImage=null;
				int width=0,height=0;
				try {
					bufferedImage=ImageIO.read(new File("src/picture"+nume+".png"));
					width = bufferedImage.getWidth();
		            height = bufferedImage.getHeight();
				}
				catch(IOException e){
					e.printStackTrace();
				}
				pictures=new Image[N*N];
				int w=width/N,h=height/N;//arr中存储的图片的大小
				//裁剪小图
				for(int i=0;i<N*N-1;i++) {
					int x=i%N*w;
					int y=i/N*h;
					pictures[i]=bufferedImage.getSubimage(x,y,w,h);
				}
				this.draw();//这里不能直接写repaint(),因为repaint()会调用paint方法,而super.paint(g);这句会清空组件,导致并不会发生重绘
			}
			public void paint(Graphics g)
			{
				super.paint(g);
				for(int i=0;i<arr.length;i++)
				{
					for(int j=0;j<arr.length;j++)
					{
						if(arr[i][j]!=-1)
						{
							g.drawImage(pictures[arr[i][j]-1], j*W, i*W, W, W,this);//以打乱过的顺序输出图片
						}
					}
				}
			}
			
			public void draw() {
				repaint();
			}
			
			public void keyTyped(KeyEvent e) {
				
			}
			
			//键盘事件,上下左右移动
			public void keyPressed(KeyEvent e) {
				
				if(e.getKeyCode()==KeyEvent.VK_UP&&blank_x!=N-1)
				{
					MoveUp();
					repaint();
				}
				else if(e.getKeyCode()==KeyEvent.VK_DOWN&&blank_x!=0)
				{
					MoveDown();
					repaint();
				}
				else if(e.getKeyCode()==KeyEvent.VK_LEFT&&blank_y!=N-1)
				{
					MoveLeft();
					repaint();
				}
				else if(e.getKeyCode()==KeyEvent.VK_RIGHT&&blank_y!=0)
				{
					MoveRight();
					repaint();
				}
				else
					return;
				IsSuccessful();
			}
			
			public void keyReleased(KeyEvent e) {
				
			}

			public void mouseClicked(MouseEvent e) {
				
			}
			
			//鼠标事件,点击图片进行上下左右移动
			public void mousePressed(MouseEvent e) {
				
				int x=e.getX();
				int y=e.getY();
				
				//超出图片范围,什么都不做
				if(x<0||y<0||x>300||y>300)
					return;
				
				//点击的图片对应的数组行列下标
				int i=y/W;
				int j=x/W;
				
				//空白块在当前点击图片的上面,当前点击图片上移
				if(blank_x==i-1&&blank_y==j)
				{
					MoveUp();
					repaint();
				}
				//空白块在当前点击图片的下面,当前点击图片下移
				else if(blank_x==i+1&&blank_y==j)
				{
					MoveDown();
					repaint();
				}
				//空白块在当前点击图片的左面,当前点击图片左移
				else if(blank_x==i&&blank_y==j-1)
				{
					MoveLeft();
					repaint();
				}
				//空白块在当前点击图片的右面,当前点击图片右移
				else if(blank_x==i&&blank_y==j+1)
				{
					MoveRight();
					repaint();
				}
				else
					return;
				IsSuccessful();
			}
			
			public void mouseReleased(MouseEvent e) {
				
			}

			public void mouseEntered(MouseEvent e) {
				
			}

			public void mouseExited(MouseEvent e) {
				
			}

			public void actionPerformed(ActionEvent e) {
				
			}
		}
 		
 		//判断是否拼图完成
		//判断拼图是否成功
 		public void IsSuccessful(){
			boolean tag=true;
			for(int i=0;i<N;i++)
			{
				for(int j=0;j<N;j++)
				{
					if(arr[i][j]!=FinalArr[i][j])
					{
						tag=false;
						break;
					}
						
				}
			}
			if(tag)
				JOptionPane.showMessageDialog(null, "恭喜你拼图成功!!共用"+step+"步");
			else
				return;
		}
	
	}

}

源码zip文件网盘链接:https://pan.baidu.com/s/1UG2tddhOus3IOnGrXxYzAA 

提取码:77sz

  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值