📅  最后修改于: 2023-12-03 15:38:30.247000             🧑  作者: Mango
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的基本功能,例如实时数据库和身份验证服务。我们希望这篇文章对您有所帮助!