按下按钮时随机活动

问题描述 投票:0回答:1

我想做一个游戏,如果我按下播放按钮,随机关卡(活动)将打开。我得到了这个代码。https:/stackoverflow.coma2957937313101103。这是可行的,但我想编辑一下,例如,所有的关卡都有两个不同的答案,答案1是失败,答案2是通过关卡,如果用户通过了第1关,而在第2关失败,则回到主活动,如果重新开始,则通过的关卡将不会再显示。

例如:有5个关卡,用户开始随机关卡,例如第3关,通过了,进入下一个随机关卡,例如第2关,通过了,进入下一个......第4关,失败了,回到主活动,用户再次开始,但是已经通过的关卡不会显示,只有未通过的......例如开始第3关......如果通过了,则进入第1关......。

我如何编辑这段代码?谁能给我一些提示?因为在这段代码中,如果我回到mainactivity并重新开始,那么它将从所有级别开始...... 我试着编辑,但我卡住了,无法工作......

另外,我想在用户离开应用时保存进度。在sharedpreferences中,我如何保存已通过的关卡(数组列表)......?

MainActivity:

enter code here

Button level1Button = findViewById(R.id.level1Button);
    level1Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // We are creating a list, which will store the activities that haven't been opened yet
            ArrayList<Class> activityList = new ArrayList<>();
            activityList.add(Level1Activity.class);
            activityList.add(Level2Activity.class);
            activityList.add(Level3Activity.class);
            activityList.add(Level4Activity.class);
            activityList.add(Level5Activity.class);

            Random generator = new Random();
            int number = generator.nextInt(5) + 1;

            Class activity = null;

            // Here, we are checking to see what the output of the random was
            switch(number) {
                case 1:
                    activity = Level1Activity.class;
                    // We are adding the number of the activity to the list
                    activityList.remove(Level1Activity.class);
                    break;
                case 2:
                    activity = Level2Activity.class;
                    activityList.remove(Level2Activity.class);
                    break;
                case 3:
                    activity = Level3Activity.class;
                    activityList.remove(Level3Activity.class);
                    break;
                case 4:
                    activity = Level4Activity.class;
                    activityList.remove(Level4Activity.class);
                    break;
                default:
                    activity = Level5Activity.class;
                    activityList.remove(Level5Activity.class);
                    break;
            }
            // We use intents to start activities
            Intent intent = new Intent(getBaseContext(), activity);
            // `intent.putExtra(...)` is used to pass on extra information to the next activity
            intent.putExtra("ACTIVITY_LIST", activityList);
            startActivity(intent);
        }
    });

Level1AActivity: Level2, Level3..:

enter code here
failbutton1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v){
            ArrayList<Class> activityList = new ArrayList<>();
            activityList.add(Level1Activity.class);
            Bundle extras = getIntent().getExtras();
            activityList = (ArrayList<Class>) extras.get("ACTIVITY_LIST");


            //Class activity = null;


            Intent intent = new Intent(Level1Activity.this, Main2Activity.class);
            intent.putExtra("ACTIVITY_LIST", activityList);
            startActivity(intent);
        }
    });

    buttonlevel1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ArrayList<Class> activityList = new ArrayList<>();
            Bundle extras = getIntent().getExtras();
            activityList = (ArrayList<Class>) extras.get("ACTIVITY_LIST");

            if(activityList.size() == 0) {
                // Do something when after all activities have been opened
                //startActivity(new Intent(Level1Activity.this, Main2Activity.class));

                //Intent intent = new Intent(Level1Activity.this, Main2Activity.class);
                //intent.putExtra("ACTIVITY_LIST", activityList);
                //startActivity(intent);
            } else {
                // Now, the random number is generated between 1 and however many
                // activities we have remaining
                Random generator = new Random();
                int number = generator.nextInt(activityList.size()) + 1;

                Class activity = null;

                // Here, we are checking to see what the output of the random was
                switch(number) {
                    case 1:
                        // We will open the first remaining activity of the list
                        activity = activityList.get(0);
                        // We will now remove that activity from the list
                        activityList.remove(0);
                        break;
                    case 2:
                        // We will open the second remaining activity of the list
                        activity = activityList.get(1);
                        activityList.remove(1);
                        break;
                    case 3:
                        // We will open the third remaining activity of the list
                        activity = activityList.get(2);
                        activityList.remove(2);
                        break;
                    case 4:
                        // We will open the fourth remaining activity of the list
                        activity = activityList.get(3);
                        activityList.remove(3);
                        break;
                    default:
                        // We will open the fifth remaining activity of the list
                        activity = activityList.get(4);
                        activityList.remove(4);
                        break;
                }

                // Note: in the above, we might not have 3 remaining activities, for example,
                // but it doesn't matter because that case wouldn't be called anyway,
                // as we have already decided that the number would be between 1 and the number of
                // activities left.


                // Starting the activity, and passing on the remaining number of activities
                // to the next one that is opened
                Intent intent = new Intent(getBaseContext(), activity);
                intent.putExtra("ACTIVITY_LIST", activityList);
                startActivity(intent);
            }
        }
    });

