Java游戏开发拼图游戏经典版

游戏介绍:

拼图游戏是一款经典的益智游戏,游戏难度分为 简单、正常、困难 三种难度,分别对应3*3,4*4,5*5布局,游戏开始前图片被随机打乱,空块位于最右下角,玩家通过点击空块周围图片或者按键方式对图片和空块进行相互交换,直到所有图片都回到原位即为游戏胜利。

本次制作的拼图游戏运行界面如下:

使用素材文件夹:

链接: https://pan.baidu.com/s/10qE7yq6IwU-vWprvc5Axgw   提取码: p16e

游戏设计的思路

对拼图界面的图像信息可以采用二维数组map进行存储,数组存储的是图片ID,拼图完成的map数组存储的内容应该为从左到右,从上到下,图片ID顺序为1~8,最右下角的数 组元素存储的图片ID为-1(BLANK_STATE)。所有的移动操作可以简化为对map的移动操作,每次移动完成调用repaint()对图片按ID进行绘画即可。使用文本存储历史记录,每次过关对当前步数和历史记录进行比较和更新。考虑到数组map要求打乱后可以通过移动被还原,所以对数组的打乱必须有所讲究,这里我们采用系统对原有图片执行10000次上下左右按键事件来对图片进行打乱,最后再将空块移动到最右下角,这样图片就顺利地做到了随机打乱。

图片的获取及显示:

先根据关卡level来获取关卡图片,不同的关卡将分成不同数量的小块,假如是简单难度3*3地图,小图片的宽w是大图片的宽的三分之一,小图片的高h是大图片的高的三分之一,第i张图片的左上角起点的x值为图片所在列数*小图片宽(i%3*w),y值为图片所在行数*小图片高(i/3*h):

private void getPics() {

		BufferedImage bufferedImage = null;
		int width = 0,height = 0;
	 try {
	  bufferedImage = ImageIO.read(new File("D:/Game/JigsawGame/pic"+level+".png"));
	  width = bufferedImage.getWidth();
	  height = bufferedImage.getHeight();
	 } catch (IOException e) {
	  e.printStackTrace();
	 }

	 if(level==EASY){

	 	pics = new Image[9];

	 	int w = width/3;
	 	int h = height/3;

	 	for(int i=0;i<8;i++){
	 		int x = i%3*w;
	 		int y = i/3*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}

	 }else if(level==NORMAL){

	 	pics = new Image[16];

	 	int w = width/4;
	 	int h = height/4;

	 	for(int i=0;i<15;i++){
	 		int x = i%4*w;
	 		int y = i/4*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}

	 }else{

	 	pics = new Image[25];

	 	int w = width/5;
	 	int h = height/5;

	 	for(int i=0;i<24;i++){
	 		int x = i%5*w;
	 		int y = i/5*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}

	 }

	}

public void paint(Graphics g){

		g.clearRect(0, 0, this.getWidth(), this.getHeight());

		for(int i=0;i<map.length;i++)
			for(int j=0;j<map.length;j++){	

				if(map[i][j]!=BLANK_STATE){
					//画图
					g.drawImage(pics[map[i][j]-1],leftX+j*W,leftY+i*W,W,W,this);
				}

			}
		}

游戏逻辑

对玩家执行不同的操作进行分别处理:

①当玩家鼠标点击

当玩家鼠标点击的小图片位于空块上下左右方时,点击的小图片与空块交换位置,否则点击无效。

②当玩家按键移动

当空块位于第一行时,moveDown()无效;

当空块位于最后一行时,moveUp()无效;

当空块位于第一列时,moveRight()无效;

当空块位于最后一列时,moveLeft()无效;

此处的moveLeft()指的是小图片移动的方向,也就是空块移动的反方向。鼠标点击事件的移动可以复用按键事件的移动方法,只需要将点击的小图片与数组下标进行转换,再判断下调用哪个方法即可。

public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub

		int x = e.getX()-leftX;
		int y = e.getY()-leftY;

		if(x<0||y<0||x>600||y>600){//超出地图范围
			return ;
		}

		//存储数组行列下标
		int i = y/W;
		int j = x/W;

		if(blank_x == i-1&&blank_y == j){//空块在当前点击块的上侧
			moveUp();
		}else if(blank_x == i+1&&blank_y == j){//空块在当前点击块的下侧
			moveDown();
		}else if(blank_x == i&&blank_y == j-1){//空块在当前点击块的左侧
			moveLeft();
		}else if(blank_x == i&&blank_y == j+1){//空块在当前点击块的右侧
			moveRight();
		}else{
			return ;
		}

		repaint();

		isWin();		

	}

