PuyoPuyo DFS算法练习

PuyoPuyo DFS算法练习

题目和解析有空再整理。

package puyopuyo;

/**
 * @Author jinjun99
 * @Date Created in 2021/11/21 11:18
 * @Description
 * @Since version-1.0
 */
public class Block {

    /**
     * 状态
     */
    int event = 0;
    /**
     * 方向
     */
    int dir = 0;

    /**
     * 列号
     */
    int col = 0;
    /**
     * 颜色
     */
    int[] val;

    public Block(int[] val) {
        this.val = val;
    }
}

package puyopuyo;

/**
 * @Author jinjun99
 * @Date Created in 2021/11/21 13:00
 * @Description
 * @Since version-1.0
 */
public class Point {
    int x = 0;
    int y = 0;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public Point() {
    }
}

package puyopuyo;

import java.util.Arrays;
import java.util.Stack;

/**
 * @Author jinjun99
 * @Date Created in 2021/11/21 17:36
 * @Description
 * @Since version-1.0
 */
public class Demo02 {
    /**
     * 宽度
     */
    private static int width = 4;
    /**
     * 高度
     */
    private static int height = 6;
    /**
     * 地图
     */
    private static int[][] map = new int[height][width];
    /**
     * 标记图
     */
    private static int[][] mark = new int[height][width];
    /**
     * 列的高度,y坐标
     */
    private static int[] tail = new int[width];
    private static int[] dirX = {1,0,-1,0};
    private static int[] dirY = {0,1,0,-1};
    /**
     * 当前块
     */
    private static Block block;
    /**
     * 地图初始化
     */
    private static void inti(int w){
        width = w;
        map = new int[height][width];
    }
    /**
     * 旋转一个角度
     * @param angle
     */
    private static void rotate(int angle){
        block.dir=(block.dir+angle)%4;
        //右边界
        if (block.dir==0&&block.col==width-1){
            block.col=width-2;
        }
        if (block.dir==2&&block.col==0){
            block.col=1;
        }
    }
    /**
     * 移动一段距离
     * @param distance
     */
    private static void move(int distance){
        block.col+=distance;
        //中间区域不用考虑
        if (block.col>=1 && block.col<=width-2){
            return;
        }
        //右方向看右边界
        if (block.dir==0 && block.col>=width-1){
            block.col=width-2;
            return;
        }
        //左方向看左边界
        if (block.dir==2 && block.col<=0){
            block.col=1;
            return;
        }
        //其他方向右越界(dis过大)
        if (block.col > width-1){
            block.col = width-1;
        }
        //其他方向左越界(dis过大)
        if (block.col < 0){
            block.col = 0;
        }
    }
    private static void hinder(int count,int life){
       // block.event = 2;
        int h = height-1;
        for (int i = 0; i < count; i++) {
            map[h-tail[i]][i] = -1*life;
            tail[i]++;
        }
    }
    /**
     * 更新当前块下落后的地图,记录列高度
     * @return
     */
    private static int land(){
        //1.将一个圆叠在另一个圆上,不留空隙。
        Point p1 = new Point();
        Point p2 = new Point();
        int h = height-1;
        if (block.event==0){
            switch (block.dir){
                case 0:
                {
                    p1.x = block.col;
                    p1.y = h-tail[block.col];
                    map[p1.y][p1.x] = block.val[0];
                    p2.x = block.col+1;
                    p2.y = h-tail[block.col];
                    map[p2.y][p2.x] = block.val[1];
                    tail[block.col]++;
                    tail[block.col+1]++;
                    break;
                }
                case 1:
                {
                    p1.x = block.col;
                    p1.y = h-(tail[block.col]+1);
                    map[p1.y][p1.x] = block.val[0];
                    p2.x = block.col;
                    p2.y = h-tail[block.col];
                    map[p2.y][p2.x] = block.val[1];
                    tail[block.col]+=2;
                    break;
                }
                case 2:
                {
                    p1.x = block.col;
                    p1.y = h-tail[block.col];
                    map[p1.y][p1.x] = block.val[0];
                    p2.x = block.col-1;
                    p2.y = h-tail[block.col-1];
                    map[p2.y][p2.x] = block.val[1];
                    tail[block.col]++;
                    tail[block.col-1]++;
                    break;
                }
                case 3:
                {
                    p1.x = block.col;
                    p1.y = h-tail[block.col];
                    map[p1.y][p1.x] = block.val[0];
                    p2.x = block.col;
                    p2.y = h-(tail[block.col]+1);
                    map[p2.y][p2.x] = block.val[1];
                    tail[block.col]+=2;
                    break;
                }
                default:
                    break;
            }
            solution(p1,p2);
        }
        int j=0;
        for (int i = 0; i < width; i++) {
            j= Math.max(tail[i], j);
        }
        return j;
    }
    private static Point[] drop = new Point[width*height];

