public class Game {

    public Game(LevelCfg levelCfg, IGameAction listener) {
        this.levelCfg = levelCfg;
        this.listener = listener;
        this.gameStep = 0;
        this.gameStar = 0;
        gameStatus = new GameStatus(levelCfg, listener);
        gameService = new GameService(levelCfg);
        alignContext = new AlignContext(gameService.getPieces(), levelCfg.getLevelAlign());
    }

    /**
     * 开始游戏
     */
    public void start() {
        unCheck();
        gameStatus.start();
    }

    /**
     * 放弃游戏，不处理游戏结果
     */
    public void finish() {
        gameStatus.stop();
    }

    /**
     * 结束游戏，处理游戏结果（暂时未用）
     */
    public void stop() {
        finish();

        if (gameService.hasPieces()) {
            gameStatus.fail();
        } else {
            gameStatus.win();
        }
    }

    /**
     * 暂停游戏
     */
    public void pause() {
        gameStatus.pause();
    }

    /**
     * 重新开始游戏
     */
    public void resume() {
        gameStatus.resume();
    }

    /**
     * 处理玩家触摸点击
     * 
     * @param x
     *            横坐标
     * @param y
     *            纵坐标
     */
    public void click(float x, float y) {
        Piece piece = gameService.findPiece(x, y);

        // 点击相应卡片
        click(piece);
    }

    /**
     * 点击卡片时的处理
     * 
     * @param piece
     *            点击的卡片
     */
    public void click(Piece piece) {
        Piece curPiece = piece;
        if (curPiece == null) {
            return;
        }

        unPrompt();
        if (selected == curPiece || !Piece.canSelect(curPiece)) {
            if (selected != null) {
                unCheck();
            }
            return;
        }

        if (selected == null) {
            check(curPiece);
        } else {
            LinkInfo linkInfo = gameService.link(selected, curPiece);
            if (linkInfo == null) {
                unCheck();
                check(curPiece);
            } else {
                handleSuccess(linkInfo, selected, curPiece);
            }
        }
    }

    /**
     * 成功配对时的处理
     * 
     * @param linkInfo
     *            连接路径信息
     * @param prePiece
     *            前一个卡片信息
     * @param curPiece
     *            当前卡片信息
     */
    private void handleSuccess(LinkInfo linkInfo, Piece prePiece, Piece curPiece) {
        unCheck();
        Piece[][] pieces = gameService.getPieces();
        if (prePiece.isStar()) {
            gameStar++;
            if (listener != null) {
                listener.onStarChanged(gameStar);
            }
        }
        if (curPiece.isStar()) {
            gameStar++;
            if (listener != null) {
                listener.onStarChanged(gameStar);
            }
        }
        // pieces[prePiece.getIndexY()][prePiece.getIndexX()].setEmpty(true);
        // pieces[curPiece.getIndexY()][curPiece.getIndexX()].setEmpty(true);
        pieces[prePiece.getIndexY()][prePiece.getIndexX()].setImageId(GameSettings.GroundCardValue);
        pieces[curPiece.getIndexY()][curPiece.getIndexX()].setImageId(GameSettings.GroundCardValue);
        onLinkPath(linkInfo);

        if (alignContext != null) {
            alignContext.Translate(prePiece, curPiece);
            if (listener != null) {
                listener.onTranslate();
            }
        }
        gameStep++;
        if (listener != null) {
            listener.onStepChanged(gameStep);
        }
        if (listener != null) {
            listener.onErase();
        }
        // 如果收集了足够的星星，游戏胜利
        if (levelCfg.getStars() != 0 && gameStar == levelCfg.getStars()) {
            gameStatus.win();
        }
        // 如果没有了游戏块，游戏胜利
        if (!gameService.hasPieces()) {
            gameStatus.win();
        }
    }

    /**
     * 选择卡片
     * 
     * @param piece
     *            选中的卡片
     */
    public void check(Piece piece) {
        selected = piece;
        if (listener != null) {
            listener.onCheck(piece);
        }
    }

    /**
     * 取消卡片选择
     */
    public void unCheck() {
        if (listener != null) {
            listener.onUnCheck(selected);
        }
        selected = null;
    }

    /**
     * 连线路径处理
     * 
     * @param linkInfo
     *            连接路径信息
     */
    public void onLinkPath(LinkInfo linkInfo) {
        gameStatus.matchSuccess(linkInfo);
        if (listener != null) {
            listener.onLinkPath(linkInfo);
        }
    }

    /**
     * 游戏提示
     */
    public void prompt() {
        unCheck();
        pair = promptPair();
        gameStatus.prompt(pair);
    }

