栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

连连看:深度优先搜索实现生成与校验

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

连连看:深度优先搜索实现生成与校验

连连看:深度优先搜索实现生成与校验
  • 一种校验连连看的算法,使用深度优先算法
      • entity:btn
      • 校验接口
      • 生成接口
      • 接口实现类
      • 生成实现(完全随机,且未校验棋盘是否可以完成)
      • 生成实现2

一种校验连连看的算法,使用深度优先算法 entity:btn
public class btn {
//    x,y坐标
    public int x;
    public int y;
//    value判断两个btn是否相等
    public int value;
//    是否已经消去
    public boolean exist;

    public btn(int x, int y, int value, boolean exist) {
        this.x = x;
        this.y = y;
        this.value = value;
        this.exist = exist;
    }

    public btn() {
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public boolean isExist() {
        return exist;
    }

    public void setExist(boolean exist) {
        this.exist = exist;
    }

    @Override
    public String toString() {
        return "btn{" +
                "x=" + x +
                ", y=" + y +
                ", value=" + value +
                ", exist=" + exist +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        btn btn = (btn) o;

        if (x != btn.x) return false;
        if (y != btn.y) return false;
        if (value != btn.value) return false;
        return exist == btn.exist;
    }
}

校验接口
public interface CheckForAll {

    
    public Boolean Check(btn[][] btns,btn b1, btn b2);

    
    public Boolean isClear(btn[][] btns);

    
    public Boolean CheckAll(btn[][] btns);
}
生成接口
public interface NewGame {
//    生成一个值为0~4,0~4,顺序随机的数组
    public int[][] NewGame();
}
接口实现类
public class CheckForAllImpl implements CheckForAll {

    
    @Override
    public Boolean Check(btn[][] btns, @NonNull btn b1, @NonNull btn b2) {
        boolean flag = false;
//        判断是否为同一按钮
        if (!b1.equals(b2)){
//            判断是否值相同
            if (b1.getValue() == b2.getValue()) {
//                判断是否已经消去
                if (b1.isExist() && b2.isExist()){
//                    判断是否能连通
                    if(isLink(btns,b1,b2)){
                        flag = true;
                    }
                }
            }
        }
        return flag;
    }

    //    bi = btns.length,bj = btns[0].length
    private static int bi,bj;
    //    标志位,false为未遍历过此格子
    private static boolean[][] flags = new boolean[bi][bj];

    
    @NonNull
    private Boolean isLink(btn[][] btns, btn b1, btn b2) {
//        获取长宽
        bi = btns.length;
        bj = btns[0].length;
        flags = new boolean[bi][bj];
//        若b1,b2均(处于边缘或与边缘相通)
        if (is_Edge(btns,b1) && is_Edge(btns,b2)){
            return true;
        }
//        b1,b2至少有一个不处于边缘或与边缘相通,判断两按钮在不穿过边缘的情况下能否连通
        else {
            return is_Connect(btns, b1, b2);
        }
    }

    @NonNull
    private Boolean is_Edge(@NonNull btn[][] btns, @NonNull btn b) {
//        重置标志位
        for (int i = 0; i < bi; i++) {
            for (int j = 0; j < bj; j++) {
                flags[i][j] = false;
            }
        }
        return isEdge(btns, b);
    }

    
    @NonNull
    private Boolean isEdge(@NonNull btn[][] btns, @NonNull btn b) {
//        若为边缘
        if (b.getX() == 0 || b.getX() == bi - 1 || b.getY() == 0 || b.getY() == bj - 1){
            return true;
        }else {
            int x = b.getX();
            int y = b.getY();
            btn b1 = btns[x-1][y];
            btn b2 = btns[x][y+1];
            btn b3 = btns[x+1][y];
            btn b4 = btns[x][y-1];
//            若不在边缘,不断迭代判断其周围已经消去的button,不再迭代已经迭代过的格子
            if (!flags[x-1][y] && !b1.isExist()){
                flags[x-1][y] = true;
                if (isEdge(btns,b1))
                    return true;
            }
            if (!flags[x][y+1] && !b2.isExist()){
                flags[x][y+1] = true;
                if (isEdge(btns,b2))
                    return true;
            }
            if (!flags[x+1][y] && !b3.isExist()){
                flags[x+1][y] = true;
                if (isEdge(btns,b3))
                    return true;
            }
            if (!flags[x][y-1] && !b4.isExist()){
                flags[x][y-1] = true;
                return isEdge(btns, b4);
            }
        }
        return false;
    }