    /**
     * 块下落后的消除
     * @param p1
     * @param p2
     */
    private static void solution(Point p1,Point p2){
        int dropNum = 2;
        drop[0] = p1;
        drop[1] = p2;

        while (dropNum!=0){
            for (int i = 0; i < dropNum; i++) {
                //一组两个颜色相同
                if (mark[drop[i].y][drop[i].x] == 1){
                    continue;
                }
                dfs(drop[i].x,drop[i].y);
                clear();
            }
            markHinder();
            dropNum = updateMap();
        }
    }
    private static Stack<Point> elimP = new Stack<>();
    private static int[][] mark2 = new int[height][width];

    /**
     * 搜索4个同色相连块,放入搜索队列
     * @param x
     * @param y
     */
    private static void dfs(int x,int y){
        mark2[y][x] = 1;
        elimP.push(new Point(x,y));
        for (int i = 0; i < 4; i++) {
            int a = x+dirX[i];
            int b = y+dirY[i];
            if (a>=0&&a<width&&b>=0&&b<height&&map[b][a]==map[y][x]&&mark2[b][a]==0){
                dfs(a,b);
            }
        }
    }

    /**
     * 根据搜索结果清理同色块
     */
    private static void clear(){
        int s = elimP.size();
        if (s>=4){
            for (int i = 0; i < s; i++) {
                Point p = elimP.pop();
                map[p.y][p.x]=0;
                mark[p.y][p.x]=1;
                tail[p.x]--;
            }
        }
        elimP.removeAllElements();

    }
    /**
     * 消除同色块后,更新阻碍块寿命和位置,顺便消除标记
     */
    private static void markHinder(){
        int h = height-1;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j <= tail[i]; j++) {
                if (map[h-j][i]<0){
                    if (check(h-j,i)==1){
                        map[h-j][i] += 1;
                        if (map[h-j][i]==0){
                            tail[i]--;
                        }
                    }
                }
            }
        }
        mark2 = new int[height][width];
        mark = new int[height][width];
    }

    /**
     * 同色块消除后,把空中的块放下来,顺便放入搜索队列
     * @return 空中块的数量
     */
    private static int updateMap(){
        int c = 0;
        int s = 0;
        int sum = 0;
        int h = height-1;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < tail[i]; j++) {
                int l = h-j;
                if (map[l][i]==0){
                    if (j>=tail[i]){
                        break;
                    }
                    //j=1,c=3
                    while (map[l-c][i]==0&&j+c<tail[i]){
                        c++;
                    }
                    if (j+c+1==tail[i]){
                        tail[i]=j;
                        break;
                    }
                    if (map[l-c][i]>0) {
                        map[l][i] = map[l - c][i];
                        map[l - c][i] = 0;
                        drop[s].x = i;
                        drop[s++].y = l;
                        sum++;
                    }
                    if (map[l-c][i]<0) {
                        map[l][i] = map[l - c][i];
                        map[l - c][i] = 0;
                    }
                }
            }
        }
        return sum;

    }

    /**
     * 查看阻碍块四周是否有爆裂的同色块
     * @param y
     * @param x
     * @return
     */
    private static int check(int y,int x){
        for (int i = 0; i < 4; i++) {
            int a = y+dirY[i];
            int b = x+dirX[i];
            if (a>=0&&b>=0&&a<height&&b<width&&mark[a][b]==1){
                return 1;
            }
        }
        return 0;
    }

    public static void main(String[] args) {
        int sum = 0;
        block = new Block(new int[]{1,1});
        rotate(0);
        move(1);
        sum = land();
        hinder(2,2);
        hinder(4,1);
        block = new Block(new int[]{2,2});
        rotate(0);
        move(2);
        sum = land();
        block = new Block(new int[]{1,1});
        rotate(1);
        move(2);
        sum = land();
        block = new Block(new int[]{2,2});
        rotate(1);
        move(3);
        sum = land();

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (map[i][j]<0){
                    System.out.print(map[i][j]);
                }else {
                    System.out.print(" "+map[i][j]);
                }
                if (j==width-1){
                    System.out.println();
                }
            }
        }
        System.out.println("最高列长度是:"+sum);
    }
}

负数代表阻碍块生命值,正数代表颜色,0为空

打印一下过程:

 0 0 0 0
 0 0 0 0
 0 0 0 0
 0 0 0 0
 0 0 0 0
 0 1 1 0
最高列长度是:1

 0 0 0 0
 0 0 0 0
 0 0 0 0
 0-1 2 0
-1-2-1 2
-2 1 1-1
最高列长度是:3

 0 0 0 0
 0 0 1 0
 0 0 1 0
 0-1 2 0
-1-2-1 2
-2 1 1-1
最高列长度是:5

 0 0 0 0
 0 0 0 0
 0 0 0 0
 0 0 0 0
-1 0 0 0
-1-1 0 0
最高列长度是:2
posted @ 2021-11-24 13:20  矜君  阅读(182)  评论(0编辑  收藏  举报