约瑟夫环随机洗牌
//今天做作业时,想着可不可以用一个随机数(整数)对一副扑克牌进行随机洗牌,发现当数据排成一个环时,使用可以实现,于是想到了约瑟夫环
//注:java,代码完全由kimi生成
package task004;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
public class RealRandNum {
// 修复:去掉 URL 末尾的空格
private static final String API_URL =
"https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain&rnd=new";
public static void main(String[] args) throws Exception {
// 1. 获取真随机数作为约瑟夫环的步长
int step = fetchRandomNumber();
System.out.println("随机步长: " + step);
// 2. 初始化54张扑克牌 (0-53,可映射到 红桃A-K,方块A-K,黑桃A-K,梅花A-K,大小王)
List<Integer> deck = new ArrayList<>();
for (int i = 0; i < 54; i++) {
deck.add(i);
}
System.out.println("原始牌序: " + deck);
// 3. 使用约瑟夫环算法打乱
List<Integer> shuffled = josephusShuffle(deck, step);
System.out.println("约瑟夫环打乱后: " + shuffled);
// 4. 映射为扑克牌名称(可选)
printPokerNames(shuffled);
}
// 获取随机数(修复异步赋值问题)
private static int fetchRandomNumber() throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.header("User-Agent", "Java TrueRandom Client")
.GET()
.build();
CompletableFuture<HttpResponse<String>> future =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// 修复:使用 AtomicReference 包装,解决 Lambda 中赋值问题
AtomicReference<String> resultRef = new AtomicReference<>();
future.thenAccept(response -> {
resultRef.set(response.body().trim());
}).join();
return Integer.parseInt(resultRef.get());
}
/**
* 约瑟夫环洗牌算法
* @param deck 初始牌组
* @param step 步长(每次数 step 张牌,第 step 张出列)
* @return 打乱后的牌序(出列顺序)
*/
private static List<Integer> josephusShuffle(List<Integer> deck, int step) {
List<Integer> result = new ArrayList<>();
List<Integer> temp = new ArrayList<>(deck); // 工作副本
int index = 0;
while (!temp.isEmpty()) {
// 计算下一个要移除的位置:(当前索引 + 步长 - 1) % 剩余数量
index = (index + step - 1) % temp.size();
// 移除该位置的牌,加入结果
result.add(temp.remove(index));
// 注意:remove 后,index 位置自动被后续元素填补
// 下一轮从当前 index 开始计数(如果从0开始需要调整,但这里 index 已经指向下一个元素)
// 如果 index == temp.size(),说明刚好在末尾,下一轮回到0
}
return result;
}
// 将数字映射为扑克牌名称(0-51为52张牌,52小王,53大王)
private static void printPokerNames(List<Integer> shuffled) {
String[] suits = {"♥", "♦", "♠", "♣"};
String[] ranks = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
System.out.println("扑克牌映射:");
for (int i = 0; i < shuffled.size(); i++) {
int card = shuffled.get(i);
String name;
if (card == 52) name = "小王";
else if (card == 53) name = "大王";
else {
name = suits[card / 13] + ranks[card % 13];
}
System.out.printf("第%2d张: %s%n", i + 1, name);
}
}
}

浙公网安备 33010602011771号