火影 发表于 2025-1-20 03:34:04

Android Studio制作简单拼图小游戏

制作的这个小游戏我称之为速度真夫君
这是一个九宫格3x3的还原图片的小游戏,当你运行程序时,计时器显示为0,当你点击第一个碎片开始计时,并且记载你的点击次数,相邻两个碎片可以互换,凌驾120秒游戏失败
https://i-blog.csdnimg.cn/direct/4ee11ce7640b465782ab8524b336b042.png
1.class PuzzleView

代码如下:
package com.example.gameapplication.Activity;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PuzzleView extends View {
    private List<PuzzlePiece> pieces; // 存储拼图块的列表
    private int numColumns = 3; // 拼图的列数(3x3)
    private int pieceSize; // 原始拼图块大小
    private int scaledPieceSize; // 缩放后的拼图块大小
    private Paint paint; // 用于绘制拼图块的画笔
    private Paint textPaint; // 用于绘制文本的画笔
    private Integer firstSelectedIndex = null; // 记录第一个选中的拼图块索引
    private float scaleFactor = 1.5f; // 拼图块的缩放因子
    private int swapCount = 0; // 记录交换次数的计数器
    private long startTime ; // 计时开始时间,初始化为0
    private Handler handler = new Handler(); // 用于更新计时器的处理器
    private boolean isRunning = false; // 计时器是否在运行

    // 定义一个Runnable来定期更新计时器
    private Runnable timerRunnable = new Runnable() {
      @Override
      public void run() {
            if (isRunning) {
                long elapsedTime = (System.currentTimeMillis() - startTime) / 1000; // 计算经过的时间(秒)
                if (elapsedTime >= 120) {
                  endGame("时间到,游戏结束!"); // 超过120秒,结束游戏
                  return;
                }
                invalidate(); // 刷新视图以更新计时器
                handler.postDelayed(this, 1000); // 每秒更新一次
            }
      }
    };

    public PuzzleView(Context context, AttributeSet attrs) {
      super(context, attrs);
      paint = new Paint(); // 初始化绘图画笔
      textPaint = new Paint(); // 初始化文本画笔
      textPaint.setColor(0xFF000000); // 设置文本颜色为黑色
      textPaint.setTextSize(50); // 设置文本大小
      pieces = new ArrayList<>(); // 初始化拼图块列表
    }

    // 初始化拼图,分割图像为拼图块
    public void initializePuzzle(Bitmap bitmap) {
      pieceSize = bitmap.getWidth() / numColumns; // 计算原始拼图块大小
      scaledPieceSize = (int) (pieceSize * scaleFactor); // 计算缩放后的拼图块大小

      // 将图像分割为拼图块
      for (int i = 0; i < numColumns; i++) {
            for (int j = 0; j < numColumns; j++) {
                // 创建拼图块的Bitmap
                Bitmap pieceBitmap = Bitmap.createBitmap(bitmap, j * pieceSize, i * pieceSize, pieceSize, pieceSize);
                // 缩放拼图块
                pieceBitmap = Bitmap.createScaledBitmap(pieceBitmap, scaledPieceSize, scaledPieceSize, true);
                pieces.add(new PuzzlePiece(pieceBitmap, i * numColumns + j)); // 添加拼图块到列表
            }
      }
      shufflePuzzle(); // 打乱拼图
      invalidate(); // 刷新视图
    }

    // 打乱拼图块的顺序
    private void shufflePuzzle() {
      Collections.shuffle(pieces); // 随机打乱拼图块
    }

    // 启动计时器
    private void startTimer() {
      startTime = System.currentTimeMillis(); // 记录开始时间
      isRunning = true; // 设置计时器为运行状态
      handler.postDelayed(timerRunnable, 1000); // 每秒启动一次计时器
    }

    // 结束游戏并显示提示
    private void endGame(String message) {
      isRunning = false; // 停止计时器
      handler.removeCallbacks(timerRunnable); // 移除计时器回调

      // 计算总用时(秒),确保在游戏开始后才计算
      long totalTime = (isRunning ? (System.currentTimeMillis() - startTime) / 1000 : 0);
      Toast.makeText(getContext(), message + " 用时: " + totalTime + "秒", Toast.LENGTH_SHORT).show(); // 显示结束提示
    }

    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);

      // 计算拼图整体绘制的起始位置,使其居中
      int totalWidth = scaledPieceSize * numColumns;
      int totalHeight = scaledPieceSize * numColumns;
      int startX = (getWidth() - totalWidth) / 2; // 水平居中
      int startY = (getHeight() - totalHeight) / 2; // 垂直居中

      // 绘制拼图块
      for (int i = 0; i < pieces.size(); i++) {
            PuzzlePiece piece = pieces.get(i);
            int x = startX + (i % numColumns) * scaledPieceSize; // 计算水平坐标
            int y = startY + (i / numColumns) * scaledPieceSize; // 计算垂直坐标
            canvas.drawBitmap(piece.getBitmap(), x, y, paint); // 绘制拼图块
      }

      // 绘制交换次数文本
      canvas.drawText("交换次数: " + swapCount, startX, startY - 20, textPaint);

      // 计算经过的时间(秒)
      long elapsedTime = (isRunning ? (System.currentTimeMillis() - startTime) / 1000 : 0);

      // 将时间格式化为“mm:ss”
      String timeFormatted = String.format("%02d:%02d", elapsedTime / 60, elapsedTime % 60);
      canvas.drawText("时间: " + timeFormatted, startX, startY - 70, textPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
      if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // 计算点击的列和行
            int startX = (getWidth() - (scaledPieceSize * numColumns)) / 2; // 计算拼图的起始X坐标
            int startY = (getHeight() - (scaledPieceSize * numColumns)) / 2; // 计算拼图的起始Y坐标
            int x = (int) (event.getX() - startX) / scaledPieceSize; // 计算点击的列
            int y = (int) (event.getY() - startY) / scaledPieceSize; // 计算点击的行
            int clickedIndex = y * numColumns + x; // 计算点击的拼图块索引

            // 处理选中逻辑
            if (clickedIndex >= 0 && clickedIndex < pieces.size()) {
                if (!isRunning) {
                  startTimer(); // 如果计时器未运行,则开始计时
                }
                handleSelection(clickedIndex); // 处理选中拼图块
            }
            invalidate(); // 刷新视图
      }
      return true; // 事件处理完成
    }

    private void handleSelection(int clickedIndex) {
      if (firstSelectedIndex == null) {
            // 第一次点击,记录索引
            firstSelectedIndex = clickedIndex;
      } else {
            // 第二次点击,检查是否可以交换
            if (isAdjacent(firstSelectedIndex, clickedIndex)) {
                swapPieces(firstSelectedIndex, clickedIndex); // 交换拼图块
                swapCount++; // 增加交换次数计数
            }
            firstSelectedIndex = null; // 重置选中状态
      }
    }

    // 交换拼图块
    private void swapPieces(int index1, int index2) {
      Collections.swap(pieces, index1, index2); // 交换拼图块
      checkCompletion(); // 检查拼图是否完成
    }

    // 检查两个拼图块是否相邻
    private boolean isAdjacent(int index1, int index2) {
      int row1 = index1 / numColumns;
      int col1 = index1 % numColumns;
      int row2 = index2 / numColumns;
      int col2 = index2 % numColumns;

      // 检查是否相邻(上下或左右)
      return (Math.abs(row1 - row2) + Math.abs(col1 - col2) == 1);
    }

    // 检查拼图是否完成
    private void checkCompletion() {
      boolean completed = true;
      for (int i = 0; i < pieces.size(); i++) {
            if (pieces.get(i).getPosition() != i) {
                completed = false; // 拼图尚未完成
                break;
            }
      }
      if (completed) {
            long totalTime = (System.currentTimeMillis() - startTime) / 1000; // 计算总用时(秒)
            endGame("拼图完成! 总交换次数: " + swapCount + ", 用时: " + totalTime + "秒"); // 游戏完成提示
      }
    }
} 2.class PuzzlePiece

