Java实现小拼图游戏

今天整理之前的项目,发现了在大二上学期的java课程设计中编写的智能拼图小游戏,觉得有意思,所以打算写篇文章和大伙分享分享。

 

一、项目功能

1)本游戏是一个Java语言的拼图游戏,有一个格子是空的,其他格子内随机放置由要拿来拼图的图片切割成的若干个小图片,图片的切割按照一定的公式计算,用户可以自己选择图片到游戏中,据不同的难度,按照公式会切割成不同的小图片块数(有3*3,4*4,5*5)。

2)在开始游戏之前,可以选择游戏难度后再点击“开始”菜单里的“开始游戏”,进行拼图游戏,通过将空格旁边的小图片移入空格子内(不断的移动方块),来实现拼图,直到方块一行一行的按图片的原始样子拼好即可完成该游戏。

3)游戏进行时,可以点击“图片预览”查看完整图片,以便拼图的方便。

4)游戏拼完后,会弹出一个“信息”框,显示时间和步数。并且可以输入玩家名字。

5)游戏的简单规则在游戏界面的“帮助”菜单内的“游戏规则”信息框内已经简单介绍了。游戏前可以先预览看看。

 

二、设计思路

一)主窗口界面设计

扫描二维码关注公众号,回复: 683729 查看本文章

1、游戏初始界面

当游戏运行时,主窗口界面中包含三个菜单,分别是开始、选择、帮助。主体部分是一个拼图的界面,有9块格子,其中有一块是空白的,状态栏有记录步数和游戏状态的标签。



 

2、游戏运行时

选择好图片后,便可以进行游戏的进行状态。游戏过程中,可以点击“选择”菜单里的“图片预览”菜单项进行完整图片的预览。


         
 
  3、游戏暂停时

当游戏者,在游戏过程中半途暂停游戏的话,将出现游戏暂停状态的界面。当游戏者又想继续游戏时,直接单击界面上的“继续”字样,就可以继续游戏了。



 

4、游戏结束

拼图完成后,会自动弹出已完成的信息提示框。并且在打破记录后会弹出输入玩家姓名的输入框。


    
 
 

(二)主窗口菜单功能

1、“开始”菜单。包括了“开始游戏”、“成绩记录”、“退出游戏”。

开始游戏:单击可以开始游戏;

成绩记录:保存的前三名玩家的成绩,保存在外存的.txt文档里。

退出游戏:退出程序。


    
 
   2、“选择”菜单。包括了“等级”、“游戏图片”、“增加图片”。当运行游戏前,先选择等级和游戏图片。

等级:在游戏者开始游戏之前,要进行游戏等级选择,共有3*3、4*4和5*5三个选择。其图片的切割块数,会根据选择的等级不同,而有所不同。

游戏图片:里面存放了该游戏的游戏图片图,直接选择某个图片名即可选择此图片作为游戏图片。

增加图片:点击该菜单项会弹出文件选择框,选择本地电脑的图片到游戏图片库。


       
 

3、“帮助”菜单。包括了“游戏规则”、“关于我们”。

游戏规则:击查看游戏的简单规则。

关于我们:可查看该游戏的版本、作者等相关信息。

(三)需要用的对话框

1、提示信息框

当游戏者运行游戏时,如果没有把“background”这个文件夹放入主程序的目录下,在运行游戏选择背景图片时,将没有图片可选,若此时直接“开始”->“新游戏”,将会弹出信息框,提示玩家图片不存在。

2、拼图成功后的提示框

当玩家拼图成功后,会弹出提示框告诉玩家所用的时间和步数。

3、成绩记录输入框

当玩家完成游戏后,并且打破前三名的记录时,将会出现一个成绩记录框。

4、前三名成绩显示框

输入成绩后,会弹出前三名玩家的成绩,包括玩家姓名,等级,时间和步数。


  
 
 

(四)功能实现思想

   由于这个是java课程设计,属于团队合作开发的小项目,所以对代码的可移植性以及重复利用性要求较高,为了达到这一目的,需要把不同的功能写成不同的类(.java),再把类似的功能由同一人写,并且放在一个自定义包里。

 

三、功能核心代码

(一)记录坐标的类

//point.java
package Function;
public class point//坐标
{
	int row;//行坐标
	int col;//列坐标
	public point(int r, int c)
	{
		row = r;
		col = c;
	}//构造函数初始化
	public void set(int r, int c)
	{
		row = r;
		col = c;
	}//设置坐标
	public int getRow()
	{
		return row;
	}//获取行坐标
	public int getCol()
	{
		return col;
	}//获取列坐标
	public boolean neighbor(int r, int c)
	{
		int n = Math.abs(row - r) + Math.abs(col - c);
		return n == 1;
	}//判断(r,c)与(row,col)是否相邻,相邻则返回true
}

 (二)分割图片的类

