程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> J2ME連連看基礎功能源代碼(含詳細注釋)

J2ME連連看基礎功能源代碼(含詳細注釋)

編輯:J2ME
J2ME連連看基礎功能源代碼(含詳細注釋) 作者:陳躍峰    文章來源:blog.csdn.net/mailbomb    更新時間:2008-4-26 12:09:15 554 //界面類代碼
import Javax.microedition.lcdui.Canvas;
import Javax.microedition.lcdui.Graphics;

/**
 * 連連看游戲界面
 */
public class LinkCanvas extends Canvas implements Runnable{
    /**游戲邏輯類*/
    GameEngine engine;   
    /**屏幕寬度*/
    int width;
    /**屏幕高度*/
    int height;
    public LinkCanvas(){
        //創建對象
        engine = new GameEngine();
        //獲得屏幕的高度和寬度
        width = getWidth();
        height = getHeight();
        //啟動線程
        Thread t = new Thread(this);
        t.start();
    }
   
    /**
     * 繪制方法
     */
    protected void paint(Graphics g) {
        //清屏
        clearScreen(g);
        //繪制地圖
        engine.paintMap(g);
        //繪制選擇框
        engine.paintSelectArea(g);
        //繪制連線
        engine.paintLinkLine(g);
    }
   
    /**
     * 清屏方法
     * @param g 畫筆
     */
    private void clearScreen(Graphics g){
        g.setColor(0xffffff);
        g.fillRect(0, 0, width, height);
        g.setColor(0);
    }
   
    public void keyPressed(int keyCode){
        int action = getGameAction(keyCode);
        switch(action){
        case UP:
            engine.moveUP();
            break;
        case DOWN:
            engine.moveDown();
            break;
        case LEFT:
            engine.moveLeft();
            break;
        case RIGHT:
            engine.moveRight();
            break;
        case FIRE:
            engine.fire();//選擇塊
            break;
        }
    }

