ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

PuyoPuyo DFS算法练习

2021-11-24 13:32:37  阅读:140  来源: 互联网

标签:p2 p1 int tail DFS 算法 PuyoPuyo col block


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

标签:p2,p1,int,tail,DFS,算法,PuyoPuyo,col,block
来源: https://www.cnblogs.com/jinjun99/p/15597658.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有