📜  如何在Android中以离线和在线模式构建Tic Tac Toe游戏?(1)

📅  最后修改于: 2023-12-03 15:38:30.247000             🧑  作者: Mango

如何在Android中以离线和在线模式构建Tic Tac Toe游戏?

Tic Tac Toe(又称井字游戏)是一种简单的纸笔游戏,玩家在一个3×3的格子里轮流画字,先在横、竖、斜连成一条直线的胜利。

在本文中,我们将介绍如何在Android中以离线和在线模式构建Tic Tac Toe游戏。

离线模式

在离线模式中,我们将实现一个简单的单人游戏,玩家将与计算机对战。我们将使用Java编写Android应用程序,并将应用程序的UI构建为一个GridView,其中的单元格将充当游戏的位置。

// Game activity
public class GameActivity extends AppCompatActivity {

    // Constants
    private static final int BOARD_SIZE = 3;

    // Variables
    private Button[][] mButtons = new Button[BOARD_SIZE][BOARD_SIZE];
    private int[][] mBoard = new int[BOARD_SIZE][BOARD_SIZE];
    private int mPlayer = 1;
    private boolean mComputer = false;

    // onCreate method
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

        // Initialize buttons and board
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                mButtons[i][j] = findViewById(getResources().getIdentifier("button_" + i + j, "id", getPackageName()));
                mBoard[i][j] = 0;
            }
        }

        // Set button listeners
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                final int x = i;
                final int y = j;
                mButtons[i][j].setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mBoard[x][y] == 0) {
                            mBoard[x][y] = mPlayer;

                            if (checkWin(mPlayer)) {
                                Toast.makeText(getBaseContext(), "Player " + mPlayer + " wins!", Toast.LENGTH_LONG).show();
                                finish();
                            }

                            mPlayer = (mPlayer == 1) ? 2 : 1;

                            if (mComputer) {
                                playComputer();
                            }
                        }
                    }
                });
            }
        }

        // Set play mode
        Intent intent = getIntent();
        mComputer = intent.getBooleanExtra("computer", false);
        if (mComputer) {
            playComputer();
        }
    }

    // Check win method
    private boolean checkWin(int player) {
        // Check rows
        for (int i = 0; i < BOARD_SIZE; i++) {
            if (mBoard[i][0] == player && mBoard[i][1] == player && mBoard[i][2] == player) {
                return true;
            }
        }

        // Check columns
        for (int i = 0; i < BOARD_SIZE; i++) {
            if (mBoard[0][i] == player && mBoard[1][i] == player && mBoard[2][i] == player) {
                return true;
            }
        }

        // Check diagonals
        if (mBoard[0][0] == player && mBoard[1][1] == player && mBoard[2][2] == player) {
            return true;
        }

        if (mBoard[2][0] == player && mBoard[1][1] == player && mBoard[0][2] == player) {
            return true;
        }

        return false;
    }

    // Play computer method
    private void playComputer() {
        boolean played = false;

        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (mBoard[i][j] == 0) {
                    mBoard[i][j] = mPlayer;

                    if (checkWin(mPlayer)) {
                        Toast.makeText(getBaseContext(), "Player " + mPlayer + " wins!", Toast.LENGTH_LONG).show();
                        finish();
                    }

                    mPlayer = (mPlayer == 1) ? 2 : 1;
                    played = true;
                    break;
                }
            }

            if (played) {
                break;
            }
        }
    }
}

在上面的代码中,我们首先声明了一些常量和变量。我们将按如下方式使用它们:

  • BOARD_SIZE是游戏板的大小。我们设置它为3,因为我们的游戏将在3×3的格子上进行。
  • mButtons是一个Button数组,用于保存UI中的按钮。我们使用findViewById方法获取每个按钮,并将其存储在数组中。
  • mBoard是一个整数数组,用于保存游戏板的状态。我们将在游戏过程中更新它,并在每个更新后检查是否有胜利者。
  • mPlayer是一个整数变量,用于表示当前玩家(1表示玩家1,2表示玩家2)。
  • mComputer是一个布尔变量,用于表示当前游戏是否是单人游戏。

onCreate方法中,我们首先通过调用findViewById方法获取UI中按钮的引用。我们使用getResources方法和getIdentifier方法来查找每个按钮的ID。我们还初始化了mBoard数组,将每个位置的初始值设置为0。

然后,我们将设置每个按钮的监听器。在单击按钮时,我们将检查该位置是否已选中。如果该位置尚未被选中,则将其设置为当前玩家,并检查是否有胜利者。如果有,我们将显示胜利消息,并结束游戏。然后,我们将更新当前玩家,以使其成为下一个玩家。