level2, level3......是一样的,只是id-s不同。

java android random android-activity
1个回答
1
投票

我建议使用 单人模式 来处理活动之间的数据传递。

你可以通过intent的 putExtra() 或以 SharedPreferences 但有 Singleton 类,它看起来更好,更容易操作你的数据,因为它们是 囊化. 所以在你想保存关卡状态的情况下(例如,当它们已经完成时)。

然而,如果你真的坚持使用 SharedPreferences 如果要保存列表,那么我建议将其转换为 Json 借用 Gson. (请看下面我的回答,如何实现这个功能)。

正如我所说,我会使用 Singleton 模式,以避免创建不必要的模板代码并封装关卡的状态。

LevelManager类

final class LevelManager {

    // constants
    private static final String LEVELS_SHARED_PREFERENCES_NAME = "app_name.LEVELS";

    // variables
    private static LevelManager instance;
    private List<Class> levels;
    private SharedPreferences sharedPreferences;

    private LevelManager(Context context) {
        sharedPreferences =
                context.getSharedPreferences(LEVELS_SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
        levels = new ArrayList<>();
        initializeList();
    }

    private void initializeList() {
        // Initialize levels, ie. add levels that are not yet completed/passed
        // Check in SharedPreferences if level has already been completed
        boolean alreadyPassed;

        alreadyPassed = sharedPreferences.getBoolean(Level1Activity.class.getSimpleName(), false);
        if (!alreadyPassed) levels.add(Level1Activity.class);

        alreadyPassed = sharedPreferences.getBoolean(Level2Activity.class.getSimpleName(), false);
        if (!alreadyPassed) levels.add(Level2Activity.class);

        alreadyPassed = sharedPreferences.getBoolean(Level3Activity.class.getSimpleName(), false);
        if (!alreadyPassed) levels.add(Level3Activity.class);

        alreadyPassed = sharedPreferences.getBoolean(Level4Activity.class.getSimpleName(), false);
        if (!alreadyPassed) levels.add(Level4Activity.class);

        alreadyPassed = sharedPreferences.getBoolean(Level5Activity.class.getSimpleName(), false);
        if (!alreadyPassed) levels.add(Level5Activity.class);
    }

    static LevelManager getInstance(Context context) {
        if (instance == null) {
            instance = new LevelManager(context);
        }
        return instance;
    }

    Class getRandomLevel() {
        if (levels.isEmpty()) {
            return null; // Return null if all levels are already completed
        }
        Collections.shuffle(levels);
        return levels.get(0);
    }

    void saveLevelState(Class levelClass, boolean passed) {
        sharedPreferences.edit().putBoolean(levelClass.getSimpleName(), passed).apply();
        if (passed) {
            // Remove level from list if user passed it so that it won't
            // be included in next levels
            levels.remove(levelClass);
        }
    }

    void reset() {
        // Clears all entries in SharedPreferences and re-initialize list
        sharedPreferences.edit().clear().apply();
        initializeList();
    }

}

在MainActivity的onCreate里面

// Get LevelManager singleton instance
final LevelManager levelManager = LevelManager.getInstance(this);

Button startButton = findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Get next random level
        Class levelToStart = levelManager.getRandomLevel();

        // If all levels are already completed
        if (levelToStart == null) {
            Toast.makeText(MainActivity.this, "All levels are completed!",
                    Toast.LENGTH_LONG).show();
            return;
        }

        Intent intent = new Intent(MainActivity.this, levelToStart);
        startActivity(intent);
    }
});

// I added a new button to reset all levels
Button resetButton = findViewById(R.id.resetButton);
resetButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Use the method reset() from LevelManager to restart everything
        levelManager.reset();
        Toast.makeText(MainActivity.this, "All levels have been reset!",
                Toast.LENGTH_LONG).show();
    }
});

在每个关卡活动的onCreate里面。

// Get LevelManager
final LevelManager levelManager = LevelManager.getInstance(this);

// I created two buttons to simulate pass and fail
Button pass = findViewById(R.id.passButton);
Button fail = findViewById(R.id.failButton);

pass.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Save state (Don't forget to change 'N' below)
        levelManager.saveLevelState(LevelNActivity.class, true);

        // Get next level
        Class levelToStart = levelManager.getRandomLevel();

        // Check if all are levels already completed
        if (levelToStart == null) {
            Toast.makeText(LevelNActivity.this, "Completed all levels",
                    Toast.LENGTH_LONG).show();
            finish(); // Must implement to avoid going back to previous level (ie. Activity)
            return;
        }

        Intent intent = new Intent(LevelNActivity.this, levelToStart);
        startActivity(intent);
        finish();
    }
});

fail.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        finish();
    }
});

如你所见,你可以简单地使用 finish() 方法,而你则使用下面的代码进入下一关。

// Get LevelManager
LevelManager levelManager = LevelManager.getInstance(this);

// Set that the user passed this level (Change 'N' to the current level we are in)
levelManager.saveLevelState(LevelNActivity.class, true);

// Get next level
Class nextLevel = levelManager.getRandomLevel();

// If all levels are completed then 'nextLevel' will be null
if (nextLevel == null) {
    // ...
}

// Start next level and finish current
Intent intent = new Intent(this, nextLevel);
startActivity(intent);
finish();

注意: 为了避免调用 finish() 当开始下一关时,你可以把它明确地放在 android:noHistory="true" 在你的manifest文件内的levels' activity标签中。


如何通过使用Gson将列表转换为Json来保存到SharedPreferences。

实际使用 Gson,你必须添加 implementation 'com.google.code.gson:gson:2.8.6' 在你的app gradle依赖里面。

另外,在 Gson 在解析 Class 对象 Json: 你需要创建自己的 序列器反序列器 这些对象,并将其注册到您的 GsonBuilder.

类适配器类 (这是我们为Class对象创建自己的自定义序列化器和反序列化器的地方)

public class ClassAdapter implements JsonSerializer<Class>, JsonDeserializer<Class> {

    @Override
    public JsonElement serialize(Class src, Type typeOfSrc, JsonSerializationContext context) {
        // Get our class 'src' name
        return new JsonPrimitive(src.getName());
    }

    @Override
    public Class deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        try {
            // Get class
            return Class.forName(json.getAsString());
        } catch (ClassNotFoundException e) {
            // If class could not be found or did not exists, handle error here...
            e.printStackTrace();
        }
        return null;
    }

}

下面是一个将列表保存到的示例用法。SharedPreferencesJson 使用 Gson:

// Create new GsonBuilder and register our adapter for Class objects
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Class.class, new ClassAdapter());

// Initialize our list of levels (ie. classes)
List<Class> classes = new ArrayList<>();
classes.add(Level1Activity.class);
classes.add(Level2Activity.class);
classes.add(Level3Activity.class);
classes.add(Level4Activity.class);
classes.add(Level5Activity.class);

// Create Gson from GsonBuilder and convert list to json
Gson gson = gsonBuilder.create();
String json = gson.toJson(classes);

// Save json to SharedPreferences
SharedPreferences sharedPreferences = getSharedPreferences("app_name", MODE_PRIVATE);
sharedPreferences.edit().putString("levels", json).apply();

并将列表找回。

// Retrieve json from SharedPreferences
SharedPreferences sharedPreferences = getSharedPreferences("app_name", MODE_PRIVATE);
String json = sharedPreferences.getString("levels", null);

// Handle here if json doesn't exist yet
if (json == null) {
    // ...
}

// Create new GsonBuilder and register our adapter for Class objects
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Class.class, new ClassAdapter());

// Create Gson from GsonBuilder and specify type of list
Gson gson = gsonBuilder.create();
Type type = new TypeToken<ArrayList<Class>>(){}.getType();

// Convert json to list
List<Class> classes = gson.fromJson(json, type);

我希望你能得到解决这个问题的宝贵建议!和往常一样,祝你编码愉快

© www.soinside.com 2019 - 2024. All rights reserved.