Java實現動物換位遊戲完整 過程詳解

效果展示

一、效果展示

1.遊戲界面

開始

成功

2.測試界面

二、項目介紹

1.總體需求

(1)在水平排列的7塊石頭上的左右各有3個類型相同的2種動物,中間的石頭上沒有動物。

(2)用鼠標單擊一個動物:

①若“該動物前方的石頭”上沒有動物,該動物就跳躍到該石頭上。

②若“該動物前方的石頭”上有動物,但隔位的石頭上無動物,該動物就越過自己前面的動物跳到隔位的石頭上。

③其他情形時,該動物不跳躍(跳躍時不能越過2塊石頭)。

(3)左面的動物隻能向右方跳躍,右面的動物隻能向左方跳躍。

(4)用戶可以通過單擊界面上提供的按鈕,隨時撤銷上一步的操作。

(5)用戶可以隨時單擊界面上的按鈕,重新開始遊戲。

2.總體設計

項目結構共四個package,分別是data,test,gui,view。具體實現封裝的12個類如圖所示:

三、代碼展示

1.圖形界面設計(gui包)

主類:AppWindows類

AppWindow類負責創建動物換位的主窗口,該類含有main方法,程序從該類開始執行。

package ch1.gui;
import javax.swing.*;
import java.awt.*;
import ch1.view.GamePanel;
public class AppWindow extends JFrame {
    GamePanel gamePanel;
    public AppWindow(){
       setTitle("動物換位遊戲");
       gamePanel = new GamePanel();
       gamePanel.setAnimalCount(6);
       gamePanel.setLeftAnimalImage("程序發佈/image/cat.jpg");
       gamePanel.setRightAnimalImage("程序發佈/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.用戶操作設計(data包)

① Animal類

Animal類創建的對象是AppWindow類的重要成員之一,用來表示“動物”。

package ch1.data;
public abstract class Animal {
    String name ;
    Point [] allCanAtPoint;    //全部點位置
    Point point;               //動物當前所在的點位置
    ViewForAnimal animalView;  //動物的外觀視圖
    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的一個子類,創建的對象是AppWindow類的成員之一,表示“左動物”。

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; //找到動物當前所處的位置:allCanAtPoint[k]
            break;
         }
      } 
      if(k==allCanAtPoint.length-1){//已經在最右面的點位置
          return false;
      }
      if(allCanAtPoint[k+1].isHaveAnimal()==false) { //前面位置上沒有動物
         this.setAtPoint(allCanAtPoint[k+1]);
         successMove = true;
         p.setAtPointAnimal(null);
         return successMove ;
      }
      if((k+1)==allCanAtPoint.length-1){ //前面位置上是已經到達終點的動物
          return false;
      }
      if(allCanAtPoint[k+2].isHaveAnimal()==false) {//前方隔位上沒有動物
         this.setAtPoint(allCanAtPoint[k+2]);
         successMove = true;
         p.setAtPointAnimal(null);
         return successMove ;
      }
      return successMove ;  
   }  
}

③ RightAnimal類

RightAnimal類是Animal的一個子類,創建的對象是AppWindow類的成員之一,表示“右動物”。

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){  //已經在最左面的點位置
          return false;
      }
      if(allCanAtPoint[k-1].isHaveAnimal()==false) {//前面位置上沒有動物
         this.setAtPoint(allCanAtPoint[k-1]);//動物到達allCanAtPoint[k-1]點
         successMove = true;
         p.setAtPointAnimal(null);           //p點設置為無動物
         return successMove ;
      }
      if((k-1)==0){   //前面位置上是已經到達終點的動物
          return false;
      }  
      if(allCanAtPoint[k-2].isHaveAnimal()==false) {//前方隔位上沒有動物
         this.setAtPoint(allCanAtPoint[k-2]); //動物到達allCanAtPoint[k-2]點
         successMove = true;
         p.setAtPointAnimal(null);           //p點設置為無動物
         return successMove ;
      }
      return successMove ;  
   }  
}

