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];
}
}
}