    /**
     * 获取当前提示的卡片对
     * 
     * @return 返回提示的卡片对，没有时返回null
     */
    private PiecePair promptPair() {
        Piece[][] pieces = gameService.getPieces();
        for (int i = 0; i < pieces.length * pieces[0].length; i++) {
            Piece p1 = pieces[i / pieces[0].length][i % pieces[0].length];
            if (Piece.canSelect(p1)) {
                for (int j = i + 1; j < pieces.length * pieces[0].length; j++) {
                    Piece p2 = pieces[j / pieces[0].length][j % pieces[0].length];
                    if (Piece.canSelect(p2) && p1.isSameImage(p2) && link(p1, p2) != null) {
                        return new PiecePair(p1, p2);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 判断是否死锁
     * 
     * @return 死锁：true
     */
    public boolean isDeadLock() {
        return promptPair() == null;
    }

    /**
     * 取消游戏提示
     */
    public void unPrompt() {
        if (pair != null) {
            gameStatus.unPrompt(pair);
            pair = null;
        }
    }

    /**
     * 游戏重排
     */
    public void refresh() {
        unPrompt();
        // 刷新后保证有消除,尝试固定次数，避免死循环
        for (int i = 0; i < GameSettings.RefreshTryCount; i++) {
            gameService.refresh();
            if (!isDeadLock()) {
                // 有可以消除时不继续重排
                break;
            }
        }
        gameStatus.refresh();
    }

    /**
     * 增加游戏时间
     * 
     * @param seconds
     *            游戏时间，单位：秒
     */
    public void addGameTime(int seconds) {
        gameStatus.addGameTime(seconds);
    }

    /**
     * 获取当前关卡配置信息
     * 
     * @return 当前关卡配置信息
     */
    public LevelCfg getLevelCfg() {
        return levelCfg;
    }

    /**
     * 获取游戏时间
     * 
     * @return 游戏时间
     */
    public int getGameTime() {
        return gameStatus.getGameTime();
    }

    /**
     * 获取游戏得分
     * 
     * @return 游戏得分
     */
    public int getGameScore() {
        return gameStatus.getGameScore();
    }

    /**
     * 获取游戏总得分
     * 
     * @return 游戏总得分
     */
    public int getTotalScore() {
        return getGameScore() + gameStatus.getRewardScore();
    }

    /**
     * 获取所有卡片信息
     */
    public Piece[][] getPieces() {
        return gameService.getPieces();
    }

    /**
     * 判断当前是否存在游戏卡片
     */
    public boolean hasPieces() {
        return gameService.hasPieces();
    }

    /**
     * 找到当前坐标点的卡片
     */
    public Piece findPiece(float x, float y) {
        return gameService.findPiece(x, y);
    }

    /**
     * 获取两个卡片间的路径信息，若不能消除，返回null
     */
    public LinkInfo link(Piece p1, Piece p2) {
        return gameService.link(p1, p2);
    }

    public int getGameStep() {
        return gameStep;
    }

    public int getGameStar() {
        return gameStar;
    }

    // 每消除一对算一步
    private int gameStep;
    private int gameStar;
    private LevelCfg levelCfg;
    private GameStatus gameStatus;
    private IGameAction listener;
    private Piece selected = null;
    private GameService gameService;
    private AlignContext alignContext = null;
    private PiecePair pair = null;
} public class GameSettings {

    /**
     * 地板卡片值
     */
    public static byte GroundCardValue = 0;

    /**
     * 游戏卡片值，用于地图模版
     */
    public static byte GameCardValue = 1;

    /**
     * 障碍卡片值
     */
    public static byte ObstacleCardValue = -1;

    /**
     * 空卡片值
     */
    public static byte EmptyCardValue = -2;

    /**
     * 消除卡片获得的积分，消除一对卡片得10分
     */
    public static int CardScore = 5;

    /**
     * 连击延时时间，2000ms
     */
    public static int ComboDelay = 2000;

    /**
     * 连击间隔，3连击，6连击，9连击。。。
     */
    public static int ComboMod = 3;

    /**
     * 连击分数，3连击则3*10=30
     */
    public static int ComboScore = 10;

    /**
     * 剩余时间奖励分数，剩余10s，则奖励40分
     */
    public static int TimeScore = 4;

    /**
     * 路径转弯奖励分数，直线不奖励，一个弯奖励5分，2个弯奖励10分
     */
    public static int CornerScore = 5;

    /**
     * 消除一对卡片奖励的时间，0s
     */
    public static int RewardTime = 0;

    /**
     * 减少时间奖励，补偿分数
     */
    public static int RewardScoreMax = 5;

    /**
     * 任务系数
     */
    public static int TaskFactor = 10;

    /**
     * 重排时尝试次数，默认5次
     */
    public static int RefreshTryCount = 5;

    /**
     * 星星的比例
     */
    public static float StarRatio = 0.4f;
} public interface IGameAction extends IGameStatus {

    /**
     * 选择卡片时的处理
     * 
     * @param piece
     *            选择的卡片信息
     */
    void onCheck(Piece piece);

    /**
     * 取消选择时的处理
     * 
     * @param piece
     *            取消选择的卡片信息
     */
    void onUnCheck(Piece piece);

    /**
     * 游戏卡片变换时的处理
     */
    void onTranslate();

    /**
     * 对连接路径的处理
     * 
     * @param linkInfo
     */
    void onLinkPath(LinkInfo linkInfo);

    /**
     * 消除后的处理，用于自动检测死锁
     */
    void onErase();

    /**
     * 游戏步数变化时的处理
     * 
     * @param step
     *            游戏步数
     */
    void onStepChanged(int step);

    /**
     * 游戏星星变化时的处理
     * 
     * @param star
     *            收集的星星数
     */
    void onStarChanged(int star);
} public class Piece {
    // private Bitmap image = null;
    private int imageId = 0;
    private int beginX = 0;
    private int beginY = 0;
    private int indexX = 0;
    private int indexY = 0;
    private int width = 40;
    private int height = 40;
    // private boolean isEmpty = false;
    private boolean isStar = false;

    public static int XSize = 0;
    public static int YSize = 0;

    public Piece(int indexY, int indexX) {
        this.indexY = indexY;
        this.indexX = indexX;
    }

    /**
     * 判断卡片与当前卡片是否为相同的图片
     * 
     * @param other
     *            要比较的卡片
     * @return 是相同的卡片则返回true
     */
    public boolean isSameImage(Piece other) {
        // if (image == null || other.image == null) {
        // return false;
        // }
        return getImageId() == other.getImageId();
    }

    /**
     * 获取卡片中心点
     * 
     * @return 卡片中心点信息
     */
    public Point getCenter() {
        return new Point(beginX + width / 2, beginY + height / 2);
    }

    /**
     * 获取卡片索引
     * 
     * @return 卡片索引
     */
    public int getIndex() {
        return getIndexY() * XSize + getIndexX();
    }

    /**
     * 交换卡片信息
     * 
     * @param other
     *            要交换的卡片
     */
    public void exchange(Piece other) {
        // Bitmap bm = getImage();
        // setImage(other.getImage());
        // other.setImage(bm);

        int imageId = getImageId();
        setImageId(other.getImageId());
        other.setImageId(imageId);

        // boolean isEmpty = isEmpty();
        // setEmpty(other.isEmpty());
        // other.setEmpty(isEmpty);

        boolean isStar = isStar();
        setStar(other.isStar());
        other.setStar(isStar);
    }

    /**
     * 判断卡片上是否有图片
     * 
     * @param piece
     *            卡片信息
     * @return 如果图片则返回true
     */
    public static boolean hasImage(Piece piece) {
        // return piece != null && !piece.isEmpty() && piece.getImageId() != GameSettings.GroundCardValue && piece.getImageId() != GameSettings.EmptyCardValue;
        return piece != null && piece.getImageId() != GameSettings.GroundCardValue && piece.getImageId() != GameSettings.EmptyCardValue;
    }

    /**
     * 判断卡片是否可以选择
     * 
     * @param piece
     *            卡片信息
     * @return 可以选择则返回true，与hasImage的区别是障碍卡片不能选择
     */
    public static boolean canSelect(Piece piece) {
        return hasImage(piece) && piece.getImageId() != GameSettings.ObstacleCardValue;
    }

    public static int getDistance(Piece p1, Piece p2) {
        return Math.abs(p1.getIndexX() - p2.getIndexX()) + Math.abs(p1.getIndexY() - p2.getIndexY());
    }

    // public Bitmap getImage() {
    // return image;
    // }
    //
    // public void setImage(Bitmap image) {
    // this.image = image;
    // }

    public int getImageId() {
        return imageId;
    }

    public void setImageId(int imageId) {
        this.imageId = imageId;
    }

    public int getBeginX() {
        return beginX;
    }

    public void setBeginX(int beginX) {
        this.beginX = beginX;
    }

    public int getBeginY() {
        return beginY;
    }

    public void setBeginY(int beginY) {
        this.beginY = beginY;
    }

    public int getIndexX() {
        return indexX;
    }

    public void setIndexX(int indexX) {
        this.indexX = indexX;
    }

    public int getIndexY() {
        return indexY;
    }

    public void setIndexY(int indexY) {
        this.indexY = indexY;
    }

    // private boolean isEmpty() {
    // return isEmpty;
    // }
    //
    // public void setEmpty(boolean isEmpty) {
    // this.isEmpty = isEmpty;
    // }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public boolean isStar() {
        return isStar;
    }

    public void setStar(boolean isStar) {
        this.isStar = isStar;
    }
} public class PiecePair {
    public PiecePair(Piece p1, Piece p2) {
        pieceOne = p1;
        pieceTwo = p2;
    }

    /**
     * 将卡片对排序，序号小的为pieceOne
     */
    public void sort() {
        if (pieceOne == null || pieceTwo == null) {
            return;
        }

        if (pieceOne.getIndex() > pieceTwo.getIndex()) {
            // 交换卡片对的位置
            Piece p = pieceOne;
            pieceOne = pieceTwo;
            pieceTwo = p;
        }
    }

    public Piece getPieceOne() {
        return pieceOne;
    }

    public void setPieceOne(Piece pieceOne) {
        this.pieceOne = pieceOne;
    }

    public Piece getPieceTwo() {
        return pieceTwo;
    }

    public void setPieceTwo(Piece pieceTwo) {
        this.pieceTwo = pieceTwo;
    }

    private Piece pieceOne;
    private Piece pieceTwo;
} public class LinkInfo {
    private List<Piece> linkPieces = new ArrayList<Piece>();

    public LinkInfo(Piece p1, Piece p2) {
        linkPieces.add(p1);
        linkPieces.add(p2);
    }

    public LinkInfo(Piece p1, Piece p2, Piece p3) {
        this(p1, p2);
        linkPieces.add(p3);
    }

    public LinkInfo(Piece p1, Piece p2, Piece p3, Piece p4) {
        this(p1, p2, p3);
        linkPieces.add(p4);
    }

    public List<Piece> getLinkPieces() {
        return linkPieces;
    }
} public enum GameAlign {
    AlignNone(0), AlignDown(1), AlignUp(2), AlignLeft(3), AlignRight(4), AlignRandom(5);

    private int value;

    GameAlign(int value) {
        this.value = value;
    }

    public static GameAlign valueOf(int align) {
        switch (align) {
        case 0:
            return AlignNone;
        case 1:
            return AlignDown;
        case 2:
            return AlignUp;
        case 3:
            return AlignLeft;
        case 4:
            return AlignRight;
        case 5:
            return AlignRandom;
        default:
            return AlignNone;
        }
    }

    public int value() {
        return this.value;
    }
} public enum GameMode {
    Level, Time, ScoreTask, TimeTask, Star, Endless;

    public static GameMode valueOf(int mode) {
        switch (mode) {
        case 1:
            return Time;
        case 2:
            return ScoreTask;
        case 3:
            return TimeTask;
        case 4:
            return Star;
        case 5:
            return Endless;
        default:
            return Level;
        }
    }
} public class LevelCfg implements Serializable {

    private static final long serialVersionUID = 2145150870959932172L;

    /**
     * 静态全局配置
     */
    public static GlobalCfg globalCfg = new GlobalCfg();

    public LevelCfg(String levelName) {
        this.levelName = levelName;
    }

    private int levelId;
    private String levelName;
    private String rankName;
    private String gameSkin;
    private int xSize;
    private int ySize;
    private int levelTime;
    private GameMode levelMode;
    // 任务目标
    private int scoreTask;
    private int timeTask;
    private GameAlign levelAlign;
    private int maxScore;
    private int minTime;
    private boolean isActive;
    private int levelStar;
    private boolean isUpload = false;
    private int[] starScores = null;
    private int emptyNum;
    private int obstacleNum;
    private int pieceWidth;
    private int pieceHeight;
    private int beginImageX;
    private int beginImageY;
    private int levelBackground;
    // 关卡地图信息字符串
    private String maptplStr;
    // 星星模式的星星数
    private int stars = 0;
    // 是否已根据屏幕调整
    private boolean isAdjust = false;

    /**
     * 初始化游戏星级的临界分数
     */
    public void initStarScores() {
        int cardCount = (xSize - 2) * (ySize - 2) - emptyNum - obstacleNum;
        if (starScores == null) {
            starScores = new int[3];
            int min = cardCount * GameSettings.CardScore + levelTime * GameSettings.TimeScore / 2;
            starScores[1] = min + GameSettings.CornerScore * cardCount / 2;
            starScores[0] = (min + starScores[1]) / 2;
            starScores[2] = starScores[1] + levelTime * GameSettings.TimeScore / 2;
        }
        // 设置任务为2颗星的分数值
        scoreTask = cardCount * GameSettings.TaskFactor;
        // 设置计时任务
        timeTask = levelTime;

        if (levelMode == GameMode.Star) {
            // 一半的星星
            stars = (int) (cardCount * GameSettings.StarRatio);
        }
    }

    /**
     * 根据游戏得分判断游戏星级
     * 
     * @param score
     *            游戏得分
     * @return 游戏星级
     */
    public int getStar(int score) {
        if (score < starScores[0])
            return 0;
        else if (score < starScores[1])
            return 1;
        else if (score < starScores[2])
            return 2;
        else
            return 3;
    }

    public int getLevelId() {
        return levelId;
    }

    public void setLevelId(int levelId) {
        this.levelId = levelId;
    }

    public String getLevelName() {
        return levelName;
    }

    public void setLevelName(String levelName) {
        this.levelName = levelName;
    }

    public String getRankName() {
        return rankName;
    }

    public void setRankName(String rankName) {
        this.rankName = rankName;
    }

    public GameMode getLevelMode() {
        return levelMode;
    }

    public void setLevelMode(GameMode levelMode) {
        this.levelMode = levelMode;
    }

    public int getScoreTask() {
        return scoreTask;
    }

    public void setScoreTask(int scoreTask) {
        this.scoreTask = scoreTask;
    }

    public int getTimeTask() {
        return timeTask;
    }

    public void setTimeTask(int timeTask) {
        this.timeTask = timeTask;
    }

    public String getGameSkin() {
        return gameSkin;
    }

    public void setGameSkin(String gameSkin) {
        this.gameSkin = gameSkin;
    }

    public int getXSize() {
        return xSize;
    }

    public void setXSize(int xSize) {
        this.xSize = xSize;
    }

    public int getYSize() {
        return ySize;
    }

    public void setYSize(int ySize) {
        this.ySize = ySize;
    }

    public int getMaxScore() {
        return maxScore;
    }

    public void setMaxScore(int maxScore) {
        this.maxScore = maxScore;
    }

    public int getMinTime() {
        return minTime;
    }

    public void setMinTime(int minTime) {
        this.minTime = minTime;
    }

    public int getLevelTime() {
        return levelTime;
    }

    public void setLevelTime(int levelTime) {
        this.levelTime = levelTime;
    }

    public GameAlign getLevelAlign() {
        return levelAlign;
    }

    public void setLevelAlign(GameAlign levelAlign) {
        this.levelAlign = levelAlign;
    }

    public boolean isActive() {
        return isActive;
    }

    public void setActive(boolean isActive) {
        this.isActive = isActive;
    }

    public int getLevelStar() {
        return levelStar;
    }

    public void setLevelStar(int levelStar) {
        this.levelStar = levelStar;
    }

    public boolean isUpload() {
        return isUpload;
    }

    public void setUpload(boolean isUpload) {
        this.isUpload = isUpload;
    }

    public int[] getStarScores() {
        return starScores;
    }

    public void setStarScores(int[] starScores) {
        this.starScores = starScores;
    }

    public int getEmptyNum() {
        return emptyNum;
    }

    public void setEmptyNum(int emptyNum) {
        this.emptyNum = emptyNum;
    }

    public int getObstacleNum() {
        return obstacleNum;
    }

    public void setObstacleNum(int obstacleNum) {
        this.obstacleNum = obstacleNum;
    }

    public int getPieceWidth() {
        return pieceWidth;
    }

    public void setPieceWidth(int pieceWidth) {
        this.pieceWidth = pieceWidth;
    }

    public int getPieceHeight() {
        return pieceHeight;
    }

    public void setPieceHeight(int pieceHeight) {
        this.pieceHeight = pieceHeight;
    }

    public int getBeginImageX() {
        return beginImageX;
    }

    public void setBeginImageX(int beginImageX) {
        this.beginImageX = beginImageX;
    }

    public int getBeginImageY() {
        return beginImageY;
    }

    public void setBeginImageY(int beginImageY) {
        this.beginImageY = beginImageY;
    }

    public int getLevelBackground() {
        return levelBackground;
    }

    public void setLevelBackground(int levelBackground) {
        this.levelBackground = levelBackground;
    }

    public String getMaptplStr() {
        return maptplStr;
    }

    public void setMaptplStr(String maptplStr) {
        this.maptplStr = maptplStr;
    }

    public int getStars() {
        return stars;
    }

    public void setStars(int stars) {
        this.stars = stars;
    }

    public boolean isAdjust() {
        return isAdjust;
    }

    public void setAdjust(boolean isAdjust) {
        this.isAdjust = isAdjust;
    }
} public class DbScore {

    private static DbHelper database = null;

    public static void init(Context context, List<ModeCfg> modeCfgs) {
        database = new DbHelper(context, modeCfgs);
    }

    /**
     * 更新关卡数据
     * 
     * @param levelScore
     *            关卡数据
     */
    public static void updateScore(LevelScore levelScore) {
        SQLiteDatabase db = database.getWritableDatabase();
        String sql = "update scores set maxscore=?,mintime=?, star=? where level=?";
        db.execSQL(sql, new Object[] { levelScore.getMaxScore(), levelScore.getMinTime(), levelScore.getStar(), levelScore.getLevel() });
        db.close();
    }

    /**
     * 激活关卡
     * 
     * @param levelScore
     *            关卡数据
     */
    public static void updateActive(LevelScore levelScore) {
        SQLiteDatabase db = database.getWritableDatabase();
        String sql = "update scores set isactive=? where level=?";
        db.execSQL(sql, new Object[] { levelScore.getIsActive(), levelScore.getLevel() });
        db.close();
    }

    /**
     * 是否上传网络
     * 
     * @param levelScore
     *            关卡数据
     */
    public static void updateUpload(LevelScore levelScore) {
        SQLiteDatabase db = database.getWritableDatabase();
        String sql = "update scores set isupload=? where level=?";
        db.execSQL(sql, new Object[] { levelScore.getIsUpload(), levelScore.getLevel() });
        db.close();
    }

    /**
     * 根据关卡id删除关卡数据（未用）
     * 
     * @param level
     *            关卡id
     */
    public static void delete(String level) {
        SQLiteDatabase db = database.getWritableDatabase();
        String sql = "delete from scores where level=?";
        db.execSQL(sql, new Object[] { level });
        db.close();
    }

    /**
     * 根据关卡id获取最高分
     * 
     * @param level
     *            关卡id
     * @return 关卡最高分
     */
    public static int selectMaxScore(String level) {
        SQLiteDatabase db = database.getReadableDatabase();
        String sql = "select maxscore from scores where level=?";
        try {
            Cursor cursor = db.rawQuery(sql, new String[] { level });
            if (cursor.moveToFirst()) {
                return cursor.getInt(cursor.getColumnIndex("maxscore"));
            }
            return 0;
        } finally {
            db.close();
        }
    }

    /**
     * 获取所有关卡数据信息，用于初始化时加载
     * 
     * @return 所有关卡数据信息
     */
    public static List<LevelScore> selectAll() {
        SQLiteDatabase db = database.getReadableDatabase();
        String sql = "select level, rank, maxscore, mintime, isactive, star, isupload from scores order by level";
        try {
            Cursor cursor = db.rawQuery(sql, new String[] {});
            List<LevelScore> levelScores = new ArrayList<LevelScore>();
            while (cursor.moveToNext()) {
                LevelScore ls = new LevelScore(cursor.getString(0), cursor.getString(1), cursor.getInt(2), cursor.getInt(3), cursor.getInt(4), cursor.getInt(5));
                ls.setIsUpload(cursor.getInt(6));
                levelScores.add(ls);
            }
            return levelScores;
        } finally {
            db.close();
        }
    }

    /**
     * 获取游戏等级（rank）中激活的关卡数
     * 
     * @param rank
     *            游戏等级
     * @return 激活的关卡数
     */
    public static int selectLevelByRank(String rank) {
        SQLiteDatabase db = database.getReadableDatabase();
        String sql = "select count(*) from scores where isactive=1 and rank=?";
        try {
            Cursor cursor = db.rawQuery(sql, new String[] { rank });
            if (cursor.moveToFirst()) {
                return cursor.getInt(0);
            }
            return 0;
        } finally {
            db.close();
        }
    }

    /**
     * 获取游戏等级（rank）中关卡的所有星级
     * 
     * @param rank
     *            游戏等级
     * @return 所有星级和
     */
    public static int selectStarByRank(String rank) {
        SQLiteDatabase db = database.getReadableDatabase();
        String sql = "select sum(star) from scores where isactive=1 and rank=?";
        try {
            Cursor cursor = db.rawQuery(sql, new String[] { rank });
            if (cursor.moveToFirst()) {
                return cursor.getInt(0);
            }
            return 0;
        } finally {
            db.close();
        }
    }
} public class LevelScore {
    public LevelScore(int level) {
        this.level = String.valueOf(level);
    }

    public LevelScore(String level) {
        this.level = level;
    }

    public LevelScore(String level, String rank, int maxScore, int minTime, int isActive, int star) {
        this.level = level;
        this.rank = rank;
        this.maxScore = maxScore;
        this.minTime = minTime;
        this.isActive = isActive;
        this.star = star;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    public String getRank() {
        return rank;
    }

    public void setRank(String rank) {
        this.rank = rank;
    }

    public int getMaxScore() {
        return maxScore;
    }

    public void setMaxScore(int maxScore) {
        this.maxScore = maxScore;
    }

    public int getMinTime() {
        return minTime;
    }

    public void setMinTime(int minTime) {
        this.minTime = minTime;
    }

    public int getIsActive() {
        return isActive;
    }

    public void setIsActive(int isActive) {
        this.isActive = isActive;
    }

    public int getStar() {
        return star;
    }

    public void setStar(int star) {
        this.star = star;
    }

    public int getIsUpload() {
        return isUpload;
    }

    public void setIsUpload(int isUpload) {
        this.isUpload = isUpload;
    }

    private String level;
    private String rank;
    private int maxScore;
    private int minTime;
    private int isActive;
    private int star;
    private int isUpload = 0;

} public class AnimatorUtil {

    private static int defaultDuration = 500;

    /**
     * 设置view的透明度
     * 
     * @param view
     *            参与动画的view
     * @param fromAlpha
     *            起始透明度
     * @param toAlpha
     *            结束透明度
     */
    public static void animAlpha(View view, float fromAlpha, float toAlpha) {
        animAlpha(view, fromAlpha, toAlpha, defaultDuration);
    }

    /**
     * 设置view的透明度
     * 
     * @param view
     *            参与动画的view
     * @param fromAlpha
     *            起始透明度
     * @param toAlpha
     *            结束透明度
     * @param duration
     *            动画时长
     */
    public static void animAlpha(View view, float fromAlpha, float toAlpha, int duration) {
        ObjectAnimator.ofFloat(view, "alpha", fromAlpha, toAlpha).setDuration(duration).start();
    }

    /**
     * 设置view的透明度
     * 
     * @param view
     *            参与动画的view
     * @param fromAlpha
     *            起始透明度
     * @param toAlpha
     *            结束透明度
     * @param duration
     *            动画时长
     * @param delay
     *            动画延迟
     */
    public static void animAlpha(View view, float fromAlpha, float toAlpha, int duration, int delay) {
        Animator anim = ObjectAnimator.ofFloat(view, "alpha", fromAlpha, toAlpha).setDuration(duration);
        anim.setStartDelay(delay);
        anim.start();
    }

    /**
     * 缩放动画
     * 
     * @param view
     *            执行动画的view
     * @param fromX
     *            X开始的比例
     * @param toX
     *            X缩放比例
     * @param fromY
     *            Y开始的比例
     * @param toY
     *            Y缩放比例
     */
    public static void animScale(View view, float fromX, float toX, float fromY, float toY) {
        animScale(view, fromX, toX, fromY, toY, defaultDuration);
    }

    /**
     * 缩放动画
     * 
     * @param view
     *            执行动画的view
     * @param fromX
     *            X开始的比例
     * @param toX
     *            X缩放比例
     * @param fromY
     *            Y开始的比例
     * @param toY
     *            Y缩放比例
     * @param duration
     *            动画时长
     */
    public static void animScale(View view, float fromX, float toX, float fromY, float toY, int duration) {
        ObjectAnimator.ofFloat(view, "scaleX", fromX, toX).setDuration(duration).start();
        ObjectAnimator.ofFloat(view, "scaleY", fromY, toY).setDuration(duration).start();
    }

    /**
     * 旋转动画
     * 
     * @param view
     *            执行动画的view
     * @param fromDegrees
     *            起始角度
     * @param toDegrees
     *            结束角度
     */
    public static void animRotate(View view, float fromDegrees, float toDegrees) {
        animRotate(view, fromDegrees, toDegrees, defaultDuration);
    }

    /**
     * 旋转动画
     * 
     * @param view
     *            执行动画的view
     * @param fromDegrees
     *            起始角度
     * @param toDegrees
     *            结束角度
     * @param duration
     *            动画时长
     */
    public static void animRotate(View view, float fromDegrees, float toDegrees, int duration) {
        ObjectAnimator.ofFloat(view, "rotation", fromDegrees, toDegrees).setDuration(duration).start();
    }

    /**
     * 平移动画
     * 
     * @param view
     *            执行动画的view
     * @param fromX
     *            起始X坐标
     * @param toX
     *            结束X坐标
     * @param fromY
     *            起始Y坐标
     * @param toY
     *            结束Y坐标
     */
    public static void animTranslate(View view, float fromX, float toX, float fromY, float toY) {
        animTranslate(view, fromX, toX, fromY, toY, defaultDuration, 0, false);
    }

    /**
     * 平移动画
     * 
     * @param view
     *            执行动画的view
     * @param fromX
     *            起始X坐标
     * @param toX
     *            结束X坐标
     * @param fromY
     *            起始Y坐标
     * @param toY
     *            结束Y坐标
     * @param duration
     *            动画时长
     */
    public static void animTranslate(View view, float fromX, float toX, float fromY, float toY, int duration, int delay, boolean isHide) {
        Animator animX = ObjectAnimator.ofFloat(view, "translationX", fromX, toX).setDuration(duration);
        Animator animY = ObjectAnimator.ofFloat(view, "translationY", fromY, toY).setDuration(duration);

        if (fromX != toX) {
            animX.setStartDelay(delay);
            animX.start();
        } else {
            view.setTranslationX(fromX);
        }
        if (fromY != toY) {
            animY.setStartDelay(delay);
            if (isHide) {
                animY.addListener(new HideAnimator(view));
            }
            animY.start();
        } else {
            view.setTranslationY(fromY);
        }
    }

} public class Stopwatch {

    private long startTime = 0;
    private long stopTime = 0;
    private boolean running = false;

    public void start() {
        this.startTime = System.currentTimeMillis();
        this.running = true;
    }

    public void stop() {
        this.stopTime = System.currentTimeMillis();
        this.running = false;
    }

    /**
     *  elaspsed time in milliseconds
     *  @return elaspsed time in milliseconds
     */
    public long getElapsedTime() {
        long elapsed;
        if (running) {
            elapsed = (System.currentTimeMillis() - startTime);
        } else {
            elapsed = (stopTime - startTime);
        }
        return elapsed;
    }

    /**
     *  elaspsed time in seconds
     * @return elaspsed time in seconds
     */
    public long getElapsedTimeSecs() {
        long elapsed;
        if (running) {
            elapsed = ((System.currentTimeMillis() - startTime) / 1000);
        } else {
            elapsed = ((stopTime - startTime) / 1000);
        }
        return elapsed;
    }

    // sample usage
    public static void main(String[] args) {
        Stopwatch s = new Stopwatch();
        s.start();
        // code you want to time goes here
        s.stop();
        System.out.println("elapsed time in milliseconds: " + s.getElapsedTime());
    }
} public class StringUtil {

    /**
     * 判断null或者空
     * 
     * @param str
     *            字符串
     * @return
     */
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.equals("");
    }

    /**
     * 转为UTF-8编码
     * 
     * @param str
     *            字符串
     * @return utf-8编码字符串
     */
    public static String toUtf8(String str) {
        try {
            return new String(str.getBytes("ISO8859_1"), "UTF-8");
        } catch (Exception e) {
            Log.d("StringUtil-toUtf8", e.getMessage());
            return str;
        }
    }

    /**
     * 将时间秒数转化为格式mm:ss
     * 
     * @param seconds
     *            时间秒数
     * @return 时间格式字符串
     */
    public static String secondToString(int seconds) {
        int min = seconds / 60;
        int second = seconds % 60;

        StringBuffer sb = new StringBuffer();
        if (min > 9) {
            sb.append(String.valueOf(min));
        } else {
            sb.append("0" + String.valueOf(min));
        }

        if (second > 9) {
            sb.append(":" + String.valueOf(second));
        } else {
            sb.append(":0" + String.valueOf(second));
        }

        return sb.toString();
    }

    public static String substring(String str, int toCount) {
        return substring(str, toCount, "..");
    }

    /**
     * 获取符合长度的字符串
     * 
     * @param str
     *            需要控制长度的字符串
     * @param toCount
     *            长度
     * @param more
     *            超过长度字符
     * @return 符合长度的字符串
     */
    public static String substring(String str, int len, String more) {
        if (str == null || "".equals(str) || len < 1) {
            return "";
        }
        char[] chars = str.toCharArray();
        int count = 0;
        int charIndex = 0;
        for (int i = 0; i < chars.length; i++) {
            int charLength = getCharLen(chars[i]);
            if (count <= len - charLength) {
                count += charLength;
                charIndex++;
            } else {
                break;
            }
        }
        if (charIndex == chars.length) {
            return new String(chars, 0, charIndex);
        } else {
            return new String(chars, 0, charIndex) + more;
        }
    }

    /**
     * 获取字符长度
     * 
     * @param c
     *            字符
     * @return 长度
     */
    private static int getCharLen(char c) {
        int k = 0x80;
        return c / k == 0 ? 1 : 2;
    }
} @SuppressLint("ShowToast")
public class ToastUtil {

    /**
     * 根据字符串资源id获取toast
     * 
     * @param ctx
     *            上下文
     * @param resId
     *            资源id
     * @return Toast对象
     */
    public static Toast getToast(Context ctx, int resId) {
        String msg = ctx.getResources().getString(resId);
        return getToast(ctx, msg);
    }

    /**
     * 根据字符串获取toast
     * 
     * @param ctx
     *            上下文
     * @param msg
     *            字符串
     * @return Toast对象
     */
    public static Toast getToast(Context ctx, String msg) {
        Toast mToast = Toast.makeText(ctx, msg, Toast.LENGTH_SHORT);
        mToast.setText(msg);
        mToast.setGravity(Gravity.BOTTOM | Gravity.CENTER, 0, 20);
        mToast.setDuration(Toast.LENGTH_SHORT);
        return mToast;
    }
} public class CardsView extends RelativeLayout {

    public CardsView(Context context) {
        super(context);
    }

    public CardsView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setGame(Game game) {
        this.game = game;

        // 加载界面图片
        // String skinName = game.getLevelCfg().getGameSkin();
        // loadImages(skinName);

        // 生成游戏卡片
        createCards(false);
    }

    /**
     * 选择卡片
     * 
     * @param piece
     */
    public void check(Piece piece) {
        gameCards[piece.getIndexY()][piece.getIndexX()].setChecked(true);
    }

    /**
     * 取消选择卡片
     * 
     * @param piece
     */
    public void unCheck(Piece piece) {
        gameCards[piece.getIndexY()][piece.getIndexX()].setChecked(false);
    }

    /**
     * 提示卡片对
     * 
     * @param pair
     */
    public void prompt(PiecePair pair) {
        gameCards[pair.getPieceOne().getIndexY()][pair.getPieceOne().getIndexX()].prompt();
        gameCards[pair.getPieceTwo().getIndexY()][pair.getPieceTwo().getIndexX()].prompt();
    }

    /**
     * 取消提示卡片对
     * 
     * @param pair
     */
    public void unPrompt(PiecePair pair) {
        gameCards[pair.getPieceOne().getIndexY()][pair.getPieceOne().getIndexX()].unPrompt();
        gameCards[pair.getPieceTwo().getIndexY()][pair.getPieceTwo().getIndexX()].unPrompt();
    }

    /**
     * 移除卡片
     * 
     * @param piece
     */
    public void erase(Piece piece) {
        removeView(gameCards[piece.getIndexY()][piece.getIndexX()]);
        gameCards[piece.getIndexY()][piece.getIndexX()] = null;
    }

    /**
     * 生成游戏卡片
     * 
     * @param isAnim
     *            是否应用动画
     */
    public void createCards(boolean isAnim) {
        String skinName = game.getLevelCfg().getGameSkin();
        List<Bitmap> scaleBitmaps = loadImages(skinName);
        removeAllViews();
        gameCards = new GameCard[game.getPieces().length][game.getPieces()[0].length];
        GameCard card = null;
        for (int i = 0; i < game.getPieces().length; i++) {
            for (int j = 0; j < game.getPieces()[i].length; j++) {
                Piece p = game.getPieces()[i][j];

                if (p.getImageId() != GameSettings.GroundCardValue) {
                    Bitmap pbm = null;
                    if (p.getImageId() == GameSettings.ObstacleCardValue) {
                        pbm = ImageUtil.scaleBitmap(obstacleBitmap, p.getWidth(), p.getHeight());
                    } else {
                        pbm = scaleBitmaps.get(p.getImageId() - 1);
                    }
                    card = new GameCard(getContext());
                    // 需要先addView，再设置Piece
                    addView(card, p.getWidth(), p.getHeight());

                    card.setPiece(p, pbm, isAnim);
                    card.setOnClickListener(cardClickHandler);

                    gameCards[i][j] = card;
                } else {
                    gameCards[i][j] = null;
                }
            }
        }
    }

    private final OnClickListener cardClickHandler = new OnClickListener() {
        public void onClick(View v) {
            game.click(((GameCard) v).getPiece());
        }
    };

    /**
     * 根据皮肤加载图片，并加入缓存
     * 
     * @param skinName
     *            皮肤名称
     * @return 图片列表
     */
    private List<Bitmap> getSkinImages(String skinName) {
        int index = 0;
        for (int i = 0; i < ViewSettings.SkinNames.length; i++) {
            if (ViewSettings.SkinNames[i].equalsIgnoreCase(skinName)) {
                index = i;
                break;
            }
        }
        while (BaseActivity.skinImages.get(index) == null) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return BaseActivity.skinImages.get(index);
    }

    /**
     * 根据皮肤加载图片
     */
    private List<Bitmap> loadImages(String skinName) {

        int scaleWidth = game.getPieces()[0][0].getWidth();
        int scaleHeight = game.getPieces()[0][0].getHeight();
        String scaleKey = String.format("%s_%s_%s", skinName, String.valueOf(scaleWidth), String.valueOf(scaleHeight));
        if (!BaseActivity.scaleImages.containsKey(scaleKey)) {
            // 根据皮肤获取图片列表
            List<Bitmap> images = getSkinImages(skinName);

            // 加载到缓存
            List<Bitmap> scaleBms = new ArrayList<Bitmap>();
            for (Bitmap bm : images) {
                scaleBms.add(ImageUtil.scaleBitmap(bm, scaleWidth, scaleHeight));
            }
            BaseActivity.scaleImages.put(scaleKey, scaleBms);
        }
        return BaseActivity.scaleImages.get(scaleKey);

        // Piece[][] pieces = game.getPieces();
        // for (int i = 0; i < pieces.length; i++) {
        // for (int j = 0; j < pieces[i].length; j++) {
        // Piece piece = pieces[i][j];
        // if (piece != null) {
        // // 设置游戏卡片和障碍卡片
        // if (piece.getImageId() == GameSettings.ObstacleCardValue) {
        // Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.obstacle);
        // piece.setImage(ImageUtil.scaleBitmap(bm, piece.getWidth(), piece.getHeight()));
        // } else if (piece.getImageId() != GameSettings.GroundCardValue) {
        // // 根据需要缩放图片
        // piece.setImage(ImageUtil.scaleBitmap(images.get(piece.getImageId() - 1), piece.getWidth(), piece.getHeight()));
        // }
        // }
        // }
        // }
    }

    private Game game;
    private GameCard[][] gameCards = null;
    private Bitmap obstacleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.obstacle);
} public class PathView extends View {

    public PathView(Activity linkup) {
        this((Context) linkup);

        // 根据屏幕分辨率设置path宽度
        Display mDisplay = linkup.getWindowManager().getDefaultDisplay();
        Point size = new Point();
        mDisplay.getSize(size);
        pathWidth = size.x / 60;

        paint.setStrokeWidth(pathWidth);
        PathEffect effect = new DashPathEffect(new float[] { pathWidth, pathWidth }, 0);
        paint.setPathEffect(effect);
    }

    public PathView(Context context) {
        super(context);

        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(pathWidth);
        paint.setColor(getResources().getColor(R.color.path_color));
        PathEffect effect = new DashPathEffect(new float[] { pathWidth, pathWidth }, 0);
        paint.setPathEffect(effect);

        alphaAnim.setDuration(500);
        HideAnimation hideAnim = new HideAnimation(this);
        alphaAnim.setAnimationListener(hideAnim);

        setVisibility(View.GONE);
    }

    /**
     * 显示消除路径
     * 
     * @param pieces
     *            路径卡片集合
     */
    public void showLines(List<Piece> pieces) {
        if (pieces == null || pieces.size() < 2) {
            return;
        }
        points = new ArrayList<Point>();
        for (Piece p : pieces) {
            points.add(p.getCenter());
        }

        setVisibility(View.VISIBLE);
        invalidate();
        startAnimation(alphaAnim);
    }

    /**
     * 绘制路径
     */
    protected void onDraw(Canvas canvas) {
        if (points == null || points.size() < 2) {
            return;
        }

        path.reset();
        Point p = points.get(0);
        path.moveTo(p.x, p.y);
        for (int i = 1; i < points.size(); i++) {
            path.lineTo(points.get(i).x, points.get(i).y);
        }

        canvas.drawPath(path, paint);
        super.onDraw(canvas);
    }

    private List<Point> points = null;
    private final Paint paint = new Paint();
    private final Path path = new Path();
    private int pathWidth = 5;
    private final AlphaAnimation alphaAnim = new AlphaAnimation(1, 0);
} public class FailDialog extends Dialog {

    public FailDialog(final GameActivity linkup) {
        super(linkup, R.style.CustomDialogStyle);
        setContentView(R.layout.fail_dialog);
        setCancelable(false);
        setCanceledOnTouchOutside(false);

        TextView btnCancel = (TextView) findViewById(R.id.fail_button_cancel);
        btnCancel.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                cancel();
                linkup.onBackPressed();
            }

        });

        TextView btnOk = (TextView) findViewById(R.id.fail_button_ok);
        btnOk.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                cancel();
                linkup.start();
            }
        });
    }

    /**
     * 处理返回键
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            TextView btn = (TextView) findViewById(R.id.fail_button_cancel);
            btn.performClick();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 显示游戏失败对话框
     * 
     * @param score
     *            游戏分数
     */
    public void showDialog(int score) {
        TextView tvScore = (TextView) findViewById(R.id.fail_score);
        tvScore.setText(String.valueOf(score) + getContext().getString(R.string.score_unit));
        show();
    }
} public class ResultInfo {
    private String userId = "";
    private int level;
    private int score;
    private int time;
    private int stars;
    private int maxScore;
    private int minTime;
    private boolean isNewRecord;
    private boolean isUpload;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public int getStars() {
        return stars;
    }

    public void setStars(int stars) {
        this.stars = stars;
    }

    public int getMaxScore() {
        return maxScore;
    }

    public void setMaxScore(int maxScore) {
        this.maxScore = maxScore;
    }

    public int getMinTime() {
        return minTime;
    }

    public void setMinTime(int minTime) {
        this.minTime = minTime;
    }

    public boolean isNewRecord() {
        return isNewRecord;
    }

    public void setNewRecord(boolean isNewRecord) {
        this.isNewRecord = isNewRecord;
    }

    public boolean isUpload() {
        return isUpload;
    }

    public void setUpload(boolean isUpload) {
        this.isUpload = isUpload;
    }
} public class SuccessDialog extends Dialog implements IUpload {

    private GameActivity linkup = null;
    private ResultInfo resultInfo = null;
    private LevelTop levelTop = null;
    private ShareUtil shareHelper = null;

    public SuccessDialog(final GameActivity linkup) {
        super(linkup, R.style.CustomDialogStyle);
        this.linkup = linkup;
        setContentView(R.layout.success_dialog);
        setCancelable(false);
        setCanceledOnTouchOutside(false);

        shareHelper = new ShareUtil(getContext());

        TextView btnCancel = (TextView) findViewById(R.id.success_button_cancel);
        btnCancel.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.onBackPressed();
            }

        });

        TextView btnAgain = (TextView) findViewById(R.id.btnAgain);
        btnAgain.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.start();
            }
        });

        TextView btnShare = (TextView) findViewById(R.id.btnshare);
        btnShare.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String msg = String.format(getContext().getString(R.string.share_score), linkup.getLevelCfg().getLevelName(),
                        String.valueOf(resultInfo.getScore()));

                // 分享
                if (levelTop.getTopStatus() == LevelTopStatus.TopInfo) {
                    // 带截图分享
                    shareHelper.shareMsgView(msg, levelTop);
                } else {
                    shareHelper.shareMessage(msg);
                }
            }
        });

        TextView btnOk = (TextView) findViewById(R.id.success_button_ok);
        btnOk.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.next();
            }
        });

        levelTop = (LevelTop) findViewById(R.id.level_top);
        levelTop.setUploadListener(this);
    }

    /**
     * 处理返回键
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            TextView btn = (TextView) findViewById(R.id.success_button_cancel);
            btn.performClick();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 显示游戏胜利对话框
     * 
     * @param ResultInfo
     *            游戏结果
     */
    public void showDialog(ResultInfo resultInfo) {
        this.resultInfo = resultInfo;
        setGameScore(resultInfo.getScore());
        setGameStar(resultInfo.getStars());
        isNewRecord(resultInfo.isNewRecord());
        if (levelTop != null) {
            levelTop.reset();
        }
        uploadScore();
        show();
    }

    /**
     * 设置游戏总得分
     * 
     * @param score
     *            游戏得分
     */
    private void setGameScore(int score) {
        TextView tvScore = (TextView) findViewById(R.id.success_score);
        tvScore.setText(String.valueOf(score) + getContext().getString(R.string.score_unit));

        TextView tvCoin = (TextView) findViewById(R.id.level_coin_reward);
        tvCoin.setText("+" + String.valueOf(score / 10));
    }

    /**
     * 设置是否是新的记录
     * 
     * @param isNewRecord
     *            是否为新记录
     */
    private void isNewRecord(boolean isNewRecord) {
        ImageView ivRecord = (ImageView) findViewById(R.id.level_champion);
        ivRecord.setVisibility(isNewRecord ? View.VISIBLE : View.INVISIBLE);
    }

    /**
     * 设置游戏星级
     * 
     * @param star
     *            星级数
     */
    private void setGameStar(int star) {
        ImageView level_star = (ImageView) findViewById(R.id.level_star);
        ImageView star1Reward = (ImageView) findViewById(R.id.level_star1_reward);
        star1Reward.setVisibility(View.GONE);
        ImageView star2Reward = (ImageView) findViewById(R.id.level_star2_reward);
        star2Reward.setVisibility(View.GONE);
        ImageView star3Reward = (ImageView) findViewById(R.id.level_star3_reward);
        star3Reward.setVisibility(View.GONE);
        TextView tvDiamond = (TextView) findViewById(R.id.level_diamond_reward);

        if (star <= 0 || star > 3) {
            return;
        }
        level_star.setImageResource(ViewSettings.StarImages[star - 1]);
        tvDiamond.setText("+" + String.valueOf(star));
        if (star > 0) {
            if (LevelCfg.globalCfg.getPromptNum() < ViewSettings.PromptMaxNum) {
                // promt 增加一次
                LevelCfg.globalCfg.setPromptNum(LevelCfg.globalCfg.getPromptNum() + 1);
            }
            star1Reward.setVisibility(View.VISIBLE);
        }
        if (star > 1) {
            if (LevelCfg.globalCfg.getAddTimeNum() < ViewSettings.AddTimeMaxNum) {
                // AddTime 增加一次
                LevelCfg.globalCfg.setAddTimeNum(LevelCfg.globalCfg.getAddTimeNum() + 1);
            }
            star2Reward.setVisibility(View.VISIBLE);
        }
        if (star > 2) {
            if (LevelCfg.globalCfg.getRefreshNum() < ViewSettings.RefreshMaxNum) {
                // refresh 增加一次
                LevelCfg.globalCfg.setRefreshNum(LevelCfg.globalCfg.getRefreshNum() + 1);
            }
            star3Reward.setVisibility(View.VISIBLE);
        }
        linkup.setGlobalCfg();
    }

    /**
     * 上传分数
     */
    private void uploadScore() {
        // 判断是否已登录
        if (!resultInfo.getUserId().equals("")) {
            LevelInfo scoreInfo = new LevelInfo();
            scoreInfo.setUserId(resultInfo.getUserId());
            scoreInfo.setLevel(resultInfo.getLevel());
            scoreInfo.setDiamond(resultInfo.getStars());
            scoreInfo.setGold(resultInfo.getScore() / 10);

            // 增加奖励的钻石和金币
            WelcomeActivity.userInfo.addDiamond(getContext(), scoreInfo.getDiamond());

            if (resultInfo.isNewRecord()) {
                scoreInfo.setScore(resultInfo.getScore());
                scoreInfo.setTime(resultInfo.getTime());
                WelcomeActivity.userInfo.addGold(getContext(), scoreInfo.getGold());
                UserScore.addGetResult(scoreInfo, levelTop.netMsgHandler);
            } else {
                if (!resultInfo.isUpload()) {
                    scoreInfo.setScore(resultInfo.getMaxScore());
                    scoreInfo.setTime(resultInfo.getMinTime());
                    WelcomeActivity.userInfo.addGold(getContext(), scoreInfo.getGold());
                    UserScore.addGetResult(scoreInfo, levelTop.netMsgHandler);
                } else {
                    // 获取排行榜
                    UserScore.getLevelTops(resultInfo.getLevel(), levelTop.netMsgHandler);
                }
            }
        } else {
            // 没有登录则提示登录
        }
    }

    @Override
    public void onLoginSuccess(Message msg) {
        UserInfo userInfo = WelcomeActivity.userInfo;
        if (userInfo != null) {
            resultInfo.setUserId(userInfo.getUserId());
            uploadScore();
        }
    }

    @Override
    public void onLevelResultAdd(Message msg) {
        // 更新是否已上传
        linkup.getLevelCfg().setUpload(true);
        LevelScore ls = new LevelScore(resultInfo.getLevel());
        ls.setIsUpload(1);
        DbScore.updateUpload(ls);
    }
} public class TaskDialog extends Dialog implements IUpload {

    private GameActivity linkup = null;
    private ResultInfo resultInfo = null;
    private LevelTop levelTop = null;
    private ShareUtil shareHelper = null;

    public TaskDialog(final GameActivity linkup) {
        super(linkup, R.style.CustomDialogStyle);
        this.linkup = linkup;
        setContentView(R.layout.task_dialog);
        setCancelable(false);
        setCanceledOnTouchOutside(false);

        shareHelper = new ShareUtil(getContext());

        TextView btnBack = (TextView) findViewById(R.id.btnBack);
        btnBack.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.onBackPressed();
            }

        });

        TextView btnShare = (TextView) findViewById(R.id.btnshare);
        btnShare.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String msg = String.format(getContext().getString(R.string.share_task), linkup.getLevelCfg().getLevelName(),
                        String.valueOf(resultInfo.getScore()));

                if (linkup.getLevelCfg().getLevelMode() == GameMode.TimeTask) {
                    msg = String.format(getContext().getString(R.string.share_time), linkup.getLevelCfg().getLevelName(),
                            StringUtil.secondToString(resultInfo.getTime()));
                }
                // 分享
                if (levelTop.getTopStatus() == LevelTopStatus.TopInfo) {
                    // 带截图分享
                    shareHelper.shareMsgView(msg, levelTop);
                } else {

                    shareHelper.shareMessage(msg);
                }
            }
        });

        levelTop = (LevelTop) findViewById(R.id.task_top);
        levelTop.setUploadListener(this);
    }

    /**
     * 处理返回键
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            TextView btn = (TextView) findViewById(R.id.btnBack);
            btn.performClick();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 显示游戏胜利对话框
     * 
     * @param resultInfo
     *            游戏结果
     */
    public void showDialog(ResultInfo resultInfo) {
        this.resultInfo = resultInfo;
        TextView tvScoreLabel = (TextView) findViewById(R.id.lb_score);
        TextView tvScore = (TextView) findViewById(R.id.success_score);
        TextView tvTask = (TextView) findViewById(R.id.task_score);
        if (linkup.getLevelCfg().getLevelMode() == GameMode.ScoreTask) {
            tvScoreLabel.setText(R.string.game_score);
            tvScore.setText(String.valueOf(resultInfo.getScore()) + getContext().getString(R.string.score_unit));
            tvTask.setText(String.valueOf(linkup.getLevelCfg().getScoreTask()) + getContext().getString(R.string.score_unit));
        } else if (linkup.getLevelCfg().getLevelMode() == GameMode.TimeTask) {
            tvScoreLabel.setText(R.string.game_time);
            tvScore.setText(StringUtil.secondToString(resultInfo.getTime()) + getContext().getString(R.string.time_unit));
            tvTask.setText(StringUtil.secondToString(linkup.getLevelCfg().getTimeTask()) + getContext().getString(R.string.time_unit));
        }

        TextView tvDiamond = (TextView) findViewById(R.id.level_diamond_reward);
        tvDiamond.setText("+" + String.valueOf(resultInfo.getStars()));
        TextView tvCoin = (TextView) findViewById(R.id.level_coin_reward);
        tvCoin.setText("+" + String.valueOf(resultInfo.getScore() / 10));

        TextView tvTaskTitle = (TextView) findViewById(R.id.dialog_title);
        tvTaskTitle.setText(R.string.game_task_fail);
        ImageView ivRecord = (ImageView) findViewById(R.id.task_pass);
        ivRecord.setVisibility(View.INVISIBLE);
        TextView btnAgainOrNext = (TextView) findViewById(R.id.btnAgainOrNext);
        Drawable drawableAgain = getContext().getResources().getDrawable(R.drawable.again);
        drawableAgain.setBounds(0, 0, drawableAgain.getMinimumWidth(), drawableAgain.getMinimumHeight());
        btnAgainOrNext.setCompoundDrawables(null, drawableAgain, null, null);
        btnAgainOrNext.setText(R.string.again);
        btnAgainOrNext.setOnClickListener(againHandler);
        if (resultInfo.isNewRecord()) {
            tvTaskTitle.setText(R.string.game_task_success);
            ivRecord.setVisibility(View.VISIBLE);
            Drawable drawableNext = getContext().getResources().getDrawable(R.drawable.next);
            drawableNext.setBounds(0, 0, drawableNext.getMinimumWidth(), drawableNext.getMinimumHeight());
            btnAgainOrNext.setCompoundDrawables(null, drawableNext, null, null);
            btnAgainOrNext.setText(R.string.next);
            btnAgainOrNext.setOnClickListener(nextHandler);
        }

        if (levelTop != null) {
            levelTop.reset();
        }
        uploadScore();
        show();
    }

    private View.OnClickListener againHandler = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            levelTop.cancelUrlImages();
            cancel();
            linkup.start();
        }
    };

    private View.OnClickListener nextHandler = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            levelTop.cancelUrlImages();
            cancel();
            linkup.next();
        }
    };

    /**
     * 上传分数
     */
    private void uploadScore() {
        // 判断是否已登录
        if (!resultInfo.getUserId().equals("")) {
            LevelInfo scoreInfo = new LevelInfo();
            scoreInfo.setUserId(resultInfo.getUserId());
            scoreInfo.setLevel(resultInfo.getLevel());
            scoreInfo.setDiamond(resultInfo.getStars());
            scoreInfo.setGold(resultInfo.getScore() / 10);

            // 增加奖励的钻石和金币
            WelcomeActivity.userInfo.addDiamond(getContext(), scoreInfo.getDiamond());
            if (resultInfo.isNewRecord()) {
                scoreInfo.setScore(resultInfo.getScore());
                scoreInfo.setTime(resultInfo.getTime());
                WelcomeActivity.userInfo.addGold(getContext(), scoreInfo.getGold());
                UserScore.addGetResult(scoreInfo, levelTop.netMsgHandler);
            } else {
                if (!resultInfo.isUpload()) {
                    // 上传之前玩过还没上传的最高分
                    if ((linkup.getLevelCfg().getLevelMode() == GameMode.ScoreTask && resultInfo.getMaxScore() != 0)
                            || (linkup.getLevelCfg().getLevelMode() == GameMode.TimeTask && resultInfo.getMinTime() != 0)) {
                        scoreInfo.setScore(resultInfo.getMaxScore());
                        scoreInfo.setTime(resultInfo.getMinTime());
                        WelcomeActivity.userInfo.addGold(getContext(), scoreInfo.getGold());
                        UserScore.addGetResult(scoreInfo, levelTop.netMsgHandler);
                    }
                } else {
                    // 获取排行榜
                    UserScore.getLevelTops(resultInfo.getLevel(), levelTop.netMsgHandler);
                }
            }

        } else {
            // 没有登录则提示登录
        }
    }

    @Override
    public void onLoginSuccess(Message msg) {
        UserInfo userInfo = WelcomeActivity.userInfo;
        if (userInfo != null) {
            resultInfo.setUserId(userInfo.getUserId());
            uploadScore();
        }
    }

    @Override
    public void onLevelResultAdd(Message msg) {
        // 更新是否已上传
        linkup.getLevelCfg().setUpload(true);
        LevelScore ls = new LevelScore(resultInfo.getLevel());
        ls.setIsUpload(1);
        DbScore.updateUpload(ls);

        // 获取排行榜
        // UserScore.getLevelTops(resultInfo.getLevel(), levelTop.netMsgHandler);
    }
} public class TimeDialog extends Dialog implements IUpload {

    private GameActivity linkup = null;
    private ResultInfo resultInfo = null;
    private LevelTop levelTop = null;
    private ShareUtil shareHelper = null;

    public TimeDialog(final GameActivity linkup) {
        super(linkup, R.style.CustomDialogStyle);
        this.linkup = linkup;
        setContentView(R.layout.time_dialog);
        setCancelable(false);
        setCanceledOnTouchOutside(false);

        shareHelper = new ShareUtil(getContext());

        TextView btnBack = (TextView) findViewById(R.id.btnBack);
        btnBack.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.onBackPressed();
            }

        });

        TextView btnShare = (TextView) findViewById(R.id.btnshare);
        btnShare.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String msg = String.format(getContext().getString(R.string.share_time), linkup.getLevelCfg().getLevelName(),
                        StringUtil.secondToString(resultInfo.getTime()));
                // 分享
                if (levelTop.getTopStatus() == LevelTopStatus.TopInfo) {
                    // 带截图分享
                    shareHelper.shareMsgView(msg, levelTop);
                } else {

                    shareHelper.shareMessage(msg);
                }
            }
        });

        TextView btnAgain = (TextView) findViewById(R.id.btnAgain);
        btnAgain.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.start();
            }
        });

        TextView btnNext = (TextView) findViewById(R.id.btnNext);
        btnNext.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                levelTop.cancelUrlImages();
                cancel();
                linkup.next();
            }
        });

        levelTop = (LevelTop) findViewById(R.id.time_top);
        levelTop.setUploadListener(this);
    }

    /**
     * 处理返回键
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            TextView btn = (TextView) findViewById(R.id.btnBack);
            btn.performClick();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 显示游戏胜利对话框
     * 
     * @param resultInfo
     *            游戏结果
     */
    public void showDialog(ResultInfo resultInfo) {
        this.resultInfo = resultInfo;
        TextView tvTime = (TextView) findViewById(R.id.success_time);
        tvTime.setText(StringUtil.secondToString(resultInfo.getTime()) + getContext().getString(R.string.time_unit));
        TextView tvRecord = (TextView) findViewById(R.id.time_record);
        tvRecord.setText(StringUtil.secondToString(linkup.getLevelCfg().getMinTime()) + getContext().getString(R.string.time_unit));
        ImageView ivRecord = (ImageView) findViewById(R.id.level_champion);
        TextView tvDiamond = (TextView) findViewById(R.id.level_diamond_reward);
        tvDiamond.setText("+" + String.valueOf(resultInfo.getStars()));
        TextView tvCoin = (TextView) findViewById(R.id.level_coin_reward);
        tvCoin.setText("+" + String.valueOf(resultInfo.getScore() / 10));
        ivRecord.setVisibility(View.INVISIBLE);
        if (resultInfo.isNewRecord()) {
            ivRecord.setVisibility(View.VISIBLE);
        }

        if (levelTop != null) {
            levelTop.reset();
        }
        uploadTime();

        show();
    }

    /**
     * 上传时间
     */
    private void uploadTime() {
        // 判断是否已登录
        if (!resultInfo.getUserId().equals("")) {
            LevelInfo timeInfo = new LevelInfo();
            timeInfo.setUserId(resultInfo.getUserId());
            timeInfo.setLevel(resultInfo.getLevel());
            timeInfo.setDiamond(resultInfo.getStars());
            timeInfo.setGold(resultInfo.getScore() / 10);

            // 增加奖励的钻石和金币
            WelcomeActivity.userInfo.addDiamond(getContext(), timeInfo.getDiamond());
            if (resultInfo.isNewRecord()) {
                timeInfo.setScore(resultInfo.getScore());
                timeInfo.setTime(resultInfo.getTime());
                WelcomeActivity.userInfo.addGold(getContext(), timeInfo.getGold());
                UserScore.addGetResult(timeInfo, levelTop.netMsgHandler);
            } else {
                if (!resultInfo.isUpload()) {
                    timeInfo.setScore(resultInfo.getMaxScore());
                    timeInfo.setTime(resultInfo.getMinTime());
                    WelcomeActivity.userInfo.addGold(getContext(), timeInfo.getGold());
                    UserScore.addGetResult(timeInfo, levelTop.netMsgHandler);
                } else {
                    // 获取排行榜
                    UserScore.getLevelTops(resultInfo.getLevel(), levelTop.netMsgHandler);
                }
            }
        } else {
            // 没有登录则提示登录
        }
    }

    @Override
    public void onLoginSuccess(Message msg) {
        UserInfo userInfo = WelcomeActivity.userInfo;
        if (userInfo != null) {
            resultInfo.setUserId(userInfo.getUserId());
            uploadTime();
        }
    }

    @Override
    public void onLevelResultAdd(Message msg) {
        // 更新是否已上传
        linkup.getLevelCfg().setUpload(true);
        LevelScore ls = new LevelScore(resultInfo.getLevel());
        ls.setIsUpload(1);
        DbScore.updateUpload(ls);

        // 获取排行榜
        // UserScore.getLevelTops(resultInfo.getLevel(), levelTop.netMsgHandler);
    }
} public class GameMsgHandler extends Handler {

    private WeakReference<GameActivity> gameActs;

    public GameMsgHandler(GameActivity act) {
        gameActs = new WeakReference<GameActivity>(act);
    }

    @Override
    public void handleMessage(Message msg) {
        GameActivity gameAct = gameActs.get();
        switch (msg.what) {
        case ViewSettings.TimeMessage:
            gameAct.showTime(msg.arg1);
            break;
        case ViewSettings.ScoreMessage:
            gameAct.showScore(msg.arg1);
            break;
        case ViewSettings.FailMessage:
            gameAct.showFail();
            break;
        case ViewSettings.WinMessage:
            gameAct.showSuccess(msg.arg1, msg.arg2);
            break;
        case ViewSettings.PromptMessage:
            gameAct.showPrompt();
            break;
        case ViewSettings.RefreshMessage:
            gameAct.showRefresh();
            break;
        }
    }

}
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;
import com.znv.linkup.core.Game;
import com.znv.linkup.core.GameSettings;
import com.znv.linkup.core.IGameAction;
import com.znv.linkup.core.card.Piece;
import com.znv.linkup.core.card.PiecePair;
import com.znv.linkup.core.card.path.LinkInfo;
import com.znv.linkup.core.config.GameAlign;
import com.znv.linkup.core.config.GameMode;
import com.znv.linkup.core.config.LevelCfg;
import com.znv.linkup.db.DbScore;
import com.znv.linkup.db.LevelScore;
import com.znv.linkup.util.AnimatorUtil;
import com.znv.linkup.util.Stopwatch;
import com.znv.linkup.util.StringUtil;
import com.znv.linkup.util.ToastUtil;
import com.znv.linkup.view.CardsView;
import com.znv.linkup.view.PathView;
import com.znv.linkup.view.dialog.FailDialog;
import com.znv.linkup.view.dialog.ResultInfo;
import com.znv.linkup.view.dialog.SuccessDialog;
import com.znv.linkup.view.dialog.TaskDialog;
import com.znv.linkup.view.dialog.TimeDialog;
import com.znv.linkup.view.handler.GameMsgHandler;
    }

    /**
     * 取消游戏提示
     */
    public void onUnPrompt(PiecePair pair) {
        if (pair != null) {
            cardsView.unPrompt(pair);
        }
    }

    /**
     * 连击时的处理
     */
    @Override
    public void onCombo(int combo) {
        if (combo % GameSettings.ComboMod == 0) {
            String msg = String.valueOf(combo);
            holder.tvCombo.setText(msg);
            int msgWidth = msg.length() * holder.screenWidth / 50 + getResources().getDrawable(R.drawable.combo).getMinimumWidth() / 2;
            Point startPoint = new Point(holder.screenCenter.x - msgWidth, (int) holder.tsScore.getY() + 100);
            Point endPoint = new Point(startPoint.x, startPoint.y - 50);
            animTranslate(holder.tvCombo, startPoint, endPoint, 1500, 0);

            soundMgr.combo();
        }
    }

    /**
     * 屏幕中心显示文字动画
     * 
     * @param msg
     *            文字信息
     * @param textSize
     *            字体大小
     */
    private void showAnimMsg(String msg, int textSize, int delay) {
        setAnimMsgStyle(msg, textSize);
        int msgWidth = msg.length() * holder.screenWidth / 50;
        Point startPoint = new Point(holder.screenCenter.x - msgWidth, holder.screenCenter.y);
        Point endPoint = new Point(startPoint.x, startPoint.y - 50);
        animTranslate(holder.tvAnimMsg, startPoint, endPoint, 1500, delay);
    }

    /**
     * 显示增加分数动画
     * 
     * @param msg
     *            文字信息
     * @param textSize
     *            字体大小
     */
    private void showAddScore(String msg, int textSize) {
        setAnimMsgStyle(msg, textSize);
        int msgWidth = msg.length() * holder.screenWidth / 60;
        Point startPoint = new Point(holder.screenCenter.x - msgWidth, (int) holder.tsScore.getY() + 100);
        Point endPoint = new Point(startPoint.x, startPoint.y - 40);
        animTranslate(holder.tvAnimMsg, startPoint, endPoint, 500, 0);
    }

    /**
     * 设置动画文字的样式
     * 
     * @param msg
     *            文字信息
     * @param textSize
     *            字体大小
     */
    private void setAnimMsgStyle(String msg, int textSize) {
        holder.tvAnimMsg.setText(msg);
        holder.tvAnimMsg.setTextSize(textSize);
    }

    /**
     * 重排时的处理
     */
    @Override
    public void onRefresh() {
        cardsView.createCards(false);

        soundMgr.refresh();
        // 减少重排一次
        LevelCfg.globalCfg.setRefreshNum(LevelCfg.globalCfg.getRefreshNum() - 1);
        setGlobalCfg();
        handler.sendEmptyMessage(ViewSettings.RefreshMessage);
    }

    /**
     * 选中时的处理
     */
    public void onCheck(Piece piece) {
        if (piece != null) {
            cardsView.check(piece);
            soundMgr.select();
        }
    }

    /**
     * 取消选中时的处理
     */
    public void onUnCheck(Piece piece) {
        if (piece != null) {
            cardsView.unCheck(piece);
        }
    }

    /**
     * 变换时的处理
     */
    @Override
    public void onTranslate() {
        if (curLevelCfg.getLevelAlign() != GameAlign.AlignNone) {
            cardsView.createCards(false);
        }
    }

    /**
     * 处理游戏消除路径
     */
    @Override
    public void onLinkPath(LinkInfo linkInfo) {