简单消消乐

package com.cgx.datastructure.leetcode;

import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 消消乐
 */
public class EliminationGames {
    @Test
    public void test() {
        String[] candidates  = {"✭", "✪", "⚝", "✦", "♠", "♥", "♣", "❆", "⁂"};
        int n = 6;
        String[] target = new String[n * n];
        // 生成目标星星
        generateTarget(n, target, candidates);
        // 打印
        printGrid(n, target);

        // 使用广度优先遍历,声明一个匹配队列
        Queue<Integer> queue = new ArrayDeque<>();
        // 结果索引
        Set<Integer> res = new HashSet<>();
        int clickPos = new Random().nextInt(target.length);
        System.out.println("点击位置:" + clickPos);
        queue.offer(clickPos);
        res.add(clickPos);
        while (!queue.isEmpty()) {
            // 拿第一个元素检查
            int idx = queue.poll();
            String str = target[idx];

            // 广度遍历(查找前驱和后继就行,不需要全部遍历)
            // 所在列的临界索引
            int x = idx / n, xl = x * n, xr = xl + n - 1;
            // 所在的列的前驱和后继
            int left = idx - 1, right = idx + 1;
            // 判断是否相同且没有匹配过的
            if (left >= xl && str.equals(target[left]) && !res.contains(left)) {
                queue.offer(left);
                res.add(left);
            }
            if (right <= xr && str.equals(target[right]) && !res.contains(right)) {
                queue.offer(right);
                res.add(right);
            }
            // 深度遍历(查找上一个和下一个就行,不需要全部遍历)
            // 所在的行的上一行和下一行的索引
            int up = idx - n, down = idx + n;
            // 判断是否相同且没有匹配过的
            if (up >= 0 && str.equals(target[up]) && !res.contains(up)) {
                queue.offer(up);
                res.add(up);
            }
            if (down < target.length && str.equals(target[down]) && !res.contains(down)) {
                queue.offer(down);
                res.add(down);
            }
        }

        System.out.println("相同:");
        System.out.println(res.toString());

        // 消去
        System.out.println("消去:");
        clear(target, res);
        printGrid(n, target);

        // 填充
        System.out.println("填充:");
        fix(n, target, res, candidates);
        printGrid(n, target);
    }

    public void generateTarget(int n, String[] target, String[] candidates) {
        Random rand = new Random();
        int randInt = 0;
        int bound = (n - 1) % candidates.length;
        for (int i = 0; i < target.length; i++) {
            randInt = rand.nextInt(bound);
            target[i] = candidates[randInt];
        }
    }

    public void printGrid(int n, String[] target) {
        for (int i = 0; i < target.length; i++) {
            System.out.printf("%3s", target[i]);
            if (i != 0 && (i + 1) % n == 0) {
                System.out.println();
            }
        }
    }

    public void clear(String[] target, Set<Integer> index) {
        for (int idx : index) {
            target[idx] = " ";
        }
    }

    public void fix(int n, String[] target, Set<Integer> index, String[] candidates) {
        // 从大到小排序
        List<Integer> orderIndex = index.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        // 清空,用于存储哪些索引需要重新生成
        index.clear();

        while (!orderIndex.isEmpty()) {
            int idx = orderIndex.remove(0);
            int up = idx - n;
            index.add(idx);
            if (up >= 0) {
                do {
                    index.add(up);
                    if (!target[up].equals(" ")) {
                        target[idx] = target[up];
                        target[up] = " ";
                        index.remove(idx);
                        orderIndex.add(0, up);
                        break;
                    } else {
                        orderIndex.add(0, up);
                        up -= n;
                    }
                } while (up >= 0);
                // 排重,排序
                orderIndex = orderIndex.stream().distinct().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
            }
        }

        // 需要重新生成的索引
        System.out.println(index.toString());

        // 重新生成
        resetGenerateTarget(n, target, index, candidates);
    }

    public void resetGenerateTarget(int n, String[] target, Set<Integer> index, String[] candidates) {
        n = (n - 1) % candidates.length;
        Random rand = new Random();
        for (int idx : index) {
            int rdx = rand.nextInt(n);
            target[idx] = candidates[rdx];
        }
    }
}

 

posted @ 2022-02-27 18:07  黎明的星海  阅读(65)  评论(0编辑  收藏  举报