Java實(shí)現(xiàn)動(dòng)物換位游戲完整?過程詳解
效果展示
一、效果展示
1.游戲界面
開始
成功
2.測(cè)試界面
二、項(xiàng)目介紹
1.總體需求
(1)在水平排列的7塊石頭上的左右各有3個(gè)類型相同的2種動(dòng)物,中間的石頭上沒有動(dòng)物。
(2)用鼠標(biāo)單擊一個(gè)動(dòng)物:
①若“該動(dòng)物前方的石頭”上沒有動(dòng)物,該動(dòng)物就跳躍到該石頭上。
②若“該動(dòng)物前方的石頭”上有動(dòng)物,但隔位的石頭上無動(dòng)物,該動(dòng)物就越過自己前面的動(dòng)物跳到隔位的石頭上。
③其他情形時(shí),該動(dòng)物不跳躍(跳躍時(shí)不能越過2塊石頭)。
(3)左面的動(dòng)物只能向右方跳躍,右面的動(dòng)物只能向左方跳躍。
(4)用戶可以通過單擊界面上提供的按鈕,隨時(shí)撤銷上一步的操作。
(5)用戶可以隨時(shí)單擊界面上的按鈕,重新開始游戲。
2.總體設(shè)計(jì)
項(xiàng)目結(jié)構(gòu)共四個(gè)package,分別是data,test,gui,view。具體實(shí)現(xiàn)封裝的12個(gè)類如圖所示:
三、代碼展示
1.圖形界面設(shè)計(jì)(gui包)
主類:AppWindows類
AppWindow類負(fù)責(zé)創(chuàng)建動(dòng)物換位的主窗口,該類含有main方法,程序從該類開始執(zhí)行。
package ch1.gui; import javax.swing.*; import java.awt.*; import ch1.view.GamePanel; public class AppWindow extends JFrame { GamePanel gamePanel; public AppWindow(){ setTitle("動(dòng)物換位游戲"); gamePanel = new GamePanel(); gamePanel.setAnimalCount(6); gamePanel.setLeftAnimalImage("程序發(fā)布/image/cat.jpg"); gamePanel.setRightAnimalImage("程序發(fā)布/image/dog.jpg"); add(gamePanel,BorderLayout.CENTER); gamePanel.setBackground(Color.white); JPanel northP = new JPanel(); northP.add(gamePanel.buttonReStart); northP.add(gamePanel.buttonRedo); add(northP,BorderLayout.NORTH); setBounds(60,60,9*gamePanel.width+9*gamePanel.gap,300); validate(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public static void main(String args[] ){ AppWindow win = new AppWindow(); } }
2.用戶操作設(shè)計(jì)(data包)
① Animal類
Animal類創(chuàng)建的對(duì)象是AppWindow類的重要成員之一,用來表示“動(dòng)物”。
package ch1.data; public abstract class Animal { String name ; Point [] allCanAtPoint; //全部點(diǎn)位置 Point point; //動(dòng)物當(dāng)前所在的點(diǎn)位置 ViewForAnimal animalView; //動(dòng)物的外觀視圖 public void setAtPoint(Point p) { if(p!=null){ point = p; point.setIsHaveAnimal(true); point.setAtPointAnimal(this); } } public Point getAtPoint() { return point; } public void setAllCanAtPoint(Point [] point){ allCanAtPoint = point; } public void setAnimalView(ViewForAnimal animalView) { this.animalView = animalView; animalView.setAnimal(this); } public ViewForAnimal getAnimalView() { return animalView; } public void setName(String s) { name = s; } public String getName() { return name; } public abstract boolean move(); }
② LeftAnimal類
LeftAnimal類是Animal的一個(gè)子類,創(chuàng)建的對(duì)象是AppWindow類的成員之一,表示“左動(dòng)物”。
package ch1.data; public class LeftAnimal extends Animal{ public boolean move(){ int k = -1; boolean successMove = false; Point p = getAtPoint(); for(int i=0;i<allCanAtPoint.length;i++){ if(allCanAtPoint[i].equals(p)){ k = i; //找到動(dòng)物當(dāng)前所處的位置:allCanAtPoint[k] break; } } if(k==allCanAtPoint.length-1){//已經(jīng)在最右面的點(diǎn)位置 return false; } if(allCanAtPoint[k+1].isHaveAnimal()==false) { //前面位置上沒有動(dòng)物 this.setAtPoint(allCanAtPoint[k+1]); successMove = true; p.setAtPointAnimal(null); return successMove ; } if((k+1)==allCanAtPoint.length-1){ //前面位置上是已經(jīng)到達(dá)終點(diǎn)的動(dòng)物 return false; } if(allCanAtPoint[k+2].isHaveAnimal()==false) {//前方隔位上沒有動(dòng)物 this.setAtPoint(allCanAtPoint[k+2]); successMove = true; p.setAtPointAnimal(null); return successMove ; } return successMove ; } }
③ RightAnimal類
RightAnimal類是Animal的一個(gè)子類,創(chuàng)建的對(duì)象是AppWindow類的成員之一,表示“右動(dòng)物”。
package ch1.data; public class RightAnimal extends Animal{ public boolean move(){ int k = -1; boolean successMove = false; Point p = getAtPoint(); for(int i=0;i<allCanAtPoint.length;i++){ if(allCanAtPoint[i].equals(p)){ k = i; break; } } if(k==0){ //已經(jīng)在最左面的點(diǎn)位置 return false; } if(allCanAtPoint[k-1].isHaveAnimal()==false) {//前面位置上沒有動(dòng)物 this.setAtPoint(allCanAtPoint[k-1]);//動(dòng)物到達(dá)allCanAtPoint[k-1]點(diǎn) successMove = true; p.setAtPointAnimal(null); //p點(diǎn)設(shè)置為無動(dòng)物 return successMove ; } if((k-1)==0){ //前面位置上是已經(jīng)到達(dá)終點(diǎn)的動(dòng)物 return false; } if(allCanAtPoint[k-2].isHaveAnimal()==false) {//前方隔位上沒有動(dòng)物 this.setAtPoint(allCanAtPoint[k-2]); //動(dòng)物到達(dá)allCanAtPoint[k-2]點(diǎn) successMove = true; p.setAtPointAnimal(null); //p點(diǎn)設(shè)置為無動(dòng)物 return successMove ; } return successMove ; } }
④ Point類
Point類負(fù)責(zé)創(chuàng)建確定位置的對(duì)象,使用Point對(duì)象,可以確定動(dòng)物以及石頭對(duì)象在窗體中的位置。
package ch1.data; public class Point{ int x,y; boolean haveAnimal; Animal animal=null; //在該點(diǎn)位置上的動(dòng)物 public void setX(int x){ this.x=x; } public void setY(int y){ this.y=y; } public boolean isHaveAnimal(){ return haveAnimal; } public void setIsHaveAnimal(boolean boo){ haveAnimal=boo; } public int getX(){ return x; } public int getY(){ return y; } public void setAtPointAnimal(Animal animal){ this.animal=animal; if(animal!=null) { haveAnimal = true; } else { haveAnimal = false; } } public Animal getAtPointAnimal(){ return animal; } }
⑤ ViewForAnimal類
該類是JPanel類的一個(gè)子類,用于實(shí)現(xiàn)動(dòng)物方法的定義。
package ch1.data; import javax.swing.JPanel; public abstract class ViewForAnimal extends JPanel { public abstract void setAnimal(Animal animal); public abstract void setImage(String name); public abstract Animal getAnimal(); public abstract void setAnimalViewLocation(int x,int y); public abstract void setAnimalViewSize(int w,int h); }
3.游戲視圖設(shè)計(jì)(view包)
① AnmialView類
AnimalView類是ViewForAnimal的一個(gè)子類,實(shí)現(xiàn)對(duì)動(dòng)物操作的各種方法。
package ch1.view; import java.awt.*; import ch1.data.*; public class AnimalView extends ViewForAnimal{ Animal animal; Image image; Toolkit tool; public AnimalView() { tool = getToolkit(); } public void setAnimal(Animal animal){ this.animal = animal; } public void setImage(String name){ image = tool.getImage(name); repaint(); } public Animal getAnimal() { return animal; } public void setAnimalViewLocation(int x,int y){ setLocation(x,y); } public void setAnimalViewSize(int w,int h){ setSize(w,h); } public void paintComponent(Graphics g){ super.paintComponent(g); int w=getBounds().width; int h=getBounds().height; g.drawImage(image,0,0,w,h,this); } }
② GamePanel類
GamePanel類是JPanel的子類,用于游戲視圖的初始化。
package ch1.view; import javax.swing.*; import java.awt.*; import ch1.data.Animal; import ch1.data.Point; import ch1.data.ViewForAnimal; import ch1.data.LeftAnimal; import ch1.data.RightAnimal; import java.util.*; import java.awt.geom.*; public class GamePanel extends JPanel { public int animalCount = -1; public Point [] point ; Animal [] leftAnimal,rightAnimal; public ViewForAnimal [] leftAnimalView,rightAnimalView;//動(dòng)物視圖 public int width =90,height=70; //動(dòng)物視圖的大小 public int gap = 2; //動(dòng)物之間的間隙 public JButton buttonRedo;//撤銷按鈕 public JButton buttonReStart;//重新開始游戲 public Stack<Point> saveAnimalStep; //存放動(dòng)物走動(dòng)的位置,以便恢復(fù) HandleAnimalMove handleAnimalMove;//負(fù)責(zé)處理MouseEvent的監(jiān)視器 HandleRedo handleRedo; //負(fù)責(zé)ActionEvent的監(jiān)視器 HandleReStart handleReStart; //負(fù)責(zé)ActionEvent的監(jiān)視器 public GamePanel(){ setLayout(null); buttonRedo = new JButton("撤銷"); buttonReStart = new JButton("重新開始"); saveAnimalStep = new Stack<Point>(); } public void setAnimalCount(int n){ if(n%2 != 0 ||n<=1) { System.out.println(n+"的個(gè)數(shù)不合理"); System.exit(0); } removeAll(); //首先移出曾添加到該容器中的全部組件 animalCount = n; initPoitAndAnimal(); //初始化動(dòng)物和位置對(duì)象 initLeftAnimalView(); //初始化左邊的動(dòng)物視圖 initRightAnimalView(); registerListener(); //注冊(cè)監(jiān)視器 } private void initPoitAndAnimal(){//初始化動(dòng)物和位置對(duì)象 point = new Point[animalCount+1]; int posionX = width; //點(diǎn)的位置的x坐標(biāo) int posionY = height; for(int i=0;i<point.length;i++) { point[i] = new Point(); point[i].setX(posionX); point[i].setY(posionY); posionX = posionX+width+gap; } int m = animalCount/2; leftAnimal = new LeftAnimal[m]; rightAnimal = new RightAnimal[m]; for(int i =0;i<leftAnimal.length;i++ ){ leftAnimal[i] = new LeftAnimal(); leftAnimal[i].setAtPoint(point[i]); leftAnimal[i].setAllCanAtPoint(point); } for(int i =0;i<rightAnimal.length;i++ ){ rightAnimal[i] = new RightAnimal(); rightAnimal[i].setAtPoint(point[m+1+i]); rightAnimal[i].setAllCanAtPoint(point); } } private void initLeftAnimalView(){//初始化左邊的動(dòng)物視圖 int m = animalCount/2; leftAnimalView = new ViewForAnimal[m]; for(int i =0;i<leftAnimalView.length;i++ ){ leftAnimalView[i] = new AnimalView(); leftAnimal[i].setAnimalView(leftAnimalView[i]); Point p = leftAnimal[i].getAtPoint(); int x = p.getX(); int y = p.getY(); add(leftAnimalView[i]); //動(dòng)物視圖所在位置和動(dòng)物所在點(diǎn)相同: leftAnimalView[i].setAnimalViewLocation(x,y); leftAnimalView[i].setAnimalViewSize(width,height); } } private void initRightAnimalView(){//初始化右邊的動(dòng)物視圖 int m = animalCount/2; rightAnimalView = new ViewForAnimal[m]; for(int i =0;i<rightAnimalView.length;i++ ){ rightAnimalView[i] = new AnimalView(); rightAnimal[i].setAnimalView(rightAnimalView[i]); Point p = rightAnimal[i].getAtPoint(); int x = p.getX(); int y = p.getY(); add(rightAnimalView[i]); rightAnimalView[i].setAnimalViewLocation(x,y); rightAnimalView[i].setAnimalViewSize(width,height); } } private void registerListener(){ handleAnimalMove = new HandleAnimalMove(this); //監(jiān)視用戶在動(dòng)物視圖上觸發(fā)的MouseEvent事件: for(int i =0;i<rightAnimalView.length;i++ ){ rightAnimalView[i].addMouseListener(handleAnimalMove); } for(int i =0;i<leftAnimalView.length;i++ ){ leftAnimalView[i].addMouseListener(handleAnimalMove); } handleRedo = new HandleRedo(this); handleReStart = new HandleReStart(this); //監(jiān)視用戶在按鈕上觸發(fā)的ActionEvent事件: buttonRedo.addActionListener(handleRedo); buttonReStart.addActionListener(handleReStart); } public void setLeftAnimalImage(String pic){ if(animalCount==-1) return; for(int i =0;i<leftAnimalView.length;i++ ){ leftAnimalView[i].setImage(pic); } } public void setRightAnimalImage(String pic){ if(animalCount==-1) return; for(int i =0;i<rightAnimalView.length;i++ ){ rightAnimalView[i].setImage(pic); } } public void paintComponent(Graphics g){ int penHeight =12; //畫筆的高度 super.paintComponent(g); int xStart =width+gap; int yStart =2*height+penHeight/2; int xEnd =(animalCount+2)*width+(animalCount+1)*2; int yEnd =2*height+penHeight/2; Line2D line=new Line2D.Double(xStart,yStart,xEnd,yEnd); Graphics2D g_2d=(Graphics2D)g; g_2d.setColor(Color.blue); BasicStroke bs= new BasicStroke(penHeight,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER); g_2d.setStroke(bs); g_2d.draw(line); } }
③ HandleAnimalMove類
該類所創(chuàng)建的對(duì)象負(fù)責(zé)處理鼠標(biāo)事件,實(shí)現(xiàn)動(dòng)物位置的移動(dòng)。
package ch1.view; import java.awt.event.*; import javax.swing.JOptionPane; import ch1.data.Point; import ch1.data.Animal; import ch1.data.ViewForAnimal; import ch1.data.LeftAnimal; import ch1.data.RightAnimal; public class HandleAnimalMove extends MouseAdapter { GamePanel panel; HandleAnimalMove(GamePanel panel){ this.panel = panel; } public void mousePressed(MouseEvent e){ ViewForAnimal animalView = (ViewForAnimal)e.getSource(); Animal animal = animalView.getAnimal(); Point pStart = animal.getAtPoint(); //得到動(dòng)物移動(dòng)前所在點(diǎn) if(animal.move()) { Point pEnd = animal.getAtPoint();//得到動(dòng)物移動(dòng)后所在點(diǎn) int x = pEnd.getX(); int y = pEnd.getY(); animalView.setAnimalViewLocation(x,y);//讓動(dòng)物視圖所在位置和動(dòng)物所在點(diǎn)相同 panel.saveAnimalStep.push(pStart); panel.saveAnimalStep.push(pEnd); } } public void mouseReleased(MouseEvent e){ boolean success = true; int n =panel.animalCount/2; for(int i=0;i<n;i++){ Animal animal=panel.point[i].getAtPointAnimal(); success = success&&(animal instanceof RightAnimal); animal=panel.point[n+1+i].getAtPointAnimal(); success = success&&(animal instanceof LeftAnimal); if(success == false) break; } if(success) { JOptionPane.showMessageDialog(null,"您成功了","消息框", JOptionPane.INFORMATION_MESSAGE); } } }
④ HandleRedo類
該類所創(chuàng)建的對(duì)象負(fù)責(zé)處理鼠標(biāo)事件,實(shí)現(xiàn)鼠標(biāo)操作的撤銷。
package ch1.view; import ch1.data.Point; import ch1.data.Animal; import ch1.data.ViewForAnimal; import java.awt.event.*; public class HandleRedo implements ActionListener { GamePanel panel; HandleRedo(GamePanel panel){ this.panel = panel; } public void actionPerformed(ActionEvent e){ //撤銷移動(dòng)動(dòng)物的操作 if(panel.saveAnimalStep.empty()) return; Point pEnd = panel.saveAnimalStep.pop(); Point pStart = panel.saveAnimalStep.pop(); Animal animal = pEnd.getAtPointAnimal(); pEnd.setIsHaveAnimal(false); pEnd.setAtPointAnimal(null); animal.setAtPoint(pStart); ViewForAnimal animalView =animal.getAnimalView(); int x = pStart.getX(); int y = pStart.getY(); animalView.setAnimalViewLocation(x,y);//讓動(dòng)物視圖所在位置和動(dòng)物所在點(diǎn)相同 } }
⑤ HandleReStart類
該類所創(chuàng)建的對(duì)象負(fù)責(zé)處理鼠標(biāo)事件,實(shí)現(xiàn)游戲的重開功能。
package ch1.view; import ch1.data.ViewForAnimal; import java.awt.event.*; public class HandleReStart implements ActionListener { GamePanel panel; HandleReStart(GamePanel panel){ this.panel = panel; } public void actionPerformed(ActionEvent e){ //處理重新開始 panel.saveAnimalStep.clear(); for(int i=0;i<panel.point.length;i++) { panel.point[i].setIsHaveAnimal(false); } for(int i =0;i<panel.leftAnimal.length;i++ ){ panel.leftAnimal[i].setAtPoint(panel.point[i]); int x = panel.point[i].getX(); int y = panel.point[i].getY(); //讓動(dòng)物視圖所在位置和動(dòng)物所在點(diǎn)相同 ViewForAnimal animalView =panel.leftAnimal[i].getAnimalView(); animalView.setAnimalViewLocation(x,y); } for(int i =0;i<panel.rightAnimal.length;i++ ){ int m = panel.animalCount/2; panel.rightAnimal[i].setAtPoint(panel.point[m+1+i]); int x = panel.point[m+1+i].getX(); int y = panel.point[m+1+i].getY(); //讓動(dòng)物視圖所在位置和動(dòng)物所在點(diǎn)相同 ViewForAnimal animalView =panel.rightAnimal[i].getAnimalView(); animalView.setAnimalViewLocation(x,y); } } }
四、代碼測(cè)試
這里我們創(chuàng)建test包,實(shí)現(xiàn)AppTest類來進(jìn)行代碼的測(cè)試,代碼如下:
package ch1.test; import ch1.data.*; public class AppTest { public static void main(String [] args) { Point [] point = new Point[7]; for(int i=0;i<point.length;i++) { point[i] = new Point(); point[i].setX(i); point[i].setY(10); } Animal [] left = new Animal[3]; Animal [] right = new Animal[3]; for(int i =0;i<left.length;i++ ){ left[i] = new LeftAnimal(); left[i].setName("貓"+i); left[i].setAtPoint(point[i]); left[i].setAllCanAtPoint(point); } for(int i =0;i<right.length;i++ ){ right[i] = new RightAnimal(); right[i].setName("狗"+i); right[i].setAtPoint(point[4+i]); right[i].setAllCanAtPoint(point); } input(point); if(right[0].move()) input(point); if(left[2].move()) input(point); if(left[1].move()) input(point); if(right[0].move()) input(point); if(right[1].move()) input(point); if(right[2].move()) input(point); if(left[2].move()) input(point); if(left[1].move()) input(point); if(left[0].move()) input(point); if(right[0].move()) input(point); if(right[1].move()) input(point); if(right[2].move()) input(point); if(left[1].move()) input(point); if(left[0].move()) input(point); if(right[2].move()) input(point); } static void input(Point [] point){ for(int i=0;i<point.length;i++){ Animal animal=point[i].getAtPointAnimal(); if(animal!=null) System.out.print(animal.getName()); else System.out.print(" "); } System.out.println(); } }
五、所需圖像
預(yù)備名字分別為dog.jpg和cat.jpg的圖像文件,它們分別是左右動(dòng)物所使用的圖像。
dog.jpg
cat.jpg
六、總結(jié)
本項(xiàng)目是很多大學(xué)課程設(shè)計(jì)中常見的題目之一,通過該項(xiàng)目的實(shí)現(xiàn),可以使開發(fā)者鞏固所學(xué)Java語言知識(shí),增進(jìn)Java語言編輯基本功,掌握J(rèn)DK、IDEA等開發(fā)工具的運(yùn)用,拓寬常用類庫(kù)的應(yīng)用。
通過該項(xiàng)目的實(shí)操,開發(fā)者可以把所學(xué)及相關(guān)知識(shí)加以融會(huì)貫通,全面掌握J(rèn)ava語言的編程思想及面向?qū)ο蟪绦蛟O(shè)計(jì)的方法,為今后從事實(shí)際工作打下堅(jiān)實(shí)的基礎(chǔ)。
到此這篇關(guān)于Java實(shí)現(xiàn)動(dòng)物換位游戲完整 過程詳解的文章就介紹到這了,更多相關(guān)Java動(dòng)物換位內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決IDEA項(xiàng)目external libraries依賴包消失的問題
有時(shí)候電腦重啟后,再打開IDEA上的項(xiàng)目時(shí)會(huì)出現(xiàn)external libraries目錄下的依賴包都消失了的情況,只剩下了一個(gè)JDK的包,本文給大家介紹了解決IDEA項(xiàng)目external libraries依賴包消失的辦法,需要的朋友可以參考下2024-02-02Spring生命周期回調(diào)與容器擴(kuò)展詳解
這篇文章主要介紹了Spring生命周期回調(diào)與容器擴(kuò)展詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12SpringMVC高級(jí)開發(fā)功能實(shí)現(xiàn)過程解析
這篇文章主要介紹了SpringMVC高級(jí)開發(fā)功能實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06springboot?vue測(cè)試平臺(tái)接口定義前后端新增功能實(shí)現(xiàn)
這篇文章主要介紹了springboot?vue測(cè)試平臺(tái)接口定義前后端新增功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05java使用common-httpclient包實(shí)現(xiàn)post請(qǐng)求方法示例
這篇文章主要給大家介紹了關(guān)于java使用common-httpclient包實(shí)現(xiàn)post請(qǐng)求的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08使用Springboot+poi上傳并處理百萬級(jí)數(shù)據(jù)EXCEL
這篇文章主要介紹了使用Springboot+poi上傳并處理百萬級(jí)數(shù)據(jù)EXCEL,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12Spring security基于數(shù)據(jù)庫(kù)中賬戶密碼認(rèn)證
這篇文章主要介紹了Spring security基于數(shù)據(jù)庫(kù)中賬戶密碼認(rèn)證,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03