Java Processing无类实现记忆卡牌游戏:洗牌功能异常求助
记忆卡牌游戏全局洗牌(含死亡卡牌)解决方案
问题说明
作业要求使用Java Processing制作记忆卡牌游戏,禁止使用类。已完成游戏主体功能,现在需要添加死亡卡牌:
- 采用二维数组存储卡牌,死亡卡牌存入第三行(索引2)
- 当前
shuffle()函数仅在各行内部洗牌,导致死亡卡牌始终处于末尾,无法与其他卡牌混合打乱
原代码问题分析
原shuffle()函数对每一行单独执行洗牌逻辑,行与行之间没有任何元素交换,因此死亡卡牌所在的第三行永远和前两行的普通卡牌分离,无法实现全局混合。
解决方案
使用Fisher-Yates洗牌算法(公平高效的标准洗牌算法),将所有卡牌(包括前两行的普通卡牌和第三行的死亡卡牌)视为一个整体进行随机交换。核心思路是把二维数组的元素映射为一维索引,遍历每个位置并与随机位置交换所有卡牌数据(包括卡牌标识、坐标)。
步骤1:修正初始化代码
原初始化中死亡卡牌的坐标存储在第二行,容易导致数组越界,需改为存入第三行,与gekozenKaart数组保持一致:
for (int i=0; i<3; i++) { if (i == 0 || i == 1) { for (int j=0; j<aantalSetjes; j++) { y[i][j] = yKaart; x[i][j] = xKaart; gekozenKaart[i][j] = teller; teller +=1; if (teller > aantalSetjes) { teller = 1; } if (xKaart<=(kaartBreedte * getSpeelveldBreedteKeer())-kaartBreedte) { xKaart += kaartBreedte; } else if (xKaart>=(kaartBreedte * getSpeelveldBreedteKeer())-kaartBreedte) { xKaart=15; yKaart += kaartLengte; } } } else if (i == 2) { for (int j=0; j<getAantalDoodsKaarten(); j++) { // 修正:将死亡卡牌的坐标存入第三行,与gekozenKaart对应 y[i][j] = yKaart; x[i][j] = xKaart; gekozenKaart[i][j] = teller; teller +=1; if (teller > getAantalDoodsKaarten()) { teller = 1; } if (xKaart<=(kaartBreedte * getSpeelveldBreedteKeer())-kaartBreedte) { xKaart += kaartBreedte; } else if (xKaart>=(kaartBreedte * getSpeelveldBreedteKeer())-kaartBreedte) { xKaart=15; yKaart += kaartLengte; } } } } shuffle();
步骤2:替换全局洗牌函数
重写shuffle()函数,实现跨行列的全局洗牌:
void shuffle() { // 计算所有卡牌的总数:2组普通卡牌 + 死亡卡牌数量 int totalCards = 2 * aantalSetjes + getAantalDoodsKaarten(); // Fisher-Yates洗牌:从最后一张牌向前遍历 for (int k = totalCards - 1; k > 0; k--) { // 生成0到当前索引k之间的随机位置 int randomIndex = int(random(0, k + 1)); // 将一维索引转换为二维数组的(i,j)坐标 int i1, j1, i2, j2; // 处理随机索引对应的二维位置 if (randomIndex < aantalSetjes) { i1 = 0; j1 = randomIndex; } else if (randomIndex < 2 * aantalSetjes) { i1 = 1; j1 = randomIndex - aantalSetjes; } else { i1 = 2; j1 = randomIndex - 2 * aantalSetjes; } // 处理当前索引k对应的二维位置 if (k < aantalSetjes) { i2 = 0; j2 = k; } else if (k < 2 * aantalSetjes) { i2 = 1; j2 = k - aantalSetjes; } else { i2 = 2; j2 = k - 2 * aantalSetjes; } // 交换卡牌标识(gekozenKaart) int tempGekozen = gekozenKaart[i1][j1]; gekozenKaart[i1][j1] = gekozenKaart[i2][j2]; gekozenKaart[i2][j2] = tempGekozen; // 交换x坐标 float tempX = x[i1][j1]; x[i1][j1] = x[i2][j2]; x[i2][j2] = tempX; // 交换y坐标 float tempY = y[i1][j1]; y[i1][j1] = y[i2][j2]; y[i2][j2] = tempY; } }
效果说明
修改后,所有卡牌(普通卡牌和死亡卡牌)会被完全随机打乱,死亡卡牌不再固定在末尾位置,符合全局洗牌的需求。
内容的提问来源于stack exchange,提问作者bossman
相关产品推荐
相关产品推荐

