游戏介绍:
拼图游戏是一款经典的益智游戏,游戏难度分为 简单、正常、困难 三种难度,分别对应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拼图游戏内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
全球理念:假设我想做一个游戏/电影/剪辑。为此,我需要这个(不)简单的动画得到工作。 这个问题的一个例子:我得到了类Screen,它有JFrame的Screen Stuff声明,设置它的配置(大小、关闭操作等),然后创建类Box的对象,显示在框架上。请检查这个类的图像/图表(希望我写的是正确的):ClassesDiagram 现在,class Box扩展了JPanel。我从JPanel继承了方法P
本文向大家介绍Android开发之经典游戏贪吃蛇,包括了Android开发之经典游戏贪吃蛇的使用技巧和注意事项,需要的朋友参考一下 前言 这款游戏实现的思路和源码参考了Google自带的Snake的例子,其中修改了一些个人认为还不够完善的地方,加入了一些新的功能,比如屏幕上的方向操作盘,暂停按钮,开始按钮,退出按钮。另外,为了稍微增加些用户体验,除了游戏的主界面,本人自己新增了5个界面,分别是登陆
你的常用的数据结构都有什么? HashMap和HashSet的区别? 怎么构造一个HashMap HashMap优势是什么? 还有什么需要注意的? 扩容机制,hash冲突? 如果你去设计一个Hash函数怎么设计呢? 一般 HashMap多线程情况下会出现什么问题? 怎么解决扩容死链的? 尾插会有什么问题? 数据错乱问题以外还有什么其他问题? 怎么解决这个问题? councurrentHashMap
本文向大家介绍JavaFx实现拼图游戏,包括了JavaFx实现拼图游戏的使用技巧和注意事项,需要的朋友参考一下 最近学习JavaFx,发现网上大概只有官方文档可以查阅,学习资料较少,写个拼图游戏供记录。。 大概说一下思路: 1.面板的构建:面板采用GridPane,方便3*3的图片布局。 2.每个小格子中的图片当然不是一张张手工切好的,利用imageview.setViewPort(Rectang
本文向大家介绍javascript实现拼图游戏,包括了javascript实现拼图游戏的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了javascript实现拼图游戏的具体代码,供大家参考,具体内容如下 CSS: JS: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
实现拼图游戏的效果,手指移动图片很流畅。 [Code4App.com]