You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android拼单词游戏实现:答案字母拆分及干扰字母随机展示问题

Android拼单词游戏动态字母生成实现

我正在开发一款Android拼单词游戏Activity,玩法为系统随机展示若干字母,用户选择对应字母拼接为正确单词即可通关。我已定义存储正确答案的单词字符串数组,当前需要实现以下需求:将选中的答案单词拆分为单个字母,额外添加若干随机字母作为干扰项,将所有字母打乱顺序后展示给用户选择。例如答案为World时,拆分得到W、O、R、L、D后混入干扰字母,再打乱顺序供玩家选择。

现有代码

TextView guessItTimer;
CountDownTimer timer;
Random r;
String currentWord;

private int presCounter = 0;
private int maxPresCounter = 4;
private String[] keys = {"R", "I", "B", "D", "X"};
String dictionary[] = {
        "remember",
        "hungry",
        "crying",
        "sour",
        "sleep",
        "awesome",
        "Seven",
        "color",
        "began",
        "appear",
        "weight",
        "language"
};
TextView textScreen, textQuestion, textTitle;
Animation smallbigforth;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_guess_it);

    guessItTimer = findViewById(R.id.guessItTimer);
    smallbigforth = AnimationUtils.loadAnimation(this, R.anim.smallbigforth);

    keys = shuffleArray(keys);
    for (String key : keys) {
        addView(( findViewById(R.id.layoutParent)), key, findViewById(R.id.et_guess));
    }
    maxPresCounter = 4;

    resetTimer();
}

//倒计时逻辑
void resetTimer() {
   timer = new CountDownTimer(30150, 1000) {
        @Override
        public void onTick(long l) {
            guessItTimer.setText(String.valueOf(l / 1000));
        }
        @Override
        public void onFinish() {
            Toast.makeText(GuessItActivity.this, "时间到", Toast.LENGTH_SHORT).show();
            startActivity(new Intent(GuessItActivity.this, BossFinalActivity.class));
            finish();
        }
    }.start();
}
private String[] shuffleArray(String[] ar) {
    Random rnd = new Random();
    for (int i = ar.length - 1; i > 0; i--) {
        int index = rnd.nextInt(i + 1);
        String a = ar[index];
        ar[index] = ar[i];
        ar[i] = a;
    }
    return ar;
}
private void addView(LinearLayout viewParent, final String text, final EditText editText) {
    LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
    );
    linearLayoutParams.rightMargin = 30;

    final TextView textView = new TextView(this);
    textView.setLayoutParams(linearLayoutParams);
    textView.setBackground(this.getResources().getDrawable(R.drawable.bgpink));
    textView.setTextColor(this.getResources().getColor(R.color.colorPurple));
    textView.setGravity(Gravity.CENTER);
    textView.setText(text);
    textView.setClickable(true);
    textView.setFocusable(true);
    textView.setTextSize(32);

    textQuestion = findViewById(R.id.textQuestionBoss);
    textScreen = findViewById(R.id.gametitle);
    textTitle =  findViewById(R.id.Ammo);

    textView.setOnClickListener(new View.OnClickListener() {

        @SuppressLint("SetTextI18n")
        @Override
        public void onClick(View v) {
            if(presCounter < maxPresCounter) {
                if (presCounter == 0)
                    editText.setText("");
                editText.setText(editText.getText().toString() + text);
                textView.startAnimation(smallbigforth);
                textView.animate().alpha(0).setDuration(300);
                presCounter++;
                if (presCounter == maxPresCounter)
                    doValidate();
            }
        }
    });

    viewParent.addView(textView);
}

private void doValidate() {
    presCounter = 0;
    EditText editText = findViewById(R.id.et_guess);
    LinearLayout linearLayout = findViewById(R.id.layoutParent);

    currentWord = dictionary[r.nextInt(dictionary.length)];


    if(editText.getText().toString().equals(currentWord)) {
        //Toast.makeText(GuessItActivity.this, "回答正确", Toast.LENGTH_SHORT).show();
        Intent a = new Intent(GuessItActivity.this,BossFinalActivity.class);
        startActivity(a);
        editText.setText("");
    } else {
        Toast.makeText(GuessItActivity.this, "回答错误", Toast.LENGTH_SHORT).show();
        editText.setText("");
    }
    keys = shuffleArray(keys);
    linearLayout.removeAllViews();
    for (String key : keys) {
        addView(linearLayout, key, editText);
    }
}

