Android Studio(Java)问答开发:如何生成无重复随机答案选项
问题原因
你现在出现选项重复、逻辑不符合预期,核心是三个实现错误:
- 随机选答案的逻辑写在了Adapter的
getView()方法里,ListView每渲染一个列表项、甚至列表滑动重绘时都会重新跑一次随机逻辑,没有任何去重校验,抽到重复值是必然结果 - 随机逻辑完全没有关联当前展示的国旗,既没有把对应正确答案加入选项池,也没有排除重复选项、排除正确答案的判断
- 每次执行随机都新建
Random实例,在短时间多次调用时因为随机种子接近,会进一步提升重复值出现的概率
修复方案
不要在列表渲染阶段做选项生成逻辑,正确流程是选中随机国旗时一次性生成好4个固定、不重复、顺序打乱的选项,再传给Adapter做纯渲染:
- 随机选中目标国旗后,先记录对应正确答案的下标
- 初始化选项集合,优先放入正确答案
- 循环随机抽取错误答案,每次抽取都校验:不能是正确答案、不能和已加入选项池的内容重复,直到凑够3个错误答案
- 打乱整个选项集合的顺序,避免正确答案出现在固定位置
- 将最终生成的4个选项传入Adapter,Adapter仅按位置读取对应内容渲染即可,不再执行任何随机逻辑
另外你原来的getView()没有做缓存复用,每次都inflate新布局会造成列表滑动卡顿,修复时一并处理。
修复后完整代码
package com.example.guesstheflag; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; public class StartGameActivity extends AppCompatActivity { private ListView listView; private ImageView imageView; // 存储最终生成的4个待展示选项 private final List<String> optionList = new ArrayList<>(); // 以下两个是你原有数据源,保持下标一一对应即可 private int[] flags; // 国旗图片资源ID数组 private String[] answers; // 对应国家名称数组 private int currentCorrectIndex; // 当前展示国旗对应的正确答案下标 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_start_game); listView = findViewById(R.id.myList); imageView = findViewById(R.id.imagernd); Random globalRandom = new Random(); // 随机选取本次要展示的国旗 currentCorrectIndex = globalRandom.nextInt(flags.length); imageView.setImageResource(flags[currentCorrectIndex]); // 一次性生成所有选项 generateValidOptions(currentCorrectIndex, globalRandom); // 传入固定选项集初始化适配器 MyAdapter myAdapter = new MyAdapter(optionList); listView.setAdapter(myAdapter); } // 生成符合要求的4个不重复选项 private void generateValidOptions(int correctIndex, Random rnd) { optionList.clear(); // 先加入正确答案 optionList.add(answers[correctIndex]); // 循环抽取3个不重复的错误答案 while (optionList.size() < 4) { int randomIndex = rnd.nextInt(answers.length); String randomAnswer = answers[randomIndex]; // 跳过正确答案、跳过已经存在的重复选项 if (randomIndex != correctIndex && !optionList.contains(randomAnswer)) { optionList.add(randomAnswer); } } // 打乱选项顺序,避免正确答案位置固定 Collections.shuffle(optionList); } // 列表适配器,仅做渲染,不处理业务逻辑 class MyAdapter extends BaseAdapter { private final List<String> showOptions; public MyAdapter(List<String> options) { this.showOptions = options; } @Override public int getCount() { return showOptions.size(); } @Override public Object getItem(int position) { return showOptions.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // 复用缓存View,避免重复加载布局卡顿 if (convertView == null) { LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.custom, null); } TextView optionText = convertView.findViewById(R.id.myText); // 直接按位置读取预先生成好的选项 optionText.setText(showOptions.get(position)); return convertView; } } }
额外说明
如果你的答案数组里本身存在重复的国家名称,需要先去重再做随机抽取,否则还是会出现重复选项。如果后续要做答对/答错判断,直接判断用户点击的选项内容是否等于answers[currentCorrectIndex]即可。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

