简单消消乐
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]; } } }