用Android写一个扫雷的小游戏
时间: 2023-12-29 14:18:13 浏览: 35
好的,下面是一个简单的扫雷游戏的实现步骤:
1. 创建一个 Android 项目,在布局文件中添加一个 GridView 用于显示扫雷游戏的方格。
2. 创建一个二维数组作为扫雷游戏的地图,其中每个元素表示一个方格,用数字表示该方格的状态:-1 表示该方格为地雷,0 表示该方格为未翻开状态,1~8 表示该方格周围的地雷数量。
3. 在 Activity 中实现 GridView 的适配器,将二维数组中的状态显示在 GridView 上。
4. 给 GridView 添加点击事件,当用户点击一个方格时,根据该方格的状态进行相应的操作:如果该方格为地雷,则游戏失败;如果该方格周围没有地雷,则递归地翻开周围的方格;否则显示该方格周围的地雷数量。
5. 在点击事件中判断游戏是否结束,如果未结束则继续游戏,否则弹出游戏结束的提示框。
6. 可以添加计时器和地雷数量的显示,以增加游戏的趣味性。
以下是一个简单的实现代码供参考:
MainActivity.java
```java
public class MainActivity extends AppCompatActivity {
private static final int ROWS = 10; // 行数
private static final int COLS = 10; // 列数
private static final int MINES = 10; // 地雷数量
private int[][] map; // 地图
private boolean[][] opened; // 是否已翻开
private boolean[][] marked; // 是否已标记为地雷
private GridView gridView;
private TextView tvTime;
private TextView tvMines;
private CountDownTimer timer;
private int time; // 游戏时间
private int minesLeft; // 剩余地雷数量
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = findViewById(R.id.grid_view);
tvTime = findViewById(R.id.tv_time);
tvMines = findViewById(R.id.tv_mines);
initMap();
initGridView();
startTimer();
}
private void initMap() {
map = new int[ROWS][COLS];
opened = new boolean[ROWS][COLS];
marked = new boolean[ROWS][COLS];
Random random = new Random();
int mines = 0;
while (mines < MINES) {
int row = random.nextInt(ROWS);
int col = random.nextInt(COLS);
if (map[row][col] != -1) {
map[row][col] = -1;
mines++;
}
}
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (map[i][j] == -1) {
continue;
}
int count = 0;
if (i > 0 && j > 0 && map[i - 1][j - 1] == -1) count++;
if (i > 0 && map[i - 1][j] == -1) count++;
if (i > 0 && j < COLS - 1 && map[i - 1][j + 1] == -1) count++;
if (j > 0 && map[i][j - 1] == -1) count++;
if (j < COLS - 1 && map[i][j + 1] == -1) count++;
if (i < ROWS - 1 && j > 0 && map[i + 1][j - 1] == -1) count++;
if (i < ROWS - 1 && map[i + 1][j] == -1) count++;
if (i < ROWS - 1 && j < COLS - 1 && map[i + 1][j + 1] == -1) count++;
map[i][j] = count;
}
}
minesLeft = MINES;
}
private void initGridView() {
GridViewAdapter adapter = new GridViewAdapter(this, ROWS, COLS);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int row = position / COLS;
int col = position % COLS;
if (opened[row][col] || marked[row][col]) {
return;
}
if (map[row][col] == -1) {
gameOver(false);
return;
}
open(row, col);
checkWin();
}
});
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
int row = position / COLS;
int col = position % COLS;
if (!opened[row][col]) {
marked[row][col] = !marked[row][col];
gridView.invalidateViews();
if (marked[row][col]) {
minesLeft--;
} else {
minesLeft++;
}
tvMines.setText(getString(R.string.mines_left, minesLeft));
}
return true;
}
});
}
private void open(int row, int col) {
if (opened[row][col] || marked[row][col]) {
return;
}
opened[row][col] = true;
gridView.invalidateViews();
if (map[row][col] == 0) {
if (row > 0 && col > 0) open(row - 1, col - 1);
if (row > 0) open(row - 1, col);
if (row > 0 && col < COLS - 1) open(row - 1, col + 1);
if (col > 0) open(row, col - 1);
if (col < COLS - 1) open(row, col + 1);
if (row < ROWS - 1 && col > 0) open(row + 1, col - 1);
if (row < ROWS - 1) open(row + 1, col);
if (row < ROWS - 1 && col < COLS - 1) open(row + 1, col + 1);
}
}
private void checkWin() {
boolean win = true;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (!opened[i][j] && map[i][j] != -1) {
win = false;
break;
}
}
}
if (win) {
gameOver(true);
}
}
private void startTimer() {
timer = new CountDownTimer(Long.MAX_VALUE, 1000) {
@Override
public void onTick(long millisUntilFinished) {
time++;
tvTime.setText(getString(R.string.time, time));
}
@Override
public void onFinish() {
}
};
timer.start();
}
private void stopTimer() {
if (timer != null) {
timer.cancel();
}
}
private void gameOver(boolean win) {
stopTimer();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(win ? R.string.win : R.string.lose);
builder.setMessage(getString(R.string.time_used, time));
builder.setPositiveButton(R.string.restart, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
resetGame();
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setCancelable(false);
builder.show();
}
private void resetGame() {
initMap();
gridView.invalidateViews();
startTimer();
}
private class GridViewAdapter extends BaseAdapter {
private Context context;
private int rows;
private int cols;
public GridViewAdapter(Context context, int rows, int cols) {
this.context = context;
this.rows = rows;
this.cols = cols;
}
@Override
public int getCount() {
return rows * cols;
}
@Override
public Object getItem(int position) {
int row = position / cols;
int col = position % cols;
return map[row][col];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int row = position / cols;
int col = position % cols;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_grid_view, parent, false);
}
TextView textView = convertView.findViewById(R.id.tv);
if (opened[row][col]) {
if (map[row][col] == -1) {
textView.setText(R.string.mine);
textView.setTextColor(Color.RED);
} else if (map[row][col] == 0) {
textView.setText("");
} else {
textView.setText(String.valueOf(map[row][col]));
}
textView.setBackgroundResource(R.drawable.bg_opened);
} else if (marked[row][col]) {
textView.setText(R.string.flag);
textView.setBackgroundResource(R.drawable.bg_closed);
} else {
textView.setText("");
textView.setBackgroundResource(R.drawable.bg_closed);
}
return convertView;
}
}
}
```
activity_main.xml
```xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="10"
android:horizontalSpacing="1dp"
android:verticalSpacing="1dp"
android:stretchMode="columnWidth" />
<LinearLayout
android:id="@+id/layout_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:background="#BBFFFFFF">
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24sp"
android:textColor="#FF0000"
android:padding="8dp"
android:text="00:00" />
<TextView
android:id="@+id/tv_mines"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24sp"
android:textColor="#FF0000"
android:padding="8dp"
android:text="@string/mines_left" />
</LinearLayout>
</RelativeLayout>
```
item_grid_view.xml
```xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="24sp"
android:textColor="#000000"
android:padding="8dp" />
```
strings.xml
```xml
<resources>
<string name="app_name">Minesweeper</string>
<string name="time">Time: %d</string>
<string name="mines_left">Mines left: %d</string>
<string name="win">You win!</string>
<string name="lose">You lose!</string>
<string name="restart">Restart</string>
<string name="mine">X</string>
<string name="flag">F</string>
<string name="time_used">Time used: %d seconds</string>
</resources>
```