④ Point類

Point類負責創建確定位置的對象,使用Point對象,可以確定動物以及石頭對象在窗體中的位置。

package ch1.data;
public class Point{
    int x,y; 
    boolean haveAnimal; 
    Animal animal=null; //在該點位置上的動物
    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類的一個子類,用於實現動物方法的定義。

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.遊戲視圖設計(view包)

① AnmialView類

AnimalView類是ViewForAnimal的一個子類,實現對動物操作的各種方法。

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;//動物視圖
    public int width =90,height=70;  //動物視圖的大小
    public int gap = 2;              //動物之間的間隙           
    public JButton buttonRedo;//撤銷按鈕
    public JButton buttonReStart;//重新開始遊戲
    public Stack<Point> saveAnimalStep; //存放動物走動的位置,以便恢復
    HandleAnimalMove handleAnimalMove;//負責處理MouseEvent的監視器
    HandleRedo handleRedo;           //負責ActionEvent的監視器 
    HandleReStart handleReStart;    //負責ActionEvent的監視器
    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+"的個數不合理");
          System.exit(0);
       } 
       removeAll();  //首先移出曾添加到該容器中的全部組件
       animalCount = n;
       initPoitAndAnimal();  //初始化動物和位置對象
       initLeftAnimalView(); //初始化左邊的動物視圖
       initRightAnimalView();
       registerListener();   //註冊監視器
    }
    private void initPoitAndAnimal(){//初始化動物和位置對象
       point = new Point[animalCount+1];
       int posionX = width; //點的位置的x坐標
       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(){//初始化左邊的動物視圖
       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]);
          //動物視圖所在位置和動物所在點相同:
          leftAnimalView[i].setAnimalViewLocation(x,y);
          leftAnimalView[i].setAnimalViewSize(width,height);
       } 
    }
    private void initRightAnimalView(){//初始化右邊的動物視圖
       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);
        //監視用戶在動物視圖上觸發的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);
        //監視用戶在按鈕上觸發的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類

該類所創建的對象負責處理鼠標事件,實現動物位置的移動。

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(); //得到動物移動前所在點
        if(animal.move()) {
           Point pEnd = animal.getAtPoint();//得到動物移動後所在點
           int x = pEnd.getX();
           int y = pEnd.getY();
           animalView.setAnimalViewLocation(x,y);//讓動物視圖所在位置和動物所在點相同
           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類

該類所創建的對象負責處理鼠標事件,實現鼠標操作的撤銷。

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){ //撤銷移動動物的操作
           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);//讓動物視圖所在位置和動物所在點相同
    } 
}

⑤ HandleReStart類

該類所創建的對象負責處理鼠標事件,實現遊戲的重開功能。

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();
           //讓動物視圖所在位置和動物所在點相同
           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();
           //讓動物視圖所在位置和動物所在點相同
           ViewForAnimal animalView =panel.rightAnimal[i].getAnimalView();
           animalView.setAnimalViewLocation(x,y);
       }  
     } 
}

四、代碼測試

這裡我們創建test包,實現AppTest類來進行代碼的測試,代碼如下:

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();
    }
}

五、所需圖像

預備名字分別為dog.jpg和cat.jpg的圖像文件,它們分別是左右動物所使用的圖像。

dog.jpg

cat.jpg

六、總結

本項目是很多大學課程設計中常見的題目之一,通過該項目的實現,可以使開發者鞏固所學Java語言知識,增進Java語言編輯基本功,掌握JDK、IDEA等開發工具的運用,拓寬常用類庫的應用。

通過該項目的實操,開發者可以把所學及相關知識加以融會貫通,全面掌握Java語言的編程思想及面向對象程序設計的方法,為今後從事實際工作打下堅實的基礎。

到此這篇關於Java實現動物換位遊戲完整 過程詳解的文章就介紹到這瞭,更多相關Java動物換位內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: