Java游戲開發(fā)拼圖游戲經(jīng)典版
游戲介紹:
拼圖游戲是一款經(jīng)典的益智游戲,游戲難度分為 簡單、正常、困難 三種難度,分別對(duì)應(yīng)3*3,4*4,5*5布局,游戲開始前圖片被隨機(jī)打亂,空塊位于最右下角,玩家通過點(diǎn)擊空塊周圍圖片或者按鍵方式對(duì)圖片和空塊進(jìn)行相互交換,直到所有圖片都回到原位即為游戲勝利。
本次制作的拼圖游戲運(yùn)行界面如下:
使用素材文件夾:
鏈接: https://pan.baidu.com/s/10qE7yq6IwU-vWprvc5Axgw 提取碼: p16e
游戲設(shè)計(jì)的思路
對(duì)拼圖界面的圖像信息可以采用二維數(shù)組map進(jìn)行存儲(chǔ),數(shù)組存儲(chǔ)的是圖片ID,拼圖完成的map數(shù)組存儲(chǔ)的內(nèi)容應(yīng)該為從左到右,從上到下,圖片ID順序?yàn)?~8,最右下角的數(shù) 組元素存儲(chǔ)的圖片ID為-1(BLANK_STATE)。所有的移動(dòng)操作可以簡化為對(duì)map的移動(dòng)操作,每次移動(dòng)完成調(diào)用repaint()對(duì)圖片按ID進(jìn)行繪畫即可。使用文本存儲(chǔ)歷史記錄,每次過關(guān)對(duì)當(dāng)前步數(shù)和歷史記錄進(jìn)行比較和更新??紤]到數(shù)組map要求打亂后可以通過移動(dòng)被還原,所以對(duì)數(shù)組的打亂必須有所講究,這里我們采用系統(tǒng)對(duì)原有圖片執(zhí)行10000次上下左右按鍵事件來對(duì)圖片進(jìn)行打亂,最后再將空塊移動(dòng)到最右下角,這樣圖片就順利地做到了隨機(jī)打亂。
圖片的獲取及顯示:
先根據(jù)關(guān)卡level來獲取關(guān)卡圖片,不同的關(guān)卡將分成不同數(shù)量的小塊,假如是簡單難度3*3地圖,小圖片的寬w是大圖片的寬的三分之一,小圖片的高h(yuǎn)是大圖片的高的三分之一,第i張圖片的左上角起點(diǎn)的x值為圖片所在列數(shù)*小圖片寬(i%3*w),y值為圖片所在行數(shù)*小圖片高(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); } } }
游戲邏輯
對(duì)玩家執(zhí)行不同的操作進(jìn)行分別處理:
①當(dāng)玩家鼠標(biāo)點(diǎn)擊
當(dāng)玩家鼠標(biāo)點(diǎn)擊的小圖片位于空塊上下左右方時(shí),點(diǎn)擊的小圖片與空塊交換位置,否則點(diǎn)擊無效。
②當(dāng)玩家按鍵移動(dòng)
當(dāng)空塊位于第一行時(shí),moveDown()無效;
當(dāng)空塊位于最后一行時(shí),moveUp()無效;
當(dāng)空塊位于第一列時(shí),moveRight()無效;
當(dāng)空塊位于最后一列時(shí),moveLeft()無效;
此處的moveLeft()指的是小圖片移動(dòng)的方向,也就是空塊移動(dòng)的反方向。鼠標(biāo)點(diǎn)擊事件的移動(dòng)可以復(fù)用按鍵事件的移動(dòng)方法,只需要將點(diǎn)擊的小圖片與數(shù)組下標(biāo)進(jìn)行轉(zhuǎn)換,再判斷下調(diào)用哪個(gè)方法即可。
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 ; } //存儲(chǔ)數(shù)組行列下標(biāo) int i = y/W; int j = x/W; if(blank_x == i-1&&blank_y == j){//空塊在當(dāng)前點(diǎn)擊塊的上側(cè) moveUp(); }else if(blank_x == i+1&&blank_y == j){//空塊在當(dāng)前點(diǎn)擊塊的下側(cè) moveDown(); }else if(blank_x == i&&blank_y == j-1){//空塊在當(dāng)前點(diǎn)擊塊的左側(cè) moveLeft(); }else if(blank_x == i&&blank_y == j+1){//空塊在當(dāng)前點(diǎn)擊塊的右側(cè) 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(); }
小圖片的移動(dòng)
交換小圖片與空塊的值,并對(duì)空塊的數(shù)組下標(biāo)重新賦值:
//空塊與上一格交換 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()獲取隨機(jī)值,各個(gè)方向按鍵事件的概率是1/4,當(dāng)符合條件時(shí)執(zhí)行移動(dòng)方法并且移動(dòng)次數(shù)+1,移動(dòng)10000次實(shí)現(xiàn)隨機(jī)打亂地圖。
private void RandomTheMap() { int i =0; //嘗試移動(dòng)一萬次 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++; } } //再將空塊移動(dòng)到最右下角 while(blank_x<level+1){ moveUp(); } while(blank_y<level+1){ moveLeft(); } step=0; }
判斷輸贏
將現(xiàn)有map信息與正確的map信息一一對(duì)比,如果都相等,過關(guān),比較當(dāng)前記錄和歷史記錄,如果刷新歷史記錄進(jìn)行記錄的更新,然后詢問是否開始下一關(guān)。如果開始下一關(guān),進(jìn)行l(wèi)evel++并對(duì)地圖及面板信息進(jìn)行初始化:
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){//通關(guān),是否進(jìn)入下一關(guān) case EASY: this.removeKeyListener(this); this.removeMouseListener(this); record = mapUtil.getRecord(level);//歷史記錄 if(step<record){ msg = "恭喜你通過簡單關(guān)卡并刷新歷史記錄,完成步數(shù)是"+step+"\n歷史記錄是"+record+",是否要進(jìn)入下一關(guān)?"; mapUtil.writeRecord(level, step);//更新歷史記錄 }else{ msg = "恭喜你通過簡單關(guān)卡,完成步數(shù)是"+step+"\n是否要進(jìn)入下一關(guān)?"; } type = JOptionPane.YES_NO_OPTION; title = "過關(guān)"; 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();//初始化地圖相關(guān)變量信息 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 = "恭喜你通過正常關(guān)卡并刷新歷史記錄,完成步數(shù)是"+step+"\n歷史記錄是"+record+",是否要進(jìn)入下一關(guān)?"; mapUtil.writeRecord(level, step);//更新歷史記錄 }else{ msg = "恭喜你通過正常關(guān)卡,完成步數(shù)是"+step+"\n是否要進(jìn)入下一關(guān)?"; } type = JOptionPane.YES_NO_OPTION; title = "過關(guān)"; 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();//初始化地圖相關(guān)變量信息 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 = "恭喜你通過困難關(guān)卡并刷新歷史記錄,完成步數(shù)是"+step+"\n歷史記錄是"+record; JOptionPane.showMessageDialog(this, msg); mapUtil.writeRecord(level, step);//更新歷史記錄 }else{ msg = "恭喜通過困難關(guān)卡,完成步數(shù)是"+step; JOptionPane.showMessageDialog(this, msg); } ;break; } } }
歷史記錄的讀寫
采用文本形式對(duì)記錄進(jìn)行保存,初始情況下,讀取記錄的時(shí)候如果沒有記錄文件進(jìn)行文件的新建并初始所有歷史記錄為9999步;記錄的保存采用兩個(gè)逗號(hào)對(duì)三個(gè)關(guān)卡的歷史記錄進(jìn)行分割,讀取后進(jìn)行array.split(",")分割操作;寫入時(shí),先清空原有文本信息,再將記錄合成字符串寫入文件。
//獲取關(guān)卡歷史記錄 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]); } //更新關(guān)卡歷史記錄 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(); } } }
到這里核心的游戲邏輯及游戲面板的相關(guān)內(nèi)容已經(jīng)說明完了,涉及輔助面板類的東西會(huì)有些錯(cuò)綜復(fù)雜,這里就不詳細(xì)介紹了。
完整源碼如下:
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; } //獲取關(guān)卡歷史記錄 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]); } //更新關(guān)卡歷史記錄 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類主要用做對(duì)地圖數(shù)組信息的初始化以及歷史記錄的讀寫。
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;//最后結(jié)果 int blank_x,blank_y;//記錄空白塊的數(shù)組下標(biāo) int step = 0; MapUtil mapUtil = new MapUtil(); int record;//存儲(chǔ)當(dāng)前關(guān)卡記錄 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();//初始化地圖相關(guān)變量信息 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; //嘗試移動(dòng)一萬次 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++; } } //再將空塊移動(dòng)到最右下角 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 ; } //存儲(chǔ)數(shù)組行列下標(biāo) int i = y/W; int j = x/W; if(blank_x == i-1&&blank_y == j){//空塊在當(dāng)前點(diǎn)擊塊的上側(cè) moveUp(); }else if(blank_x == i+1&&blank_y == j){//空塊在當(dāng)前點(diǎn)擊塊的下側(cè) moveDown(); }else if(blank_x == i&&blank_y == j-1){//空塊在當(dāng)前點(diǎn)擊塊的左側(cè) moveLeft(); }else if(blank_x == i&&blank_y == j+1){//空塊在當(dāng)前點(diǎn)擊塊的右側(cè) 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){//通關(guān),是否進(jìn)入下一關(guān) case EASY: this.removeKeyListener(this); this.removeMouseListener(this); record = mapUtil.getRecord(level);//歷史記錄 if(step<record){ msg = "恭喜你通過簡單關(guān)卡并刷新歷史記錄,完成步數(shù)是"+step+"\n歷史記錄是"+record+",是否要進(jìn)入下一關(guān)?"; mapUtil.writeRecord(level, step);//更新歷史記錄 }else{ msg = "恭喜你通過簡單關(guān)卡,完成步數(shù)是"+step+"\n是否要進(jìn)入下一關(guān)?"; } type = JOptionPane.YES_NO_OPTION; title = "過關(guān)"; 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();//初始化地圖相關(guān)變量信息 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 = "恭喜你通過正常關(guān)卡并刷新歷史記錄,完成步數(shù)是"+step+"\n歷史記錄是"+record+",是否要進(jìn)入下一關(guān)?"; mapUtil.writeRecord(level, step);//更新歷史記錄 }else{ msg = "恭喜你通過正常關(guān)卡,完成步數(shù)是"+step+"\n是否要進(jìn)入下一關(guān)?"; } type = JOptionPane.YES_NO_OPTION; title = "過關(guān)"; 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();//初始化地圖相關(guān)變量信息 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 = "恭喜你通過困難關(guān)卡并刷新歷史記錄,完成步數(shù)是"+step+"\n歷史記錄是"+record; JOptionPane.showMessageDialog(this, msg); mapUtil.writeRecord(level, step);//更新歷史記錄 }else{ msg = "恭喜通過困難關(guān)卡,完成步數(shù)是"+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類負(fù)責(zé)游戲運(yùn)行界面右下角完整拼圖順序的小圖片顯示;
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("當(dāng)前難度:"); JLabel nowStepLabel = new JLabel("當(dāng)前步數(shù):"); JLabel historyStepLabel = new JLabel("歷史記錄:"); JButton button1 = new JButton("退出"); BorderLayout panel1 = new BorderLayout();//右側(cè) 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());//當(dāng)前面板 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類負(fù)責(zé)游戲運(yùn)行界面右邊輔助面板的顯示,其中裝載了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類是游戲窗口類,裝載了游戲面板和輔助面板,用來開始游戲。
源碼已經(jīng)粘貼完畢,最后再展示兩張游戲運(yùn)行截圖:
到此這篇關(guān)于Java游戲開發(fā)拼圖游戲經(jīng)典版的文章就介紹到這了,更多相關(guān)Java拼圖游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解讀SpringBoot接收List<Bean>參數(shù)問題(POST請(qǐng)求方式)
這篇文章主要介紹了解讀SpringBoot接收List<Bean>參數(shù)問題(POST請(qǐng)求方式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09基于Java實(shí)現(xiàn)的圖的廣度優(yōu)先遍歷算法
這篇文章主要介紹了基于Java實(shí)現(xiàn)的圖的廣度優(yōu)先遍歷算法,需要的朋友可以參考下2014-07-07如何應(yīng)對(duì)spring框架的HTTP ERROR 400 Bad Request錯(cuò)
這篇文章主要介紹了如何應(yīng)對(duì)spring框架的HTTP ERROR 400 Bad Request錯(cuò)誤返回問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08顯示IntelliJ IDEA工具的Run Dashboard功能圖文詳解
這篇文章主要介紹了顯示IntelliJ IDEA工具的Run Dashboard功能,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Java Fluent Mybatis 項(xiàng)目工程化與常規(guī)操作詳解流程篇 下
Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國內(nèi)又以Mybatis用的多,基于mybatis上的增強(qiáng)框架,又有mybatis plus和TK mybatis等。今天我們介紹一個(gè)新的mybatis增強(qiáng)框架 fluent mybatis關(guān)于項(xiàng)目工程化與常規(guī)操作流程2021-10-10