2013年9月7日 星期六

java魔方陣遊戲

   

        利用大學所習得的迴圈技巧解出魔方陣可能解,並設計遊戲方式讓玩家可以動腦破關,設置難度為三關,點擊灰色方塊並可與黃色方塊交換,直到上下左右以及對角數字相加相等。

(一)解答畫面
(二)解答Model



public class Model {   
    private String sCheck[] = new String[4];
    private StringBuilder sResult ;
    private int iNum;
    public void setNum(int iRow,int iCol){//設置九宮格
        int n = iRow;
        iNum = 0;
        sResult = new StringBuilder();
        for (int i = 0; i < sCheck.length; i++) {sCheck[i] = "";}
        int v[] = new int[iRow*iCol];
        init(v);
        int a[] = new int [iRow*iCol];
        magic_UL(a,v,n);
        print(a,n);
        a = new int [iRow*iCol];        
        magic_UR(a,v,n);
        print(a,n);
        a = new int [iRow*iCol];
        magic_IL(a,v,n);
        print(a,n);
        a = new int [iRow*iCol];
        magic_IR(a,v,n);
        print(a,n);      
    }
    private void init(int[] v) {
         for (int i = 0; i < v.length; i++) {v[i] = i+1;}                   
    }
    private void magic_UL(int[] a, int[] v, int n) {//第一組解
        int r = 0,c = n/2,newr = 0,newc = 0;
        for (int i = 0; i < v.length; i++) {
            a[r*n+c] = v[i];
            newr = ((r-1)+n) % n;
            newc = ((c-1)+n) % n;
            if (a[newr*n+newc] != 0){
                newr = r+1;
                newc = c;
            }
        r = newr;
        c = newc;
        }
    }
    private void magic_UR(int[] a, int[] v, int n) {//第二組解
        int r = 0,c = n/2,newr = 0,newc = 0;
        for (int i = 0; i < v.length; i++) {
            a[r*n+c] = v[i];
            newr = ((r-1)+n) % n;
            newc = ((c+1)+n) % n;
            if (a[newr*n+newc] != 0){
                newr = r+1;
                newc = c;
            }
        r = newr;
        c = newc;
        }
    }
    private void magic_IL(int[] a, int[] v, int n) {//第三組解
         int r = n-1,c = n/2,newr = 0,newc = 0;
        for (int i = 0; i < v.length; i++) {
            a[r*n+c] = v[i];
            newr = ((r+1)+n) % n;
            newc = ((c-1)+n) % n;
            if (a[newr*n+newc] != 0){
                newr = r-1;
                newc = c;
            }
        r = newr;
        c = newc;
        }
    }
    private void magic_IR(int[] a, int[] v, int n) {//第四組解
        int r = n-1,c = n/2,newr = 0,newc = 0;
        for (int i = 0; i < v.length; i++) {
            a[r*n+c] = v[i];
            newr = ((r+1)+n) % n;
            newc = ((c+1)+n) % n;
            if (a[newr*n+newc] != 0){
                newr = r-1;
                newc = c;
            }
        r = newr;
        c = newc;
        }
    }
    private void print(int[] a, int n) {//印出解答
        sResult.append("第" + (iNum+1) + "組為:\n");
        for (int i = 0; i < a.length; i++) {
            sCheck[iNum] += a[i];
            sResult.append(String.format("%3d |", a[i]));           
            if (i%n == n-1){sResult.append("\n--------------------------\n");}                                          
        }
        iNum ++ ;        
    }
    public String getResult(){
        return sResult.toString();
    }
    public String[] getCheck(){
        return sCheck;
    }
}
(三)UIView
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class StyleBox_View extends JFrame implements ActionListener{
    private JPanel jpNorth = new JPanel(new FlowLayout());
    private JPanel jpWest = new JPanel();
    private JPanel jpCenter= new JPanel(new FlowLayout());
    private JPanel jpEast = new JPanel();
    private JLabel jlTitle = new JLabel("請選擇關卡");
    private JComboBox jCom = new JComboBox();
    private JButton jbStart = new JButton("Start");
    private JButton jbResult = new JButton("看答案"); 
    private JButton jbExplain = new JButton("說明");
    private int iCol,iRow;//欄列
    private JButton[][] jbGame;//宣告按鈕陣列
    private JButton jbSource,jbTarget;// 記錄移動視窗按鈕,及目標按鈕  
    private int [] myRandom;//建立亂數陣列供排列    
    private Model m = new Model();//處理答案的Model
    private JTextArea jta = new JTextArea();//答案文字
    private JScrollPane js;//捲軸
    public StyleBox_View(){
        super();
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension screenSize = toolkit.getScreenSize();
        int screenHeight = (int) screenSize.getHeight();// 解析度長
        int screenWidth = (int) screenSize.getWidth();// 解析度寬
        this.getContentPane().setBackground(Color.CYAN);
        this.setSize(800,600);
        this.setLocation(screenWidth / 2 - this.getWidth() / 2, screenHeight / 2
    -   this.getHeight() / 2);// 設定Frame置中        
        getjpNorth();
        this.add(jpNorth,BorderLayout.NORTH);         
        this.setVisible(true);
        jbResult.addActionListener(this); 
        jbExplain.addActionListener(this);
    }
    private void getjpNorth() {
        jpNorth.add(jlTitle);
        getjCom();
        jpNorth.add(jCom);
        jbStart.addActionListener(this);
        jpNorth.add(jbStart);
        jpNorth.add(jbExplain);
    }
    private void getjCom() {
        DefaultComboBoxModel com = new DefaultComboBoxModel();
        for (int i = 0; i < 3; i++) {com.addElement(i+1);}                              
        jCom.setModel(com);
        jCom.addActionListener(this);
    }              
    private void Start() {
        if (jCom.getSelectedIndex() == 0) {iCol = 3;iRow = 3;}
        if (jCom.getSelectedIndex() == 1) {iCol = 5;iRow = 5;} 
        if (jCom.getSelectedIndex() == 2) {iCol = 7;iRow = 7;}       
        m.setNum(iRow, iCol);
        myRandom = new int[iRow*iCol];//建立亂數陣列供排列
        getRandomArray();
        jpWest.setLayout(new GridLayout(iRow, iCol));
        jpWest.removeAll();
        jpCenter.removeAll();
        jpEast.removeAll();
        int btnCount = 1;   //記錄共有多少個按鈕
        jbGame = new JButton[iRow][iCol];
        for (int i = 0; i < iRow; i++) {
            for (int j = 0; j < iCol; j++) {
                jbGame[i][j] = new JButton();
                jbGame[i][j].setText("" + myRandom[btnCount-1]);//利用亂數陣列來定義按鈕內文字
                jbGame[i][j].setBackground(Color.YELLOW); //定義按鈕顏色
                jbGame[i][j].addMouseListener(new MouseAdapter() { //建立滑鼠事件
                    public void mousePressed(MouseEvent e) {
                        JButton mb = (JButton) e.getSource();
                        btnCheck(mb);        //當此按鈕被點擊時,執行 btnCheck() 
                    }                    
                });
                jpWest.add(jbGame[i][j]);
                btnCount++; 
            }         
        }
        setGame();
        this.add(jpWest,BorderLayout.WEST);             
        jpCenter.add(jbResult);      
        this.add(jpCenter,BorderLayout.CENTER); 
        jbStart.setEnabled(false);
        jbResult.setEnabled(true);
        pack();
    }      
     private void getRandomArray() {
        int iNOOFRND = iRow * iCol - 1;
        int iLoopCount = 0;
        int iResult = 0;
        while (iLoopCount < iNOOFRND) {
            iResult = 1 + (int) (iNOOFRND * Math.random());
            if (!bFound(myRandom, iResult, iLoopCount)) {
                myRandom[iLoopCount] = iResult;
                iLoopCount++;
            }
        }
        myRandom[iRow * iCol - 1] = 0;
    }
     private  boolean bFound(int iA[], int iR, int iLimit) {//檢查是否解答完成
        for (int i = 0; i <= iLimit; i++) {if (iA[i] == iR) {return true;}}
            return false;                                        
    }
     private void btnCheck(JButton mb) {
        for (int i = 0; i < iRow; i++) {
            for (int j = 0; j < iCol; j++) {
                if (mb == jbGame[i][j]) {
                        jbTarget = jbGame[i][j];
                        btnChange(jbSource, jbTarget);  //呼叫btnChange()來動移按鈕                      
                }
            }
        }
    }
     private void setGame() {
        jbGame[iRow - 1][iCol - 1].setText((iRow*iCol) + "");  //將最後一個按鈕文字改為數字9
        jbGame[iRow - 1][iCol - 1].setBackground(Color.GRAY); //修改最後一按鈕顏色
        jbGame[iRow - 1][iCol - 1].setFocusable(true); //將駐點放在最後一個按鈕上
        jbSource = jbGame[iRow - 1][iCol - 1];  //記錄最後一按鈕為移動視窗按鈕     
    }    
    private void btnChange(JButton jbSource, JButton jbTarget) {
        String tmp = jbSource.getText();   //將來源端按鈕上之數字存進 tmp中
        jbSource.setText(jbTarget.getText());    //將來源端按鈕文字變成目的端按鈕文字
        jbTarget.setText(tmp);    //將目的端按鈕文字變成 tmp值
        jbSource.setBackground(Color.YELLOW); // 來源端變橘色
        jbTarget.setBackground(Color.GRAY); // 目的端變藍色
        this.jbSource = jbTarget;  //將記錄按鈕位址存為目的端
        checkWin();  //檢查是否勝利
    }
    private void getEastJPanel() {
        jpEast.removeAll();      
        jpEast.setLayout(new BorderLayout());
        js = new JScrollPane(jta);
        jpEast.add(js);
        this.add(jpEast,BorderLayout.EAST);  
        jta.setText(m.getResult());
        pack();
    }
    private void checkWin() {//確認是否獲勝
        String sNow = "";
        for (int i = 0; i < iRow; i++) {
            for (int j = 0; j < iCol; j++) {
                sNow += jbGame[i][j].getText();  //取得nowStr目前btn狀態字串
            }
        }  
        String sCheck[] = m.getCheck();//取出四組解答     
        for (int i = 0; i < sCheck.length; i++) {//巡邏檢查
            if (sNow.equals(sCheck[i])) {
            JOptionPane.showMessageDialog(this, "恭喜過關");
            break;
            }
        }
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == jbStart){Start();}
        else if (e.getSource() == jbResult){
            getEastJPanel();             
            jbResult.setEnabled(false);
            jbStart.setEnabled(true);
            jpWest.removeAll();
            this.validate();
        }else if (e.getSource() == jCom){Start();}   
        else if (e.getSource() == jbExplain){
            JOptionPane.showMessageDialog(this, "點擊黃色格子會與灰色格子互換\n直到上下左右及對角數字相加相等就可過關");
        }
     }          
    public static void main(String[] args) {
        final StyleBox_View sv = new StyleBox_View();
        sv.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        sv.addWindowStateListener(new WindowStateListener() {
            @Override
            public void windowStateChanged(WindowEvent e) {
                sv.pack();
            }
        });
    }   
}
(四)檔案下載

沒有留言:

張貼留言