代码如下:
package com.example.gameapplication.Activity;

import android.graphics.Bitmap;

public class PuzzlePiece {
    private Bitmap bitmap;
    private int position; // 在拼图中的位置

    public PuzzlePiece(Bitmap bitmap, int position) {
      this.bitmap = bitmap;
      this.position = position;
    }

    public Bitmap getBitmap() {
      return bitmap;
    }

    public int getPosition() {
      return position;
    }

    public void setPosition(int position) {
      this.position = position;
    }
} 3.class MainActivity

package com.example.gameapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;

import com.example.gameapplication.Activity.PuzzleView;

public class MainActivity extends AppCompatActivity {
    private PuzzleView puzzleView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      puzzleView = new PuzzleView(this, null);
      setContentView(puzzleView);

      Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.puzzle); // 替换为你的图片
      puzzleView.initializePuzzle(bitmap);
    }
} 4.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- PuzzleView will be set programmatically in MainActivity -->

</FrameLayout>
最后自己找一张喜欢的图片放进去就可以了
https://i-blog.csdnimg.cn/direct/c5d9756441534b0bbecd4a038b8fd614.png
 总结,这个游戏没什么难度 但是重要在于图片的起始位置,判断点击的是哪个碎片,两个碎片是否相邻,时间的盘算。结束!!!!!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Android Studio制作简单拼图小游戏