    @NonNull
    private Boolean is_Connect(@NonNull btn[][] btns, @NonNull btn b1, @NonNull btn b2){
//        重置标志位
        for (int i = 0; i < bi; i++) {
            for (int j = 0; j < bj; j++) {
                flags[i][j] = false;
            }
        }
        return isConnect(btns, b1, b2);
    }

    
    @NonNull
    private Boolean isConnect(@NonNull btn[][] btns, @NonNull btn b1, @NonNull btn b2) {
        int x = b1.getX();
        int y = b1.getY();
//        不断迭代判断其周围已经消去的button的四周有无b2
        if (x != 0){
            btn bt1 = btns[x-1][y];
            if (!flags[x-1][y]){
                flags[x-1][y] = true;
//                若此格未消去
                if (bt1.isExist()){
                    if (bt1.equals(b2)){
                        return true;
                    }
                }else {
                    if (isConnect(btns,bt1,b2)){
                        return true;
                    }
                }
            }
        }
        if (y != bj - 1){
            btn bt2 = btns[x][y+1];
            if (!flags[x][y+1]){
                flags[x][y+1] = true;
                if (bt2.isExist()){
                    if (bt2.equals(b2)){
                        return true;
                    }
                }else {
                    if (isConnect(btns,bt2,b2)){
                        return true;
                    }
                }
            }
        }
        if (x != bi - 1){
            btn bt3 = btns[x+1][y];
            if (!flags[x+1][y]){
                flags[x+1][y] = true;
                if (bt3.isExist()){
                    if (bt3.equals(b2)){
                        return true;
                    }
                }else {
                    if (isConnect(btns,bt3,b2)){
                        return true;
                    }
                }
            }
        }
        if (y != 0){
            btn bt4 = btns[x][y-1];
            if (!flags[x][y-1]){
                flags[x][y-1] = true;
                if (bt4.isExist()){
                    if (bt4.equals(b2)){
                        return true;
                    }
                }else {
                    if (isConnect(btns,bt4,b2)){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    
    @NonNull
    private Boolean isFullLink(@NonNull btn[][] btns, @NonNull btn b1) {
        int x1 = b1.getX();
        int y1 = b1.getY();
//            若被完全包围
        return btns[x1 - 1][y1].isExist() && btns[x1][y1 - 1].isExist()
                && btns[x1 + 1][y1].isExist() && btns[x1][y1 + 1].isExist();
    }

    
    @NonNull
    private Boolean isSide(@NonNull btn[][] btns, @NonNull btn b1, @NonNull btn b2) {
        int x1 = b1.getX();
        int y1 = b1.getY();
        return b2.equals(btns[x1 - 1][y1]) || b2.equals(btns[x1][y1 + 1])
                || b2.equals(btns[x1 + 1][y1]) || b2.equals(btns[x1][y1 - 1]);
    }

    
    @Override
    public Boolean isClear(@NonNull btn[][] btns) {
        for (cn.ljh.link.entity.btn[] btn : btns) {
            for (cn.ljh.link.entity.btn value : btn) {
                if (value.isExist()) {
                    return false;
                }
            }
        }
        return true;
    }

    
    @Override
    public Boolean CheckAll(@NonNull btn[][] _btns) {
        btn[][] btns = _btns.clone();
//        标志位,false为value未遍历过此格子
        boolean[][] flag = new boolean[btns.length][btns[0].length];
        for (cn.ljh.link.entity.btn[] btn : btns) {
            for (cn.ljh.link.entity.btn value : btn) {
                flag[value.getX()][value.getY()] = true;
                for (cn.ljh.link.entity.btn[] item : btns) {
                    for (cn.ljh.link.entity.btn element : item) {
                        if (!flag[element.getX()][element.getY()]) {
                            if (Check(btns, value, element)) {
                                btns[value.getX()][value.getY()].setExist(false);
                                btns[element.getX()][element.getY()].setExist(false);
                                if (isClear(btns)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return isClear(btns);
    }
}
生成实现(完全随机,且未校验棋盘是否可以完成)
public class NewGameImpl implements NewGame {

    
    @Override
    public int[][] NewGame() {
        int[][] game =new int[4][4];
//        初始化数组
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 4; j++) {
                game[i][j] = 4 * i + j;
            }
        }
        for (int i = 2; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                game[i][j] = 4 * (i - 2) + j;
            }
        }
//        打乱数组
        SecureRandom random = new SecureRandom();
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                int m = random.nextInt(4);
                int n = random.nextInt(4);
                int M = random.nextInt(4);
                int N = random.nextInt(4);
                int temp = game[m][n];
                game[m][n] = game[M][N];
                game[M][N] = temp;
            }
        }
        return game;
    }
}
生成实现2
public class NewGame2Impl implements NewGame2 {

    
    @Override
    public int[][] NewGame2(int i, int j) {

        CheckForAll check = new CheckForAllImpl();

//        棋盘,下标为坐标
        btn[][] chess = new btn[i][j];
//        棋盘每个格子的value,下标为坐标
        int[][] game = new int[i][j];
//        Mark[a][b][c][d] = false:(a,b)(c,d)两格子无法置为value相同
        boolean[][][][] Mark = new boolean[i][j][i][j];
//        存放空格子的坐标
//        2 = (0,2);9 = (3,1)
        List chessList = new ArrayList<>();
//        可以取到的value
        List ValueList = new ArrayList<>();

        for (int a = 0; a < i; a++) {
            for (int b = 0; b < j; b++) {
//                起始格子value置为-1,即为空格子
                game[a][b] = -1;
//                初始化坐标与value
                chess[a][b] = new btn(a, b, -1, false);
            }
        }

//        初始化chessList:0,1,2,...,i * j -1
        for (int k = 0; k < i * j; k++) {
            chessList.add(k);
        }

//        初始化Mark
        for (int k = 0; k < i; k++) {
            for (int l = 0; l < j; l++) {
                for (int m = 0; m < i; m++) {
                    for (int n = 0; n < j; n++) {
                        Mark[k][l][m][n] = true;
                    }
                }
            }
        }

//        初始化value列表:0,0,1,1,2,2,...,n,n
        for (int a = 0; a < (i * j) / 2; a++) {
            for (int k = 0; k < 2; k++) {
                ValueList.add(a);
            }
        }

//        循环加入符合要求的两格
        while (true) {
//        随机找两个空格子,存放其坐标,并从chessList中移除
            int[] canBt = new int[2];
            int[] x = new int[2];
            int[] y = new int[2];
            SecureRandom random = new SecureRandom();
            canBt[0] = chessList.remove(random.nextInt(chessList.size()));
//            若两坐标是同一个或已被标记为value不可相同则重新寻找第二个
            int flag;
            do {
                flag = random.nextInt(chessList.size());
                canBt[1] = chessList.get(flag);
                for (int k = 0; k < 2; k++) {
                    x[k] = canBt[k] / j;
                    y[k] = canBt[k] - j * x[k];
                }
            } while (canBt[1] == canBt[0] || !Mark[x[0]][y[0]][x[1]][y[1]]);
//            取到合适的格子坐标则从chessList中移去
            chessList.remove(flag);
//            实例化两个格子
            btn[] btnTemp = new btn[2];
//            移除可用value中的前两个并赋给btnTemp
            for (int k = 0; k < 2; k++) {
                btnTemp[k] = new btn(x[k], y[k], ValueList.remove(k), true);
            }


//            若仍有空格子则验证新加入的两格
            if (!chessList.isEmpty()) {
//                通过则加入chess,再继续随机两个格子
                if (check.Check(chess, btnTemp[0], btnTemp[1])) {
                    for (int k = 0; k < 2; k++) {
                        chess[x[k]][y[k]] = new btn(x[k], y[k], btnTemp[k].getValue(), true);
                    }
                }
//                若不通过,则回退一步,并做标记,再重新随机两个格子
                else {
                    Mark[x[0]][y[0]][x[1]][y[1]] = false;
                    for (int k = 0; k < 2; k++) {
                        ValueList.add(k, btnTemp[k].getValue());
                        chessList.add(canBt[k]);
                    }
                }
            }
//            若已无空格子,则验证整体,通过则break
            else {
                for (int k = 0; k < 2; k++) {
                    chess[x[k]][y[k]] = new btn(x[k], y[k], btnTemp[k].getValue(), true);
                }
                if (check.CheckAll(chess)) {
                    break;
                }
//                若验证失败,回退到最初
                else {
                    for (int a = 0; a < i; a++) {
                        for (int b = 0; b < j; b++) {
                            game[a][b] = -1;
                            chess[a][b] = new btn(a, b, -1, false);
                        }
                    }
                    for (int k = 0; k < i * j; k++) {
                        chessList.add(k);
                    }
                    for (int k = 0; k < i; k++) {
                        for (int l = 0; l < j; l++) {
                            for (int m = 0; m < i; m++) {
                                for (int n = 0; n < j; n++) {
                                    Mark[k][l][m][n] = true;
                                }
                            }
                        }
                    }
                    for (int a = 0; a < (i * j) / 2; a++) {
                        for (int k = 0; k < 2; k++) {
                            ValueList.add(a);
                        }
                    }
                }
            }
        }

//        返回棋盘的value分布
        for (int k = 0; k < i; k++) {
            for (int l = 0; l < j; l++) {
                game[k][l] = chess[k][l].getValue();
            }
        }
        return game;
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/937027.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号