最后,我们检查游戏是否是单人游戏。如果是,我们将调用playComputer方法,以使计算机开始下棋。

checkWin方法中,我们将检查游戏板的状态,查看当前玩家是否已成为胜利者。我们首先检查每一行和每一列,然后检查对角线。如果有任何直线都被一个玩家填满,我们将返回true,表示该玩家已获胜。

playComputer方法中,我们将让计算机下棋。我们遍历数组中的每个位置,找到第一个未选的位置,并将其设置为当前玩家。然后,我们检查是否有胜利者,并更新当前玩家。如果玩家已完成下棋,我们将停止遍历。

在线模式

在在线模式中,玩家将可以与其他人在线对战。我们将使用Firebase数据库来实现在线功能。我们将使用Firebase的Realtime Database来存储游戏状态,并使用Firebase的Authentication来验证用户。

首先,我们需要设置Firebase项目。我们需要在Firebase控制台中创建一个新项目,并添加Firebase实时数据库和Firebase身份验证服务。

我们还需要在Android应用程序中添加Firebase SDK。在build.gradle文件中,我们将添加以下依赖项:

implementation 'com.google.firebase:firebase-database'
implementation 'com.google.firebase:firebase-auth'

然后,我们将实现一个双人游戏。我们将使用以下类来表示游戏状态:

// Game class
public class Game {
    public int[][] board;
    public int player;

    public Game() {}

    public Game(int[][] board, int player) {
        this.board = board;
        this.player = player;
    }
}

我们还需要用一个唯一的游戏ID存储游戏状态。我们将使用以下代码生成一个随机的游戏ID:

// Generate game id
String gameId = FirebaseDatabase.getInstance().getReference().child("games").push().getKey();

现在,我们将实现一个游戏大厅列表,列出所有可用的游戏。我们将使用以下类来表示游戏状态的摘要:

// GameSummary class
public class GameSummary {
    public String id;
    public int playerCount;

    public GameSummary() {}

    public GameSummary(String id, int playerCount) {
        this.id = id;
        this.playerCount = playerCount;
    }
}

我们将使用Firebase实时数据库来存储游戏状态的摘要。我们将使用以下代码将摘要添加到数据库中:

// Add game summary
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("games").child(gameId).child("summary");
ref.setValue(new GameSummary(gameId, 1));

我们还需要设置一个监听器,以检测新游戏的加入:

// Listen for new games
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("games");
ref.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
        GameSummary summary = snapshot.child("summary").getValue(GameSummary.class);
        if (summary != null && summary.playerCount == 1) {
            // Add game to list
        }
    }

    @Override
    public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {}

    @Override
    public void onChildRemoved(@NonNull DataSnapshot snapshot) {}

    @Override
    public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {}

    @Override
    public void onCancelled(@NonNull DatabaseError error) {}
});

在上面的代码中,我们使用addChildEventListener方法添加一个名为games的根节点的监听器。在每次添加新游戏时,我们将读取游戏状态的摘要,并检查玩家数量。如果玩家数量为1,则表示该游戏已准备好进行,我们将添加该游戏到列表中。

我们也需要将玩家添加到游戏中。我们将使用以下代码将玩家添加到游戏中:

// Add player to game
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("games").child(gameId).child("players").child("2");
ref.setValue(FirebaseAuth.getInstance().getCurrentUser().getUid());

在上面的代码中,我们使用setValue方法将当前用户的UID添加到游戏的players/2节点中。我们使用FirebaseAuth类来读取当前用户的UID。

现在,我们需要设置一个监听器,以检测游戏状态的更改。我们将使用以下代码来监视游戏状态:

// Listen for game changes
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("games").child(gameId);
ref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        Game game = snapshot.getValue(Game.class);
        if (game != null) {
            // Update UI
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {}
});

在上面的代码中,我们使用addValueEventListener方法添加一个节点的监听器。在每次节点更改时,我们将读取游戏状态,并更新UI。

最后,我们需要更新游戏状态。我们将使用以下代码来更新游戏状态:

// Update game state
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("games").child(gameId);
ref.setValue(new Game(mBoard, mPlayer));

在上面的代码中,我们使用setValue方法将新的Game对象写入数据库中。

结论

在本文中,我们介绍了如何在Android中以离线和在线模式构建Tic Tac Toe游戏。在离线模式中,玩家将与计算机对战,而在在线模式中,玩家将可以与其他人在线对战。我们还介绍了一些Firebase的基本功能,例如实时数据库和身份验证服务。我们希望这篇文章对您有所帮助!