public void onBackPressed() {
    timer.cancel();
    this.finish();
    super.onBackPressed();
}

修改实现方案

新增辅助方法

首先新增两个辅助方法,分别用于生成随机干扰字母、动态拼接正确字母和干扰字母并打乱:

// 生成随机大写英文字母
private char getRandomLetter() {
    return (char) ('A' + r.nextInt(26));
}

/**
 * 生成待选字母数组
 * @param targetWord 正确答案单词
 * @param distractCount 干扰字母数量
 * @return 打乱后的待选字母数组
 */
private String[] generateKeys(String targetWord, int distractCount) {
    // 统一转大写避免大小写匹配问题
    String upperWord = targetWord.toUpperCase();
    List<String> keyList = new ArrayList<>();
    // 添加正确单词的所有字母
    for (char c : upperWord.toCharArray()) {
        keyList.add(String.valueOf(c));
    }
    // 添加指定数量的干扰字母
    for (int i = 0; i < distractCount; i++) {
        keyList.add(String.valueOf(getRandomLetter()));
    }
    // 转数组后打乱顺序
    String[] keysArr = keyList.toArray(new String[0]);
    return shuffleArray(keysArr);
}

// 新增题目初始化方法,复用逻辑
private void initNewWord() {
    EditText editText = findViewById(R.id.et_guess);
    LinearLayout layoutParent = findViewById(R.id.layoutParent);
    // 先随机选取本次要猜的目标单词
    currentWord = dictionary[r.nextInt(dictionary.length)];
    // 生成待选字母,这里设置干扰字母为3个,可按需调整
    keys = generateKeys(currentWord, 3);
    // 最大可输入长度同步为当前单词的长度
    maxPresCounter = currentWord.length();
    // 重置输入框和字母视图
    editText.setText("");
    layoutParent.removeAllViews();
    for (String key : keys) {
        addView(layoutParent, key, editText);
    }
}

修改初始化逻辑

修改onCreate方法,补充Random实例初始化,调用题目初始化方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_guess_it);

    guessItTimer = findViewById(R.id.guessItTimer);
    smallbigforth = AnimationUtils.loadAnimation(this, R.anim.smallbigforth);
    // 初始化Random实例,修复原代码空指针隐患
    r = new Random();
    // 初始化第一道题目
    initNewWord();

    resetTimer();
}

修改验证逻辑

修正原代码先验证后选目标单词的逻辑错误,调整为使用当前已生成的目标单词做校验:

private void doValidate() {
    presCounter = 0;
    EditText editText = findViewById(R.id.et_guess);
    LinearLayout linearLayout = findViewById(R.id.layoutParent);
    // 统一转大写对比,兼容单词大小写混合场景
    if(editText.getText().toString().toUpperCase().equals(currentWord.toUpperCase())) {
        Toast.makeText(GuessItActivity.this, "回答正确", Toast.LENGTH_SHORT).show();
        // 答对后跳转页面,若需要继续出题可替换为调用initNewWord()
        Intent a = new Intent(GuessItActivity.this,BossFinalActivity.class);
        startActivity(a);
        editText.setText("");
    } else {
        Toast.makeText(GuessItActivity.this, "回答错误", Toast.LENGTH_SHORT).show();
        editText.setText("");
        // 答错后重新打乱当前题目字母,用户可重拼;若需要直接换题可替换为调用initNewWord()
        keys = shuffleArray(keys);
        linearLayout.removeAllViews();
        for (String key : keys) {
            addView(linearLayout, key, editText);
        }
    }
}

注意事项

  • 干扰字母数量可按需调整,也可根据单词长度动态设置,比如单词长度超过5个字母时设置4个干扰项
  • 若需要区分大小写校验,可删除转大写的逻辑,同时保证词典内单词和用户输入的大小写统一

内容的提问来源于stack exchange,提问作者ElG0hary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:36:03