PuzzleManager拼图管理,生成拼图,打乱顺序,点击拼图块移动,检测是否拼成
拼成的效果图
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class PuzzleManager : MonoBehaviour
{
public GameObject piecePrefab;//拼图块预制体
public int rows = 3;//行数
public int cols = 3;//列数
private GameObject[,] pieces;//存储拼图块
private Vector2[,] piecePos;//存储拼图块正确位置
private Vector2 emptyPosition;//空白位置
private int emptyR, emptyC;
private int WH = 226;//拼图块宽高
private bool m_IsMove = false;
[SerializeField]
private Sprite[] sprites;//拼图块图片数组
private void Start()
{
pieces = new GameObject[rows, cols];
piecePos = new Vector2[rows, cols];
emptyR = rows - 1;
emptyC = cols - 1;
emptyPosition = new Vector2(emptyR * WH, -emptyC * WH);//初始空白位置
piecePos[emptyR, emptyC] = emptyPosition;
m_IsMove = true;
InitializePuzzle();
ShufflePuzzle();
}
/// <summary>
/// 初始化拼图块
/// </summary>
private void InitializePuzzle()
{
if (transform.childCount > 0)
{
for (int i = 0; i < transform.childCount; i++)
{
Destroy(transform.GetChild(i).gameObject);
}
}
int a = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (i == rows - 1 && j == cols - 1) continue; // 留空位置
GameObject piece = Instantiate(piecePrefab);
Image image = piece.GetComponent<Image>();
image.sprite = sprites[a];
a++;
Text text = piece.transform.Find("Text (Legacy)").GetComponent<Text>();
text.SetText(string.Format("{0}", a));
piece.transform.SetParent(transform);
piece.transform.localScale = Vector3.one;
int x = j * WH;
int y = -i * WH;
Vector2 pos = new Vector2(x, y);
piece.transform.localPosition = pos;
piece.GetComponent<PuzzlePiece>().SetPosition(i, j, x, y);
pieces[i, j] = piece;
piecePos[i, j] = pos;
}
}
}
/// <summary>
/// 打乱逻辑顺序
/// </summary>
void ShufflePuzzle()
{
//int shuffleCount = 100; // 打乱次数
int shuffleCount = 10; // 打乱次数
for (int i = 0; i < shuffleCount; i++)
{
List<PuzzlePiece> possibleMoves = GetPossibleMoves();
int randomIndex = UnityEngine.Random.Range(0, possibleMoves.Count);
PuzzlePiece movePuzzlePiece = possibleMoves[randomIndex];
// 移动拼图块
MovePiece(movePuzzlePiece.gameObject, movePuzzlePiece.GetPosition(), movePuzzlePiece.row, movePuzzlePiece.col);
}
}
/// <summary>
/// 判断空白块周围是否可以移动
/// </summary>
/// <returns></returns>
private List<PuzzlePiece> GetPossibleMoves()
{
List<PuzzlePiece> possibleMoves = new List<PuzzlePiece>();
// 检查上下左右的拼图块是否可以移动
if (emptyC > 0)// 上
{
PuzzlePiece puzzlePiece = pieces[emptyR, emptyC - 1].GetComponent<PuzzlePiece>();
possibleMoves.Add(puzzlePiece);
}
if (emptyC < rows - 1)// 下
{
PuzzlePiece puzzlePiece = pieces[emptyR, emptyC + 1].GetComponent<PuzzlePiece>();
possibleMoves.Add(puzzlePiece);
}
if (emptyR > 0)// 左
{
PuzzlePiece puzzlePiece = pieces[emptyR - 1, emptyC].GetComponent<PuzzlePiece>();
possibleMoves.Add(puzzlePiece);
}
if (emptyR < cols - 1)// 右
{
PuzzlePiece puzzlePiece = pieces[emptyR + 1, emptyC].GetComponent<PuzzlePiece>();
possibleMoves.Add(puzzlePiece);
}
return possibleMoves;
}
void Update()
{
if (m_IsMove)
{
if (Input.GetMouseButtonDown(0))
{
Vector2 mousePos = UICameraCtrl.Instance.GetComponent<Camera>().ScreenToWorldPoint(Input.mousePosition);
HandleClick(mousePos);
if (IsPuzzleComplete())
{
AppDebug.Log("拼图完成");
m_IsMove = false;
if (OnResult != null) OnResult(true);
}
}
}
}
void HandleClick(Vector2 position)
{
foreach (var piece in pieces)
{
if (piece != null && piece.GetComponent<Collider2D>().OverlapPoint(position))
{
PuzzlePiece puzzlePiece = piece.GetComponent<PuzzlePiece>();
Vector2 piecePos = puzzlePiece.GetPosition();
int r = puzzlePiece.row;
int c = puzzlePiece.col;
if (IsAdjacent(piecePos, emptyPosition))
{
MovePiece(piece, piecePos, r, c);
break;
}
}
}
}
/// <summary>
/// 判断是否可以移动
/// </summary>
/// <param name="piecePos"></param>
/// <param name="emptyPos"></param>
/// <returns></returns>
private bool IsAdjacent(Vector2 piecePos, Vector2 emptyPos)
{
return Mathf.Abs(piecePos.x - emptyPos.x) + Mathf.Abs(piecePos.y - emptyPos.y) == WH;
}
/// <summary>
/// 移动交换位置
/// </summary>
/// <param name="piece"></param>
/// <param name="piecePos"></param>
/// <param name="pieceR"></param>
/// <param name="pieceC"></param>
private void MovePiece(GameObject piece, Vector2 piecePos, int pieceR, int pieceC)
{
pieces[emptyR, emptyC] = piece;
piece.GetComponent<PuzzlePiece>().SetPosition(emptyR, emptyC, (int)emptyPosition.x, (int)emptyPosition.y);
piece.transform.localScale = Vector3.one;
piece.transform.localPosition = new Vector2(emptyPosition.x, emptyPosition.y);
emptyPosition = piecePos;
emptyR = pieceR;
emptyC = pieceC;
}
/// <summary>
/// 判断是否完成
/// </summary>
/// <returns></returns>
private bool IsPuzzleComplete()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (i == rows - 1 && j == cols - 1) continue; // 留空位置
// 检查每个拼图块是否在正确的位置
if (pieces[i, j] != null && piecePos[i, j] != null)
{
if (pieces[i, j].GetComponent<PuzzlePiece>().GetPosition() != piecePos[i, j])
{
return false;
}
}
}
}
return true;
}
}
拼图块脚本PuzzlePiece主要是在二维数组中的位置和在UI上的坐标设置
using UnityEngine;
public class PuzzlePiece : MonoBehaviour
{
public int row, col;
private int m_X, m_Y;
public void SetPosition(int r, int c, int x, int y)
{
row = r;
col = c;
m_X = x;
m_Y = y;
}
public Vector2 GetPosition()
{
return new Vector2(m_X, m_Y);
}
}