在本文中,我们将在Android中使用Java和XML构建一个Tic Tac Toe游戏项目。井字游戏是基于两个人的游戏。每个玩家在X和O之间进行选择。玩家同时玩一局。在移动中,玩家可以从3×3网格中选择任意位置。这里的目标是在水平,垂直或对角线方向上获得三个连续的X或O。此应用程序中只有一个活动。该活动将显示一个3×3的网格。游戏状态将显示在底部。下面给出了一个示例GIF,以使我们对本文中要做的事情有一个了解。
分步实施
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Java作为编程语言。
第2步:首先进入编码部分,您必须做一些准备工作
添加图像:下面列出了所有图像。将它们保存在资源中的可绘制文件夹中。转到应用>“ res”>“ drawable”,然后粘贴以下文件:
- 网格
- Ø
- X
在themes.xml文件中将样式更改为NoActionBar:
步骤3:使用activity_main.xml文件
XML代码用于构建活动的结构及其样式部分。它包含一个TextView 在活动的最顶部以显示标题。然后,它包含网格的ImageView,并且在每个框中都有一个ImageView。在活动的底部,有一个TextView来显示游戏的状态。以下是activity_main.xml文件的代码。
XML
Java
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
boolean gameActive = true;
// Player representation
// 0 - X
// 1 - O
int activePlayer = 0;
int[] gameState = {2, 2, 2, 2, 2, 2, 2, 2, 2};
// State meanings:
// 0 - X
// 1 - O
// 2 - Null
// put all win positions in a 2D array
int[][] winPositions = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{0, 4, 8}, {2, 4, 6}};
public static int counter = 0;
// this function will be called every time a
// players tap in an empty box of the grid
public void playerTap(View view) {
ImageView img = (ImageView) view;
int tappedImage = Integer.parseInt(img.getTag().toString());
// game reset function will be called
// if someone wins or the boxes are full
if (!gameActive) {
gameReset(view);
}
// if the tapped image is empty
if (gameState[tappedImage] == 2) {
// increase the counter
// after every tap
counter++;
// check if its the last box
if (counter == 9) {
// reset the game
gameActive = false;
}
// mark this position
gameState[tappedImage] = activePlayer;
// this will give a motion
// effect to the image
img.setTranslationY(-1000f);
// change the active player
// from 0 to 1 or 1 to 0
if (activePlayer == 0) {
// set the image of x
img.setImageResource(R.drawable.x);
activePlayer = 1;
TextView status = findViewById(R.id.status);
// change the status
status.setText("O's Turn - Tap to play");
} else {
// set the image of o
img.setImageResource(R.drawable.o);
activePlayer = 0;
TextView status = findViewById(R.id.status);
// change the status
status.setText("X's Turn - Tap to play");
}
img.animate().translationYBy(1000f).setDuration(300);
}
int flag = 0;
// Check if any player has won
for (int[] winPosition : winPositions) {
if (gameState[winPosition[0]] == gameState[winPosition[1]] &&
gameState[winPosition[1]] == gameState[winPosition[2]] &&
gameState[winPosition[0]] != 2) {
flag = 1;
// Somebody has won! - Find out who!
String winnerStr;
// game reset function be called
gameActive = false;
if (gameState[winPosition[0]] == 0) {
winnerStr = "X has won";
} else {
winnerStr = "O has won";
}
// Update the status bar for winner announcement
TextView status = findViewById(R.id.status);
status.setText(winnerStr);
}
}
// set the status if the match draw
if (counter == 9 && flag == 0) {
TextView status = findViewById(R.id.status);
status.setText("Match Draw");
}
}
// reset the game
public void gameReset(View view) {
gameActive = true;
activePlayer = 0;
for (int i = 0; i < gameState.length; i++) {
gameState[i] = 2;
}
// remove all the images from the boxes inside the grid
((ImageView) findViewById(R.id.imageView0)).setImageResource(0);
((ImageView) findViewById(R.id.imageView1)).setImageResource(0);
((ImageView) findViewById(R.id.imageView2)).setImageResource(0);
((ImageView) findViewById(R.id.imageView3)).setImageResource(0);
((ImageView) findViewById(R.id.imageView4)).setImageResource(0);
((ImageView) findViewById(R.id.imageView5)).setImageResource(0);
((ImageView) findViewById(R.id.imageView6)).setImageResource(0);
((ImageView) findViewById(R.id.imageView7)).setImageResource(0);
((ImageView) findViewById(R.id.imageView8)).setImageResource(0);
TextView status = findViewById(R.id.status);
status.setText("X's Turn - Tap to play");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
步骤4:使用MainActivity。 Java文件
我们将创建一个二维数组,该数组将存储所有获胜位置。我们将创建一个函数,该函数将在单击网格内的框时运行。在此函数内部,我们将首先检查选中的框是否为空。之后,如果最后一个动作是O,我们将设置X的图像;如果最后一个动作是X,我们将设置O的图像。然后,我们将检查该移动是否已到达移动位置,然后重置游戏。下面是MainActivity的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。
Java
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
boolean gameActive = true;
// Player representation
// 0 - X
// 1 - O
int activePlayer = 0;
int[] gameState = {2, 2, 2, 2, 2, 2, 2, 2, 2};
// State meanings:
// 0 - X
// 1 - O
// 2 - Null
// put all win positions in a 2D array
int[][] winPositions = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{0, 4, 8}, {2, 4, 6}};
public static int counter = 0;
// this function will be called every time a
// players tap in an empty box of the grid
public void playerTap(View view) {
ImageView img = (ImageView) view;
int tappedImage = Integer.parseInt(img.getTag().toString());
// game reset function will be called
// if someone wins or the boxes are full
if (!gameActive) {
gameReset(view);
}
// if the tapped image is empty
if (gameState[tappedImage] == 2) {
// increase the counter
// after every tap
counter++;
// check if its the last box
if (counter == 9) {
// reset the game
gameActive = false;
}
// mark this position
gameState[tappedImage] = activePlayer;
// this will give a motion
// effect to the image
img.setTranslationY(-1000f);
// change the active player
// from 0 to 1 or 1 to 0
if (activePlayer == 0) {
// set the image of x
img.setImageResource(R.drawable.x);
activePlayer = 1;
TextView status = findViewById(R.id.status);
// change the status
status.setText("O's Turn - Tap to play");
} else {
// set the image of o
img.setImageResource(R.drawable.o);
activePlayer = 0;
TextView status = findViewById(R.id.status);
// change the status
status.setText("X's Turn - Tap to play");
}
img.animate().translationYBy(1000f).setDuration(300);
}
int flag = 0;
// Check if any player has won
for (int[] winPosition : winPositions) {
if (gameState[winPosition[0]] == gameState[winPosition[1]] &&
gameState[winPosition[1]] == gameState[winPosition[2]] &&
gameState[winPosition[0]] != 2) {
flag = 1;
// Somebody has won! - Find out who!
String winnerStr;
// game reset function be called
gameActive = false;
if (gameState[winPosition[0]] == 0) {
winnerStr = "X has won";
} else {
winnerStr = "O has won";
}
// Update the status bar for winner announcement
TextView status = findViewById(R.id.status);
status.setText(winnerStr);
}
}
// set the status if the match draw
if (counter == 9 && flag == 0) {
TextView status = findViewById(R.id.status);
status.setText("Match Draw");
}
}
// reset the game
public void gameReset(View view) {
gameActive = true;
activePlayer = 0;
for (int i = 0; i < gameState.length; i++) {
gameState[i] = 2;
}
// remove all the images from the boxes inside the grid
((ImageView) findViewById(R.id.imageView0)).setImageResource(0);
((ImageView) findViewById(R.id.imageView1)).setImageResource(0);
((ImageView) findViewById(R.id.imageView2)).setImageResource(0);
((ImageView) findViewById(R.id.imageView3)).setImageResource(0);
((ImageView) findViewById(R.id.imageView4)).setImageResource(0);
((ImageView) findViewById(R.id.imageView5)).setImageResource(0);
((ImageView) findViewById(R.id.imageView6)).setImageResource(0);
((ImageView) findViewById(R.id.imageView7)).setImageResource(0);
((ImageView) findViewById(R.id.imageView8)).setImageResource(0);
TextView status = findViewById(R.id.status);
status.setText("X's Turn - Tap to play");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}