public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		if(e.getKeyCode() == KeyEvent.VK_UP&&blank_x!=level+1){//上
			moveUp();
		}else if(e.getKeyCode() == KeyEvent.VK_DOWN&&blank_x!=0){//下
			moveDown();
		}else if(e.getKeyCode() == KeyEvent.VK_LEFT&&blank_y!=level+1){//左
			moveLeft();
		}else if(e.getKeyCode() == KeyEvent.VK_RIGHT&&blank_y!=0){//右
			moveRight();
		}else{
			return ;
		}

		repaint();
	 isWin();

	}

小图片的移动

交换小图片与空块的值,并对空块的数组下标重新赋值:

	//空块与上一格交换
 private void moveDown(){

		map[blank_x][blank_y] = map[blank_x-1][blank_y];
		map[blank_x-1][blank_y] = BLANK_STATE;
		blank_x = blank_x-1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	//空块与下一格交换
private void moveUp(){

		map[blank_x][blank_y] = map[blank_x+1][blank_y];
		map[blank_x+1][blank_y] = BLANK_STATE;
		blank_x = blank_x+1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	//空块与左一格交换
private void moveRight(){

		map[blank_x][blank_y] = map[blank_x][blank_y-1];
		map[blank_x][blank_y-1] = BLANK_STATE;
		blank_y = blank_y-1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	//空块与右一格交换
private void moveLeft(){

		map[blank_x][blank_y] = map[blank_x][blank_y+1];
		map[blank_x][blank_y+1] = BLANK_STATE;
		blank_y = blank_y+1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

打乱地图信息

使用Math.Random()获取随机值,各个方向按键事件的概率是1/4,当符合条件时执行移动方法并且移动次数+1,移动10000次实现随机打乱地图。

private void RandomTheMap() {

		int i =0;

		//尝试移动一万次
		while(i<10000){
			int rate = (int) (Math.random()*100);
			if(rate<25&&blank_x!=level+1){
				moveUp();
				i++;
			}else if(rate<50&&blank_x!=0){
				moveDown();
				i++;
			}else if(rate<75&&blank_y!=level+1){
				moveLeft();
				i++;
			}else if(rate<100&&blank_y!=0){
				moveRight();
				i++;
			}
		}

		//再将空块移动到最右下角

		while(blank_x<level+1){
			moveUp();
		}

		while(blank_y<level+1){
			moveLeft();
		}

		step=0;
	}

判断输赢

将现有map信息与正确的map信息一一对比,如果都相等,过关,比较当前记录和历史记录,如果刷新历史记录进行记录的更新,然后询问是否开始下一关。如果开始下一关,进行level++并对地图及面板信息进行初始化:

private void isWin() {

		boolean flag = true;

		for(int i=0;i<successMap.length;i++){
			for(int j=0;j<successMap.length;j++){
				if(map[i][j] != successMap[i][j]){
					flag = false;
					break;
				}
			}
		}

		if(flag){
			String msg;
			int type;
			int choice;
			int record;
			String title;
			switch(level){//通关,是否进入下一关
			case EASY:
					this.removeKeyListener(this);
					this.removeMouseListener(this);
					record = mapUtil.getRecord(level);//历史记录
					if(step<record){
						msg = "恭喜你通过简单关卡并刷新历史记录,完成步数是"+step+"\n历史记录是"+record+",是否要进入下一关?";
						mapUtil.writeRecord(level, step);//更新历史记录
					}else{
						msg = "恭喜你通过简单关卡,完成步数是"+step+"\n是否要进入下一关?";
					}
					type = JOptionPane.YES_NO_OPTION;
					title = "过关";
					choice = 0;
					choice = JOptionPane.showConfirmDialog(null, msg,title,type);
					if(choice==1){
						System.exit(0);
					}else if(choice == 0){
						level++;
						map = mapUtil.getMap(level);
						successMap = mapUtil.getMap(level);
						record = mapUtil.getRecord(level);//获取正常难度的历史记录
						initializeMap();//初始化地图相关变量信息
						RandomTheMap();//打乱图案顺序
						step = 0;
						HelpPanel.histotyStep.setText(record+"");
						HelpPanel.panelCenter.setSuccessPic(level);
						HelpPanel.nowLevel.setText("正常");
						HelpPanel.nowStep.setText(step+"");
						getPics();
						this.addKeyListener(this);
						this.addMouseListener(this);
						repaint();
					}
				;break;
			case NORMAL:
				this.removeKeyListener(this);
				this.removeMouseListener(this);
				record = mapUtil.getRecord(level);//历史记录
				if(step<record){
					msg = "恭喜你通过正常关卡并刷新历史记录,完成步数是"+step+"\n历史记录是"+record+",是否要进入下一关?";
					mapUtil.writeRecord(level, step);//更新历史记录
				}else{
					msg = "恭喜你通过正常关卡,完成步数是"+step+"\n是否要进入下一关?";
				}
					type = JOptionPane.YES_NO_OPTION;
					title = "过关";
					choice = 0;
					choice = JOptionPane.showConfirmDialog(null, msg,title,type);
					if(choice==1){
						System.exit(0);
					}else if(choice == 0){
						level++;
						map = mapUtil.getMap(level);
						successMap = mapUtil.getMap(level);
						initializeMap();//初始化地图相关变量信息
						RandomTheMap();//打乱图案顺序
						getPics();
						step = 0;
						record = mapUtil.getRecord(level);//获取困难难度的历史记录。
						HelpPanel.histotyStep.setText(record+"");
						HelpPanel.panelCenter.setSuccessPic(level);
						HelpPanel.nowStep.setText(step+"");
						HelpPanel.nowLevel.setText("困难");
						this.addKeyListener(this);
						this.addMouseListener(this);
						repaint();
					}
				;break;
			case HARD:
				this.removeKeyListener(this);
				this.removeMouseListener(this);
				record = mapUtil.getRecord(level);//历史记录
				if(step<record){
					msg = "恭喜你通过困难关卡并刷新历史记录,完成步数是"+step+"\n历史记录是"+record;
					JOptionPane.showMessageDialog(this, msg);
					mapUtil.writeRecord(level, step);//更新历史记录
				}else{
					msg = "恭喜通过困难关卡,完成步数是"+step;
					JOptionPane.showMessageDialog(this, msg);
				}
				;break;
			}

		}

	}

历史记录的读写

采用文本形式对记录进行保存,初始情况下,读取记录的时候如果没有记录文件进行文件的新建并初始所有历史记录为9999步;记录的保存采用两个逗号对三个关卡的历史记录进行分割,读取后进行array.split(",")分割操作;写入时,先清空原有文本信息,再将记录合成字符串写入文件。

//获取关卡历史记录
	public int getRecord(int level){
		File file = new File("D://GameRecordAboutSwing");

		if(!file.exists()){
			file.mkdirs();
		}
		File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");

		try{
		if(!record.exists()){//如果不存在,新建文本
			record.createNewFile();
			fos = new FileOutputStream(record);
			dos = new DataOutputStream(fos);
			String s = "9999,9999,9999";
			dos.writeBytes(s);
			System.out.println(record.isFile());;
		}
		//读取记录
		fis = new FileInputStream(record);
		dis = new DataInputStream(fis);
		String str = dis.readLine();
		array = str.split(",");

		}catch(Exception e){
			e.printStackTrace();
		}finally{
			 try {
					if(fis!=null)
					 fis.close();
					if(dis!=null)
					 dis.close();
					if(fos!=null)
			 	 fos.close();
					if(dos!=null)
					 dos.close();
			 } catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}

		return Integer.parseInt(array[level-1]);
	}

	//更新关卡历史记录
	public void writeRecord(int level,int step){
		File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");

		try {
			//清空原有记录
			FileWriter fileWriter =new FileWriter(record);
	 fileWriter.write("");
			fileWriter.flush();
			fileWriter.close();
	 //重新写入文本
			fos = new FileOutputStream(record);
			dos = new DataOutputStream(fos);
			array[level-1] = step+"";
			String s = array[0]+","+array[1]+","+array[2];
			dos.writeBytes(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
		 try {
				if(fos!=null)
		 	 fos.close();
				if(dos!=null)
				 dos.close();
		 } catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

到这里核心的游戏逻辑及游戏面板的相关内容已经说明完了,涉及辅助面板类的东西会有些错综复杂,这里就不详细介绍了。

完整源码如下:

MapUtil类:

package 人物拼图;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

public class MapUtil {

	int[][] map;
	FileInputStream fis = null;
	FileOutputStream fos = null;
	DataInputStream dis = null;
	DataOutputStream dos = null;
	String array[] = null;

	int level = 1;

	public static final int EASY = 1,NORMAL = 2,HARD = 3,BLANK_STATE = -1;

	public int[][] getMap(int level){
		switch(level){
		case EASY:
			map = new int[3][3];
			for(int i=0;i<3;i++)
				for(int j=0;j<3;j++){
					map[i][j] = 3*i+j+1;
				}
			map[2][2] = BLANK_STATE;
		;break;
		case NORMAL:
			map=new int[4][4];
			for(int i=0;i<4;i++)
				for(int j=0;j<4;j++){
					map[i][j] = 4*i+j+1;
				}
			map[3][3] = BLANK_STATE;
		break;
		case HARD:
			map=new int[5][5];
			for(int i=0;i<5;i++)
				for(int j=0;j<5;j++){
					map[i][j] = 5*i+j+1;
				}
			map[4][4] = BLANK_STATE;
			break;
		}
		return map;
	}

	//获取关卡历史记录
	public int getRecord(int level){
		File file = new File("D://GameRecordAboutSwing");

		if(!file.exists()){
			file.mkdirs();
		}
		File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");

		try{
		if(!record.exists()){//如果不存在,新建文本
			record.createNewFile();
			fos = new FileOutputStream(record);
			dos = new DataOutputStream(fos);
			String s = "9999,9999,9999";
			dos.writeBytes(s);
			System.out.println(record.isFile());;
		}
		//读取记录
		fis = new FileInputStream(record);
		dis = new DataInputStream(fis);
		String str = dis.readLine();
		array = str.split(",");

		}catch(Exception e){
			e.printStackTrace();
		}finally{
			 try {
					if(fis!=null)
					 fis.close();
					if(dis!=null)
					 dis.close();
					if(fos!=null)
			 	 fos.close();
					if(dos!=null)
					 dos.close();
			 } catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}

		return Integer.parseInt(array[level-1]);
	}

	//更新关卡历史记录
	public void writeRecord(int level,int step){
		File record = new File("D://GameRecordAboutSwing/recordJigsawGame.txt");

		try {
			//清空原有记录
			FileWriter fileWriter =new FileWriter(record);
	 fileWriter.write("");
			fileWriter.flush();
			fileWriter.close();
	 //重新写入文本
			fos = new FileOutputStream(record);
			dos = new DataOutputStream(fos);
			array[level-1] = step+"";
			String s = array[0]+","+array[1]+","+array[2];
			dos.writeBytes(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
		 try {
				if(fos!=null)
		 	 fos.close();
				if(dos!=null)
				 dos.close();
		 } catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

}

MapUtil类主要用做对地图数组信息的初始化以及历史记录的读写。

GamePanel类

package 人物拼图;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements ActionListener ,MouseListener,KeyListener{

	Image pics[];
	int leftX=50,leftY=50;
	int level,W;
	int[][] map;
	int[][] successMap;//最后结果
	int blank_x,blank_y;//记录空白块的数组下标
	int step = 0;
	MapUtil mapUtil = new MapUtil();
	int record;//存储当前关卡记录
	public static final int EASY = 1,NORMAL = 2,HARD = 3,BLANK_STATE = -1;

	public GamePanel(int level){
		setSize(600, 600);
		this.level = level;
		map = mapUtil.getMap(level);
		successMap = mapUtil.getMap(level);
		initializeMap();//初始化地图相关变量信息
		RandomTheMap();//打乱图案顺序
		this.setVisible(true);
		this.addKeyListener(this);
		this.addMouseListener(this);
		this.setFocusable(true);
		getPics();
		record = mapUtil.getRecord(level);
		HelpPanel.histotyStep.setText(record+"");
		HelpPanel.nowStep.setText(step+"");
		repaint();
	}

	public void paint(Graphics g){

		g.clearRect(0, 0, this.getWidth(), this.getHeight());

		for(int i=0;i<map.length;i++)
			for(int j=0;j<map.length;j++){	

				if(map[i][j]!=BLANK_STATE){
					//画图
					g.drawImage(pics[map[i][j]-1],leftX+j*W,leftY+i*W,W,W,this);
				}

			}
		}

	private void initializeMap(){
		switch(level){
		case EASY:
			blank_x=2;blank_y=2;
			W = 200;
			;break;
		case NORMAL:
			blank_x=3;blank_y=3;
			W = 150;
			;break;
		case HARD:
			blank_x=4;blank_y=4;
			W = 120;
			;break;
		}
	}

	private void RandomTheMap() {

		int i =0;

		//尝试移动一万次
		while(i<10000){
			int rate = (int) (Math.random()*100);
			if(rate<25&&blank_x!=level+1){
				moveUp();
				i++;
			}else if(rate<50&&blank_x!=0){
				moveDown();
				i++;
			}else if(rate<75&&blank_y!=level+1){
				moveLeft();
				i++;
			}else if(rate<100&&blank_y!=0){
				moveRight();
				i++;
			}
		}

		//再将空块移动到最右下角

		while(blank_x<level+1){
			moveUp();
		}

		while(blank_y<level+1){
			moveLeft();
		}

		step=0;
	}

	//空块与上一格交换
	private void moveDown(){

		map[blank_x][blank_y] = map[blank_x-1][blank_y];
		map[blank_x-1][blank_y] = BLANK_STATE;
		blank_x = blank_x-1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	//空块与下一格交换
	private void moveUp(){

		map[blank_x][blank_y] = map[blank_x+1][blank_y];
		map[blank_x+1][blank_y] = BLANK_STATE;
		blank_x = blank_x+1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	//空块与左一格交换
	private void moveRight(){

		map[blank_x][blank_y] = map[blank_x][blank_y-1];
		map[blank_x][blank_y-1] = BLANK_STATE;
		blank_y = blank_y-1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	//空块与右一格交换
	private void moveLeft(){

		map[blank_x][blank_y] = map[blank_x][blank_y+1];
		map[blank_x][blank_y+1] = BLANK_STATE;
		blank_y = blank_y+1;
		step++;
		HelpPanel.nowStep.setText(step+"");
	}

	private void getPics() {

		BufferedImage bufferedImage = null;
		int width = 0,height = 0;
	 try {
	  bufferedImage = ImageIO.read(new File("D:/Game/JigsawGame/pic"+level+".png"));
	  width = bufferedImage.getWidth();
	  height = bufferedImage.getHeight();
	 } catch (IOException e) {
	  e.printStackTrace();
	 }

	 if(level==EASY){

	 	pics = new Image[9];

	 	int w = width/3;
	 	int h = height/3;

	 	for(int i=0;i<8;i++){
	 		int x = i%3*w;
	 		int y = i/3*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}

	 }else if(level==NORMAL){

	 	pics = new Image[16];

	 	int w = width/4;
	 	int h = height/4;

	 	for(int i=0;i<15;i++){
	 		int x = i%4*w;
	 		int y = i/4*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}

	 }else{

	 	pics = new Image[25];

	 	int w = width/5;
	 	int h = height/5;

	 	for(int i=0;i<24;i++){
	 		int x = i%5*w;
	 		int y = i/5*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}

	 }

	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		if(e.getKeyCode() == KeyEvent.VK_UP&&blank_x!=level+1){//上
			moveUp();
		}else if(e.getKeyCode() == KeyEvent.VK_DOWN&&blank_x!=0){//下
			moveDown();
		}else if(e.getKeyCode() == KeyEvent.VK_LEFT&&blank_y!=level+1){//左
			moveLeft();
		}else if(e.getKeyCode() == KeyEvent.VK_RIGHT&&blank_y!=0){//右
			moveRight();
		}else{
			return ;
		}

		repaint();
		isWin();

	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub

		int x = e.getX()-leftX;
		int y = e.getY()-leftY;

		if(x<0||y<0||x>600||y>600){//超出地图范围
			return ;
		}

		//存储数组行列下标
		int i = y/W;
		int j = x/W;

		if(blank_x == i-1&&blank_y == j){//空块在当前点击块的上侧
			moveUp();
		}else if(blank_x == i+1&&blank_y == j){//空块在当前点击块的下侧
			moveDown();
		}else if(blank_x == i&&blank_y == j-1){//空块在当前点击块的左侧
			moveLeft();
		}else if(blank_x == i&&blank_y == j+1){//空块在当前点击块的右侧
			moveRight();
		}else{
			return ;
		}

		repaint();

		isWin();		

	}

	private void isWin() {

		boolean flag = true;

		for(int i=0;i<successMap.length;i++){
			for(int j=0;j<successMap.length;j++){
				if(map[i][j] != successMap[i][j]){
					flag = false;
					break;
				}
			}
		}

		if(flag){
			String msg;
			int type;
			int choice;
			int record;
			String title;
			switch(level){//通关,是否进入下一关
			case EASY:
					this.removeKeyListener(this);
					this.removeMouseListener(this);
					record = mapUtil.getRecord(level);//历史记录
					if(step<record){
						msg = "恭喜你通过简单关卡并刷新历史记录,完成步数是"+step+"\n历史记录是"+record+",是否要进入下一关?";
						mapUtil.writeRecord(level, step);//更新历史记录
					}else{
						msg = "恭喜你通过简单关卡,完成步数是"+step+"\n是否要进入下一关?";
					}
					type = JOptionPane.YES_NO_OPTION;
					title = "过关";
					choice = 0;
					choice = JOptionPane.showConfirmDialog(null, msg,title,type);
					if(choice==1){
						System.exit(0);
					}else if(choice == 0){
						level++;
						map = mapUtil.getMap(level);
						successMap = mapUtil.getMap(level);
						record = mapUtil.getRecord(level);//获取正常难度的历史记录
						initializeMap();//初始化地图相关变量信息
						RandomTheMap();//打乱图案顺序
						step = 0;
						HelpPanel.histotyStep.setText(record+"");
						HelpPanel.panelCenter.setSuccessPic(level);
						HelpPanel.nowLevel.setText("正常");
						HelpPanel.nowStep.setText(step+"");
						getPics();
						this.addKeyListener(this);
						this.addMouseListener(this);
						repaint();
					}
				;break;
			case NORMAL:
				this.removeKeyListener(this);
				this.removeMouseListener(this);
				record = mapUtil.getRecord(level);//历史记录
				if(step<record){
					msg = "恭喜你通过正常关卡并刷新历史记录,完成步数是"+step+"\n历史记录是"+record+",是否要进入下一关?";
					mapUtil.writeRecord(level, step);//更新历史记录
				}else{
					msg = "恭喜你通过正常关卡,完成步数是"+step+"\n是否要进入下一关?";
				}
					type = JOptionPane.YES_NO_OPTION;
					title = "过关";
					choice = 0;
					choice = JOptionPane.showConfirmDialog(null, msg,title,type);
					if(choice==1){
						System.exit(0);
					}else if(choice == 0){
						level++;
						map = mapUtil.getMap(level);
						successMap = mapUtil.getMap(level);
						initializeMap();//初始化地图相关变量信息
						RandomTheMap();//打乱图案顺序
						getPics();
						step = 0;
						record = mapUtil.getRecord(level);//获取困难难度的历史记录。
						HelpPanel.histotyStep.setText(record+"");
						HelpPanel.panelCenter.setSuccessPic(level);
						HelpPanel.nowStep.setText(step+"");
						HelpPanel.nowLevel.setText("困难");
						this.addKeyListener(this);
						this.addMouseListener(this);
						repaint();
					}
				;break;
			case HARD:
				this.removeKeyListener(this);
				this.removeMouseListener(this);
				record = mapUtil.getRecord(level);//历史记录
				if(step<record){
					msg = "恭喜你通过困难关卡并刷新历史记录,完成步数是"+step+"\n历史记录是"+record;
					JOptionPane.showMessageDialog(this, msg);
					mapUtil.writeRecord(level, step);//更新历史记录
				}else{
					msg = "恭喜通过困难关卡,完成步数是"+step;
					JOptionPane.showMessageDialog(this, msg);
				}
				;break;
			}

		}

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub

	}

}

GamePanel类主要涉及游戏面板的小图片的读取和显示,以及全部游戏的逻辑。

SuccessPanel类:

package 人物拼图;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class SuccessPanel extends JPanel{

	int level;
	Image[] pics;
	int[][] map;
	int W ;
	MapUtil mapUtil;
	private int leftX=10;
	private int leftY=150;

	public static final int EASY=1,NORMAL=2,HARD=3,BLANK_STATE=-1;

	public SuccessPanel(int level){
		setSuccessPic(level);
	}

	public void setSuccessPic(int level) {

		mapUtil = new MapUtil();
		this.level = level;

		BufferedImage bufferedImage = null;
		int width = 0,height = 0;
	 try {
	  bufferedImage = ImageIO.read(new File("D:/Game/JigsawGame/pic"+level+".png"));
	  width = bufferedImage.getWidth();
	  height = bufferedImage.getHeight();
	 } catch (IOException e) {
	  e.printStackTrace();
	 }

		if(level == EASY){
			pics = new Image[9];
			map = mapUtil.getMap(level);
			W = 40;

	 	int w = width/3;
	 	int h = height/3;

	 	for(int i=0;i<8;i++){
	 		int x = i%3*w;
	 		int y = i/3*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}
		}else if(level == NORMAL){
			pics = new Image[16];
			map = mapUtil.getMap(level);
			W = 30;

	 	int w = width/4;
	 	int h = height/4;

	 	for(int i=0;i<15;i++){
	 		int x = i%4*w;
	 		int y = i/4*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}
		}else{
			pics = new Image[25];
			map = mapUtil.getMap(level);
			W = 24;

			int w = width/5;
	 	int h = height/5;

	 	for(int i=0;i<24;i++){
	 		int x = i%5*w;
	 		int y = i/5*h;
	 		pics[i] = bufferedImage.getSubimage(x, y, w, h);
	 	}
		}

		repaint();
	}

	public void paint(Graphics g){

		for(int i=0;i<map.length;i++)
			for(int j=0;j<map.length;j++){	

				if(map[i][j]!=BLANK_STATE){
					//画图
					g.drawImage(pics[map[i][j]-1],leftX+j*W,leftY+i*W,W,W,this);
				}

			}
	}

}

SuccessPanel类负责游戏运行界面右下角完整拼图顺序的小图片显示;

HelpPanel类:

package 人物拼图;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

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

public class HelpPanel extends JPanel {

	private int level = 1;
	public static final int EASY = 1,NORMAL = 2,HARD = 3,BLANK_STATE = -1;
	static JLabel nowStep = new JLabel("0");
	static JLabel histotyStep = new JLabel("9999");
	static JLabel nowLevel = new JLabel();
	JLabel levelLabel = new JLabel("当前难度:");
	JLabel nowStepLabel = new JLabel("当前步数:");
	JLabel historyStepLabel = new JLabel("历史记录:");
	JButton button1 = new JButton("退出");
	BorderLayout panel1 = new BorderLayout();//右侧
	JPanel panelNorth = new JPanel(new GridLayout(4,2,10,30));
	static SuccessPanel panelCenter = new SuccessPanel(1);

	public HelpPanel(int level){
		setLevel(level);
		this.setVisible(true);
		this.setLayout(new BorderLayout());//当前面板

		panelNorth.add(levelLabel);
		panelNorth.add(nowLevel);
		panelNorth.add(nowStepLabel);
		panelNorth.add(nowStep);
		panelNorth.add(historyStepLabel);
		panelNorth.add(histotyStep);//历史记录
		panelNorth.add(button1);

		this.add(panelNorth,BorderLayout.NORTH);
		this.add(panelCenter,BorderLayout.CENTER);

		button1.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				System.exit(1);
			}
		});;
	}

	public void setLevel(int level){
		this.level = level;
		panelCenter.setSuccessPic(level);
		if(level == EASY){
		 	nowLevel.setText("简单");
		}else if(level == NORMAL){
		 	nowLevel.setText("正常");
		}else{
		 	nowLevel.setText("困难");
		}

	}

}

HelpPanel类负责游戏运行界面右边辅助面板的显示,其中装载了SuccessPanel;

GameClient类:

package 人物拼图;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

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

public class GameClient extends JFrame{

	GamePanel panel2;

	public GameClient(){

		HelpPanel panel = new HelpPanel(1);
		panel2 = new GamePanel(1);//难度简单
		panel2.setLayout(new BorderLayout());

		this.getContentPane().setLayout(new BorderLayout());
		this.getContentPane().add(panel,BorderLayout.EAST);
		this.getContentPane().add(panel2,BorderLayout.CENTER);
		this.setSize(850,750);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setTitle("人物拼图游戏");
		this.setVisible(true);

	}

	public static void main(String[] args) {
		new GameClient();
	}

}

GameClient类是游戏窗口类,装载了游戏面板和辅助面板,用来开始游戏。

源码已经粘贴完毕,最后再展示两张游戏运行截图:

到此这篇关于Java游戏开发拼图游戏经典版的文章就介绍到这了,更多相关Java拼图游戏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaFx实现拼图游戏

    最近学习JavaFx,发现网上大概只有官方文档可以查阅,学习资料较少,写个拼图游戏供记录.. 大概说一下思路: 1.面板的构建:面板采用GridPane,方便3*3的图片布局. 2.每个小格子中的图片当然不是一张张手工切好的,利用imageview.setViewPort(Rectangle2D 2d)的方法进行切割. 3.再来说鼠标点击时图片的移动,这时候以里面的空格子为中心,不以鼠标点击的那个事件源为中心,这样可以避免走弯路(当时我是有一种柳暗花明的感觉.). 4.鼠标点击后空格子和其周围带

  • java实现拼图游戏

    本文实例为大家分享了java实现拼图游戏的具体代码,供大家参考,具体内容如下 游戏说明: 设计一款拼图游戏,要求点击图片按钮,实现图片按钮的移动,直到每一个按钮都到达指定位置游戏终止退出. 游戏设计思路: 1.准备一张图像文件: 2.创建N个按钮图标,每个按钮图标里面存入一张分割后的图片信息: 3.创建一个空白按钮用于和图标按钮交换位置,达到移动的效果: 4.乱序,将按钮图标乱序,完成游戏效果: 5.创建一个面板添加游戏开始和游戏结束按钮: 6.设计游戏窗口: 游戏界面设计基本结构: 代码实现:

  • Java 小游戏开发之俄罗斯方块

    Java项目 俄罗斯方块 一.心得 二.游戏实例 游戏截图 目录结构 三.代码 1.主界面 Tetris.java package com.fry.tetris; import java.util.Arrays; import java.util.Random; /** * 4格方块 */ public class Tetromino { protected Cell[] cells = new Cell[4]; /** 保存旋转的相对于轴位置状态 */ protected State[] st

  • Java制作智能拼图游戏原理及代码

    今天突发奇想,想做一个智能拼图游戏来给哄女友. 需要实现这些功能 第一图片自定义 第二宫格自定义,当然我一开始就想的是3*3 4*4 5*5,没有使用3*5这样的宫格. 第三要实现自动拼图的功能,相信大家知道女人耍游戏都不是很厉害,所以这个自动拼图功能得有. 其他什么暂停.排行就不写了! 现在重点问题出来了 要实现自动拼图功能似乎要求有点高哦!计算机有可不能像人一样只能: 先追究下本质 拼图游戏其实就是排列问题: 排列有这么一个定义:在一个1,2,...,n的排列中,如果一对数的前后位置与大小顺

  • java实现简单美女拼图游戏

    拼图小游戏,学习阶段.很多不足,改进了一下 演示图片: J_Puzzle.java import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.a

  • Java游戏开发拼图游戏经典版

    游戏介绍: 拼图游戏是一款经典的益智游戏,游戏难度分为 简单.正常.困难 三种难度,分别对应3*3,4*4,5*5布局,游戏开始前图片被随机打乱,空块位于最右下角,玩家通过点击空块周围图片或者按键方式对图片和空块进行相互交换,直到所有图片都回到原位即为游戏胜利. 本次制作的拼图游戏运行界面如下: 使用素材文件夹: 链接: https://pan.baidu.com/s/10qE7yq6IwU-vWprvc5Axgw   提取码: p16e 游戏设计的思路 对拼图界面的图像信息可以采用二维数组ma

  • Java实现Android拼图游戏设计过程解析

    目录 1.项目介绍 2.项目原理 3.项目设计 4.项目实现 5.获取布局 6.准备图片 7.初始化item 8.游戏图片的切换 9.游戏胜利的判断 10.游戏封面 1.项目介绍 这是一款基于 Java 开发的移动端安卓小游戏——大家来拼图 2.项目原理 把选定的一张图片切分很多份,先是 33 格式,在一定的时间内点击格子交换使图形拼成一张完整的图片就算闯关成功,这样关卡也很容易设计,33:44:55:6*6: 3.项目设计 我们需要一个容器,可以放这些图片的块块,为了方便,我们准备使用Rela

  • IOS游戏开发之五子棋OC版

    先上效果图 - 功能展示 - 初高级棋盘切换效果 实现思路及主要代码详解 1.绘制棋盘 利用Quartz2D绘制棋盘.代码如下 - (void)drawBackground:(CGSize)size{ self.gridWidth = (size.width - 2 * kBoardSpace) / self.gridCount; //1.开启图像上下文 UIGraphicsBeginImageContext(size); //2.获取上下文 CGContextRef ctx = UIGraph

  • java控制台实现拼图游戏

    本文实例为大家分享了java控制台实现拼图游戏的具体代码,供大家参考,具体内容如下 1.首先对原始的拼图进行多次无规律的移动,将拼图打乱 2.然后进行游戏,在游戏移动同时对拼图顺序进行判断 ①如果拼图成功,则跳出循环,结束游戏: ②如果拼图失败,陷入死循环,继续移动拼图,直至拼图成功为止. import java.util.Random; import java.util.Scanner; public class GrameOfPingTuTest{ private static Scanne

  • java实现九宫格拼图游戏

    本文实例为大家分享了java实现九宫格拼图游戏的具体代码,供大家参考,具体内容如下 设计步骤: 先将框架构思出来,首先将拼图游戏的雏形实现,即一个界面,九个按钮,按钮上的图片显示出自己想要的图片. (1)其次构思移动版块的问题,想到按钮直接互换是极为麻烦的一件事,所以采用更换按钮上的图片.按钮类上有两个属性,a[9]表示按钮的位置,b[9]表示按钮上图片的编号, 空白快图片编号为8标记,点击按钮之后,点击事件得到点击的块数在哪(1-9),if -else判断相邻是否为标记的空白快.方法简单但是代

  • Java实现简易拼图游戏的方法详解

    目录 效果展示 游戏结构 实现代码 效果展示 介绍:游戏共有五张图片可以选择,分成了4 X 4 十六个方格,点击开始就可以开始游戏.游戏运行的截图如下: 游戏结构 实现代码 代码如下:MedleyGame.java类 package game.medleyPicture; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.even

  • javascript游戏开发之《三国志曹操传》零部件开发(三)情景对话中仿打字机输出文字

    前两讲我告诉了大家如何使人物移动,那么今天我们就来看看如何实现仿<三国志曹操传>人物情景对话.具体的链接我写在下方. 一.前言 相信大家都还记得吧,在某些新闻里会有一些惨不忍睹的结果是用像打字机一样的方式把文字弄出来.那么今天的主要目的就是要办到这个. 就在9月5日的时候,我在办公室里起了个做这种程序的念头,并且有了点思路.我首先想用调margin的方法,按理说是作出来了,但很不让人满意,毕竟很麻烦,并且技术也差.所以我打算用上数组和循环.9月13日我抽空写出来了,但由于这几天很忙,基本上在工

  • 经典再现 基于JAVA平台开发坦克大战游戏

    一.需求描述  1.功能性需求 在功能需求分析阶段,我们的主要任务是指定系统必须提供哪些服务,定义软件完成哪些功能,提供给那些人使用,功能需求是软件开发的一项基本需求,是需求分析必不可少的一部分.坦克大战是一款经典游戏了,本游戏学习了一些前辈们的经验,整体来说讲,游戏分为敌我双方,主要参与战斗的坦克有玩家控制,敌人坦克可以智能随机出现在屏幕上,并且移动,发射一定数量的子弹:玩家可以在规定的区域内随意移动坦克,当有子弹击中玩家时,玩家死亡,游戏结束:敌人坦克智能运行,敌方坦克由于需要具有一定智能性

  • 基于javascript制作经典传统的拼图游戏

    本文实例为大家分享了javascript制作经典传统的拼图游戏的关键代码,供大家参考,具体内容如下 效果图: 拼出你喜欢的白雪公主和七个小矮人 实现代码: <!DOCTYPE html> <html> <head> <title>pingtu.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

随机推荐