需要将选择的一张图片按照3*3或其他格式进行分割,然后随机摆放在主界面的9个格子中

//Split.java
package PictureOperation;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import Arg.*;
//Singleton class
public class Split
{
	public static final int HARD = 0;
	public static final int NORMAL = 1;
	public static final int EASY = 2;
	public static final String pvo = "png";
	public static final int [] level = {
		72, 90, 120
	};
	private static Split Ob;
	private String filename;
	private String path;
	private Split() {}
	public static Split get()
	{
		if (Ob == null)
			Ob = new Split();
		return Ob;
	}
	public boolean set(String fn)
	{
		filename = fn;
		path = Arg.path + "/" + filename;
		File file = new File(path);
		return file.exists();
	}
	public BufferedImage[][] divid(int type)
	{
		try
		{
			if (filename == null)
				return null;
			BufferedImage image = ImageIO.read(new File(path));
			BufferedImage imagei = new BufferedImage(360, 360,BufferedImage.TYPE_INT_RGB );
			imagei.getGraphics().drawImage(image, 0, 0, 360, 360, null);
			image=imagei;
			int len = level[type];
			int cal = image.getWidth() / len;
			int row = image.getHeight() / len;
			BufferedImage [][] subimage = new BufferedImage[row][cal];
			for (int i = 0; i < row; i++)
				for (int j = 0; j < cal; j++)
					subimage[i][j] = image.getSubimage(j*len,  
i*len, len, len);
			return subimage;
		}
		catch (Exception e)
		{
			return null;
		}
	}
}

 (三)图片交换类

当点击一张图片时,如果它的周围四个位置有一个为空白,则可以移动到空白位,并让该图片位置变成空白。

//Matrix.java
package PictureOperation;
import Function.*;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.ImageIcon;
public class Matrix
{
	private JButton [][] button;
	private JPanel panel;
	private int row;
	private int col;
	private int [][] matrix;
	private GameOver gOver;
	public Matrix(JButton [][] b, JPanel p, int len, GameOver g)
	{
		this.button = b;
		this.panel = p;
		this.gOver = g;
		
		row = b.length;//长
		col = b[0].length;//宽
		
		matrix = new int[row][col];
		matrix[row-1][col-1] = row * col;
		gOver.start(matrix);
		panel.removeAll();
		point pint = new point(row-1, col-1);
		for (int i = 0; i < row; i++)
			for (int j = 0; j < col; j++)
			{
				button[i][j] = new JButton();
				button[i][j].setBounds(j*len, i*len, len, len);
				button[i][j].addActionListener(new ButtonClick(button, pint, matrix, i, j, gOver));
				panel.add(button[i][j]);
			}
	}
	public void init(BufferedImage [][] image)
	{
		if (button == null || image == null)
			return;
		ImageIcon icon;
		int r, c, rad, d, m;
		boolean [] visit = new boolean[row*col-1];
		for (int i = 0; i < row*col - 1; i++)
		{
			r = i / col;
			c = i % col;
			
			rad = (int)(Math.random()*(row*col-1-i));
			for (d = m = 0; d < row*col - 1 && m <= rad; d++)
				if (!visit[d])
					m++;
			matrix[i/col][i%col] = d;
			visit[--d] = true;
			icon = new ImageIcon(image[d/col][d%col]);//分割
			button[i/col][i%col].setIcon(icon);
		}
	}
}

 (四)其他代码

由于博文篇幅太长容易造成大伙的视觉疲劳,所以有兴趣实现的小伙伴可以到附件下载Puzzle_lite.rar。还有就是写这个游戏的时候,学校课程还在C++和Java不断的切换,所以写出来的代码还有点C++的风格,望海涵。

 

四、不足之处

测试过程中发现,有的拼图拼到最后出现有1对板块是对调的,怎么都还原不到完整的顺序,这样的拼图其实是不可还原的拼图。

 

由于我们设计时,是将板块随机打乱,实际上并不是所有随机打乱之后都是可以还原的!确切的说,随机打乱后,有是不可以被还原的。

 

谢谢您的关注和阅读,文章不当之处还请您不吝赐教~~~微笑微笑微笑

 

 

猜你喜欢

转载自bill56.iteye.com/blog/2279259
今日推荐