    public void run() {
        try{
            while(true){
                //延時
                Thread.sleep(100);
                //每次判斷邏輯
                engine.action();
                repaint();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

//邏輯類源代碼
import Java.util.*;
import Javax.microedition.lcdui.*;
/**
 * 游戲數據和邏輯類
 */
public class GameEngine {
    /**選中塊的個數*/
    private int selectTileNum = 0;
    //第一個選擇塊的行號和列號
    /**行號*/
    private int firstRow;
    /**列號*/
    private int firstCol;
    //第二個選擇塊的行號和列號
    /**行號*/
    private int secondRow;
    /**列號*/
    private int secondCol;
   
    //當前選擇框,默認在左上角
    /**當前選擇框的行號*/
    private int cRow;
    /**當前選擇框的列號*/
    private int cCol;
   
    /**最大行數*/
    private final int MAX_ROW = 10;
    /**最大列數*/
    private final int MAX_COL = 10;
   
    /**地圖數據,0代表空,數據1-10分別代表十種不同的結構*/
    private int[][] map = new int[MAX_ROW][MAX_COL];
    /**隨機數對象*/
    private Random ran = new Random();
   
    //地圖區域左上角的坐標
    private final int LEFTX = 20;
    private final int LEFTY = 50;
   
    /**每個單元格的寬度*/
    private final int TILE_WIDTH = 20;
    /**每個單元格的高度*/
    private final int TILE_HEIGHT = 20;
   
    /**連線類型*/
    private int linkType;
   
    /**無法連線*/
    private final int NO_LINK = 0;
    /**水平連線*/
    private final int H_LINK = 1;
    /**垂直聯系*/
    private final int V_LINK = 2;
    /**一個拐點,先移動x*/
    private final int ONE_CORNER_FIRSTX = 3;
    /**一個拐點,先移動y*/
    private final int ONE_CORNER_FIRSTY = 4;
    /**兩個拐點,待完善*/
    private final int TWO_CORNER = 5;
   
    /**
     * 兩次拐彎的行號和列號
     * 數據格式為:
     *   第一個拐點的行號,第一個拐點的列號,第二個拐點的行號,第二個拐點的列號
     */
    int[] p = new int[4];
   
    public GameEngine(){
        //初始化地圖數據
        initMap();
    }
   
    /**
     * 初始化地圖數據
     */
    private void initMap(){
        for(int row = 0;row < map.length;row++){
            for(int col = 0;col < map[row].length;col++){
                map[row][col] = row + 1;
            }
        }
        //循環打亂10次
        int tempRow;
        int tempCol;
        int temp;
        for(int i = 0;i < 10;i++){
            for(int row = 0;row < map.length;row++){
                for(int col = 0;col < map[row].length;col++){
                    //隨機行號
                    tempRow = Math.abs(ran.nextInt() % 10);
                    //隨機列號
                    tempCol = Math.abs(ran.nextInt() % 10);
                    //如果不是同一個單元格,則交換數據
                    if(!((tempRow == row) && (tempCol == col))){
                        temp = map[row][col];
                        map[row][col] = map[tempRow][tempCol];
                        map[tempRow][tempCol] = temp;
                    }
                }
            }
        }
    }
   
    /**
     * 繪制地圖數據
     * @param g 畫筆
     */
    public void paintMap(Graphics g){
        for(int row = 0;row < map.length;row++){
            for(int col = 0;col < map[row].length;col++){
                //如果沒有數據,則跳過
                if(map[row][col] == 0){
                    continue;
                }else{//繪制方塊
                    //繪制方框
                    g.drawRect(LEFTX + col * TILE_WIDTH, LEFTY + row * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
                    //繪制數字
                    g.drawString(String.valueOf(map[row][col]), LEFTX + col * TILE_WIDTH + 5,
                            LEFTY + row * TILE_HEIGHT + 4,
                            Graphics.TOP | Graphics.LEFT);
                }
            }
        }
    }
   
    /**
     * 繪制選擇框
     * @param g 畫筆
     */
    public void paintSelectArea(Graphics g){
        //繪制當前選擇框
        g.setColor(0xff00);
        g.drawRect(LEFTX + cCol * TILE_WIDTH, LEFTY + cRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
        g.setColor(0);
       
        //繪制選中項
        switch(selectTileNum){
        case 1:  //選擇一個
            g.setColor(0xff0000);
            g.drawRect(LEFTX + firstCol * TILE_WIDTH, LEFTY + firstRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
            g.setColor(0);
            break;
        case 2:  //選中兩個
            g.setColor(0xff0000);
            g.drawRect(LEFTX + firstCol * TILE_WIDTH, LEFTY + firstRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
            g.drawRect(LEFTX + secondCol * TILE_WIDTH, LEFTY + secondRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
            g.setColor(0);
            break;
        }
    }
   
    /**
     * 繪制方塊連線
     * @param g 畫筆
     */
    public void paintLinkLine(Graphics g){
        //如果無連線,則直接返回
        if(linkType == NO_LINK){
            return;
        }
        //根據連線類型實現繪制
        //繪制到方塊的中心點
        switch(linkType){
        case H_LINK://水平
        case V_LINK://垂直
            paintLine(g,firstRow,firstCol,secondRow,secondCol);
            break;
        case ONE_CORNER_FIRSTX://一個拐彎,先移動X
            //水平線
            paintLine(g,firstRow,firstCol,firstRow,secondCol);
            //垂直線
            paintLine(g,firstRow,secondCol,secondRow,secondCol);
            break;
        case ONE_CORNER_FIRSTY://一個拐彎,先移動Y
            //水平線
            paintLine(g,firstRow,firstCol,secondRow,firstCol);
            //垂直線
            paintLine(g,secondRow,firstCol,secondRow,secondCol);
            break;
        case TWO_CORNER:
            //塊1到第一個拐點的連線
            paintLine(g,firstRow,firstCol,p[0],p[1]);
            //兩個拐點之間的連線
            paintLine(g,p[0],p[1],p[2],p[3]);
            //第二個拐點到塊2的連線
            paintLine(g,p[2],p[3],secondRow,secondCol);
            break;
        }
        //邏輯代碼,清除連接類型
        linkType = NO_LINK;
    }
   
    /**
     * 繪制兩個方塊中心點的連線
     * @param g  畫筆
     * @param r1 方塊1的行號
     * @param c1 方塊1的列號
     * @param r2 方塊2的行號
     * @param c2 方塊2的列號
     */
    private void paintLine(Graphics g,int r1,int c1,int r2,int c2){
        g.drawLine(LEFTX + c1 * TILE_WIDTH + TILE_WIDTH/2,
                LEFTY + r1 * TILE_HEIGHT + TILE_HEIGHT/2,
                LEFTX + c2 * TILE_WIDTH + TILE_WIDTH/2,
                LEFTY + r2 * TILE_HEIGHT + TILE_HEIGHT/2);
       
    }
   
    /**
     * 向左移動選擇框
     */
    public void moveLeft(){
        if(cCol > 0){
            cCol--;
        }
    }
   
    /**
     * 向右移動選擇框
     */
    public void moveRight(){
        if(cCol < MAX_COL -1){
            cCol++;
        }
    }
   
    /**
     * 向上移動選擇框
     */
    public void moveUP(){
        if(cRow > 0){
            cRow--;
        }
    }
   
    /**
     * 向下移動選擇框
     */
    public void moveDown(){
        if(cRow < MAX_ROW - 1){
            cRow++;
        }
    }
   
    /**
     * 確定鍵邏輯處理
     */
    public void fire(){
        //如果選擇的塊為空,則直接返回
        if(map[cRow][cCol] == 0){
            return;
        }
        //選中的塊的數量增加1
        selectTileNum++;
        //判別存儲位置
        switch(selectTileNum){
        case 1: //第一次選擇
            firstRow = cRow;
            firstCol = cCol;
            break;
        case 2: //第二次選擇
            //選擇同一個塊,2個選擇塊都失去選中
            if((firstRow == cRow) && (firstCol == cCol)){
                selectTileNum = 0;
                return;
            }
            secondRow = cRow;
            secondCol = cCol;
            break;
        }
    }
   
    /**
     * 判斷(r1,c1)塊和(r2,c2)塊中間是否為空行
     * 不包含這兩個塊
     * @param r1 塊1的行號
     * @param c1 塊1的列號
     * @param r2 塊2的行號
     * @param c2 塊2的列號
     * @return true代表為空,false代表不為空
     */     
    private boolean isEmptyRow(int r1,int c1,int r2,int c2){
        //判斷是否位於同一行
        if(r1 != r2){
            return false;
        }
        //判斷兩個塊的相對位置
        if(c1 > c2){ //第一塊位於右側
            for(int col = c1 - 1;col > c2;col--){
                //如果有非空塊
                if(map[r1][col] != 0){
                    return false;
                }
            }
        }else{ //第一塊位於左側
            for(int col = c2 - 1;col > c1;col--){
                //如果有非空塊
                if(map[r1][col] != 0){
                    return false;
                }
            }
        }
        return true;
    }
   
    /**
     * 判斷塊(r1,c1)和塊(r2,c2)之間是否是空列
     * 不包含這兩個塊
     * @param r1 塊1的行號
     * @param c1 塊1的列號
     * @param r2 塊2的行號
     * @param c2 塊2的列號
     * @return true代表為空,false代表不為空
     */
    private boolean isEmptyCol(int r1,int c1,int r2,int c2){
        //判斷是否位於同一列
        if(c1 != c2){
            return false;
        }
        //判斷兩個塊的相對位置
        if(r2 > r1){//第一個塊在上方
            for(int row = r1 + 1;row < r2;row++){
                //如果有非空塊
                if(map[row][c1] != 0){
                    return false;
                }
            }
        }else{//第二個塊在上方
            for(int row = r2 + 1;row < r1;row++){
                //如果有非空塊
                if(map[row][c1] != 0){
                    return false;
                }
            }
        }
        return true;
    }
   
    /**
     * 判斷一個塊是否為空
     * @param r 塊的行號
     * @param c 塊的列號
     * @return true代表為空,false代表不空
     */
    private boolean isEmptyCell(int r,int c){
        return map[r][c] == 0;
    }   
       
    /**
     * 是否是一次轉彎實現連線
     * @return NO_LINK代表沒有連線,其他值代表對應的連線類型
     */
    private int isOneCornerLink(int r1,int c1,int r2,int c2){
        //先移動行,再移動列
        if(isEmptyCell(r1,c2)){ //轉折點為空
            if(isEmptyRow(r1,c1,r1,c2) & isEmptyCol(r1,c2,r2,c2)){
                return ONE_CORNER_FIRSTX;
            }
        }
        //先移動列,再移動行
        if(isEmptyCell(r2,c1)){//轉折點為空
            if(isEmptyCol(r1,c1,r2,c1) & isEmptyRow(r2,c1,r2,c2)) {
                return ONE_CORNER_FIRSTY;
            }
        }
        //無連接
        return NO_LINK;
    }
   
    /**
     * 是否經過2次轉折實現連接
     * @param r1 塊1的行號
     * @param c1 塊1的列號
     * @param r2 塊2的行號
     * @param c2 塊2的列號
     * @return true代表可以連接,false代表不能
     */
    private boolean isTwoCornerLink(int r1,int c1,int r2,int c2){
        int result;
        //正常情況,劃分成4個方向
        //塊1向上
        for(int row = r1 -1;row >= 0;row--){
            //如果有數據不為空,則直接結束該方向的嘗試
            if(map[row][c1] != 0){
                break;
            }
            //存儲第一個拐點的坐標
            p[0] = row;
            p[1] = c1;
            //每次都嘗試轉折,則變成一個轉點的操作
            result = isOneCornerLink(row,c1,r2,c2);
            //如果可以連接
            if(result != NO_LINK){
                //存儲第二個拐點的位置
                switch(result){
                case ONE_CORNER_FIRSTX:
                    p[2] = row;
                    p[3] = c2;
                    break;
                case ONE_CORNER_FIRSTY:
                    p[2] = r2;
                    p[3] = c1;
                    break;
                }
                return true;
            }
        }
        //塊1向下
        for(int row = r1 + 1;row < MAX_ROW;row++){
            //如果有數據不為空,則直接結束該方向的嘗試
            if(map[row][c1] != 0){
                break;
            }
            //存儲第一個拐點的坐標
            p[0] = row;
            p[1] = c1;
            //每次都嘗試轉折,則變成一個轉點的操作
            result = isOneCornerLink(row,c1,r2,c2);
            //如果可以連接
            if(result != NO_LINK){
                //存儲第二個拐點的位置
                switch(result){
                case ONE_CORNER_FIRSTX:
                    p[2] = row;
                    p[3] = c2;
                    break;
                case ONE_CORNER_FIRSTY:
                    p[2] = r2;
                    p[3] = c1;
                    break;
                }
                return true;
            }
        }
        //塊1向左
        for(int col = c1 -1;col >= 0;col--){
            //如果有數據不為空,則直接結束該方向的嘗試
            if(map[r1][col] != 0){
                break;
            }
            //存儲第一個拐點的坐標
            p[0] = r1;
            p[1] = col;
            //每次都嘗試轉折,則變成一個轉點的操作
            result = isOneCornerLink(r1,col,r2,c2);
            //如果可以連接
            if(result != NO_LINK){
                //存儲第二個拐點的位置
                switch(result){
                case ONE_CORNER_FIRSTX:
                    p[2] = r1;
                    p[3] = c2;
                    break;
                case ONE_CORNER_FIRSTY:
                    p[2] = r2;
                    p[3] = col;
                    break;
                }
                return true;
            }
        }
        //塊1向右
        for(int col = c1  + 1;col < MAX_COL;col++){
            //如果有數據不為空,則直接結束該方向的嘗試
            if(map[r1][col] != 0){
                break;
            }
            //存儲第一個拐點的坐標
            p[0] = r1;
            p[1] = col;
            //每次都嘗試轉折,則變成一個轉點的操作
            result = isOneCornerLink(r1,col,r2,c2);
            //如果可以連接
            if(result != NO_LINK){
                //存儲第二個拐點的位置
                switch(result){
                case ONE_CORNER_FIRSTX:
                    p[2] = r1;
                    p[3] = c2;
                    break;
                case ONE_CORNER_FIRSTY:
                    p[2] = r2;
                    p[3] = col;
                    break;
                }
                return true;
            }
        }
       
        //四個特例,也就是超出地圖區域的連接
        //實現地圖區域上側的連接,也就是到上側是一個空列
        if((isEmptyCol(r1,c1,-1,c1)) & (isEmptyCol(r2,c2,-1,c2))){
            p[0] = -1;
            p[1] = c1;
            p[2] = -1;
            p[3] = c2;
            return true;
        }
        //左側
        if((isEmptyRow(r1,c1,r1,-1)) & (isEmptyRow(r2,c2,r2,-1))){
            p[0] = r1;
            p[1] = -1;
            p[2] = r2;
            p[3] = -1;
            return true;
        }
        //下側
        if((isEmptyCol(r1,c1,MAX_ROW,c1)) & (isEmptyCol(r2,c2,MAX_ROW,c2))){
            p[0] = MAX_ROW;
            p[1] = c1;
            p[2] = MAX_ROW;
            p[3] = c2;
            return true;
        }
        //右側
        if((isEmptyRow(r1,c1,r1,MAX_COL)) & (isEmptyRow(r2,c2,r2,MAX_COL))){
            p[0] = r1;
            p[1] = MAX_COL;
            p[2] = r2;
            p[3] = MAX_COL;
            return true;
        }       
        return false;
    }
   
    /**
     * 邏輯判斷是否有連線
     * @return NO_LINK代表無連線,其它數據代表有連線
     */
    private int logic(){
        //如果數值不同
        if(map[firstRow][firstCol] != map[secondRow][secondCol]){
            return NO_LINK;
        }
        //判斷連接方式
        if(isEmptyRow(firstRow,firstCol,secondRow,secondCol)){ //水平連線
            return H_LINK;
        }
        if(isEmptyCol(firstRow,firstCol,secondRow,secondCol)){//垂直連線
            return V_LINK;
        }
        //一個轉點的連接
        int result = isOneCornerLink(firstRow,firstCol,secondRow,secondCol);
        if(result != NO_LINK){
            return result;
        }
        //兩個轉點的連接
        if(isTwoCornerLink(firstRow,firstCol,secondRow,secondCol)){
            return TWO_CORNER;
        }       
        //返回無連接
        return NO_LINK;
    }
   
    /**
     * 邏輯判別和邏輯處理
     */
    public boolean action(){
        //判斷是否選擇兩個方塊
        if(selectTileNum != 2){
            return false;
        }
        boolean b = false;
        //判斷是否有連線
        linkType = logic();
        //如果有連線,則消失
        if(linkType != NO_LINK){
            map[firstRow][firstCol] = 0;
            map[secondRow][secondCol] = 0;
            b = true;
        }
        //選擇的塊數初始化
        selectTileNum = 0;
        return b;
    }
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved