首页 > 解决方案 > 分离游戏逻辑和UI

问题描述

这是一个只有三个视图的简单游戏:一个 TextView 和两个按钮(红色和绿色按钮)。

玩家应该按下与 TextView 背景颜色相同颜色的按钮。如果 TextView 背景颜色是红色,那么玩家应该按下红色按钮。

假设有三种不同的播放模式: 常规:您可以玩一整天。时间限制:您只有 3 秒的时间来回答。计时赛:在 30 秒内尽可能多地回答正确。

所有模式共享相同的布局 (xml)。

方法 newGame() 和 newRound() 的行为会根据玩家选择的模式而有所不同。

“常规”可以有 2 种状态:正在播放 = 呈现颜色并且程序正在等待用户输入给 - 错误 - 答案 = 玩家按下了错误的按钮。现在该按钮已禁用。玩家必须按下正确的按钮才能继续(新回合)。

“Timelimit”总是从 3 倒数到 0。当用户按下按钮时,计时器总是重新启动,如果计时器达到 0,则触发 newRound。

“计时赛”将从 30 倒计时到 0,但在其他方面将像“常规”游戏一样工作。

所有三种模式共享一些公共变量,例如:boolean isRed;//知道TextView是否是红色的。

这将如何根据活动和课程进行组织/结构化?

下面是一些实际的代码:

活动主.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<Button
    android:id="@+id/btn_red"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Normal game"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<Button
    android:id="@+id/btn_timer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Timer game"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_red"
    app:layout_constraintVertical_bias="0.041" />

</android.support.constraint.ConstraintLayout>

活动播放.xml:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    tools:context=".PlayActivity">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp">

        <TextView
            android:id="@+id/txt_colorbox"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="40dp"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp">

        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:orientation="horizontal"
            android:paddingLeft="16dp"
            android:paddingRight="16dp">

            <Button
                android:id="@+id/btn_red"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:text="" />

            <Button
                android:id="@+id/btn_green"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:text="" />

        </LinearLayout>

        <LinearLayout 
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="4"
            android:orientation="vertical"
            android:paddingLeft="16dp"
            android:paddingRight="16dp">

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

MainActivity.java:

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements 
View.OnClickListener {

Button btn_normal;
Button btn_timer;

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

    btn_normal = findViewById(R.id.btn_red);
    btn_timer = findViewById(R.id.btn_timer);

    btn_normal.setOnClickListener(this);
    btn_timer.setOnClickListener(this);

}

@Override
public void onClick(View v) {
    Intent intent = new Intent(this, PlayActivity.class);
    if (v == btn_normal) {
        intent.putExtra("GAME_MODE", "regular");
    } else if (v == btn_timer) {
        intent.putExtra("GAME_MODE", "timelimit");
    }
    startActivity(intent);
}
}

PlayActivity.java:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class PlayActivity extends AppCompatActivity implements View.OnClickListener {

    static Button btn_red;
    static Button btn_green;
    static TextView txt_colorbox;
    Game game;

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

        txt_colorbox = findViewById(R.id.txt_colorbox);

        btn_red = findViewById(R.id.btn_red);
        btn_green = findViewById(R.id.btn_green);

        btn_red.setOnClickListener(this);
        btn_green.setOnClickListener(this);

        String gameMode = getIntent().getStringExtra("GAME_MODE");

        if (gameMode.equals("regular")) {
            game = new RegularGame();
        } else if (gameMode.equals("timelimit")) {
            game = new TimelimitGame();
        }
        else if (gameMode.equals("timetrial")) {
            game = new TimetrialGame();
        }

        game.newGame();
        game.newRound();

    }

    @Override
    public void onClick(View v) {
        if (v == btn_red) {
            System.out.println("pressed Red");
        } else if (v == btn_green) {
            System.out.println("pressed Green");
        }
    }
}

游戏.java:

public abstract class Game {

    boolean isRed;

    public void newGame() {
    }

    public void newRound() {
    }

}

常规游戏.java

public class RegularGame extends Game {

    @Override
    public void newGame() {
        System.out.println("New game: regular mode");
    }

    @Override
    public void newRound() {
        System.out.println("New Round");
    }

}

TimelimitGame.java:

public class TimelimitGame extends Game {

    @Override
    public void newGame() {
        System.out.println("New game: timelimit mode");
    }

    @Override
    public void newRound() {
        System.out.println("New Round");
    }

}

TimetrialGame.java:

public class TimetrialGame extends Game {

    @Override
    public void newGame() {
        System.out.println("New game: timer mode");
    }

    @Override
    public void newRound() {
        System.out.println("New Round");
    }

}

我是否应该在 Game() 构造函数中提供上下文/活动。这样我就可以以这种方式访问​​ TextView 和 Buttons 还是应该 updateUI 驻留在 PlayActivity 中但从 Game 类中收集信息?

标签: javaandroid

解决方案


推荐阅读