# Unity 芯片拼图算法

1.他所选中的那个碎片到底能不能在点击的棋盘格位置放下呢？例如，现在只剩两格空格点了，而选择的确是一个三格的碎片，则无论如何点击也是不可能放下此碎片的，即使可能剩下五格，也不一定能保证放下特殊形状的三格碎片。

2.如果能放下碎片，那应该以碎片的哪个格子为基准点进行放置呢？观察下面几张图：

``` 1 using System.Collections.Generic;
2 using UnityEngine;
3
4 public class Fragment : MonoBehaviour
5 {
6     public int TypeID;
7     //默认原点
8     public List<Vector2Int> Pos;
9     //其他可能的原点组合
10     public List<List<Vector2Int>> ExPos;
11     public bool bSelected { get; set; }
12     public virtual void Init() { }
13 }```

``` 1 using System.Collections.Generic;
2 using UnityEngine;
3
4 public class RTFragment : Fragment
5 {
6     public override void Init()
7     {
8         TypeID = 7;
9         Pos = new List<Vector2Int>() { new Vector2Int(0, 0), new Vector2Int(-1, 0), new Vector2Int(0, -1) };
10
11         ExPos = new List<List<Vector2Int>>()
12         {
13             new List<Vector2Int>(){new Vector2Int(0,0),new Vector2Int(1,0),new Vector2Int(1,-1)},
14             new List<Vector2Int>(){new Vector2Int(0,0),new Vector2Int(0,1),new Vector2Int(-1,1)}
15         };
16     }
17 }```

``` 1     protected List<List<Vector2Int>> InitExPos(List<Vector2Int> pos,List<Vector2Int> offse)
2     {
3         var ex = new List<List<Vector2Int>>();
4         foreach (var o in offse)
5         {
6             var temp = new List<Vector2Int>();
7             foreach (var p in pos)
8             {
10             }
12         }
13         return ex;
14     }```

`        ExPos = InitExPos(Pos, new List<Vector2Int>() { new Vector2Int(0, 1), new Vector2Int(1, 0) });`

``` 1     public Vector2Int Size { get; private set; }
2
3     public int[,] PuzzlePicture { get; private set; }
4
5     public Dictionary<List<Vector2Int>, Fragment> PuzzleFragments = new Dictionary<List<Vector2Int>, Fragment>();
6
7     public void InitPuzzle(Vector2Int size)
8     {
9         Size = size;
10         PuzzlePicture = new int[Size.x, Size.y];
11     }```

``` 1     /// <summary>
2     /// 在棋盘格中添加碎片
3     /// </summary>
4     /// <param name="frag">选择的碎片</param>
5     /// <param name="offse">在棋盘格中的位置</param>
6     /// <returns>是否添加成功</returns>
7     public bool AddFragment(Fragment frag, Vector2Int offse)
8     {
9         var pos = new List<Vector2Int>();
10         var expos = new List<List<Vector2Int>>();
11         foreach (var p in frag.Pos)
12         {
14         }
15         foreach (var pg in frag.ExPos)
16         {
17             var temp = new List<Vector2Int>();
18             foreach (var p in pg)
19             {
21             }
23         }
24         var s = AddFragToPos(pos, expos);
25         if (s != null)
26         {
28         }
29         return s != null;
30     }
31
32     List<Vector2Int> AddFragToPos(List<Vector2Int> pos, List<List<Vector2Int>> expos)
33     {
34         bool ms = true;
35         var spos = new List<Vector2Int>();
36         foreach (var p in pos)
37         {
38             ms = CheckPos(p);
39             if (!ms)
40                 break;
41         }
42         if (!ms)
43         {
44             foreach (var pg in expos)
45             {
46                 bool tb = true;
47                 foreach (var p in pg)
48                 {
49                     tb = CheckPos(p);
50                     if (!tb)
51                         break;
52                 }
53                 if (tb)
54                 {
55                     foreach (var p in pg)
56                     {
57                         PuzzlePicture[p.x, p.y] = 1;
58                     }
59                     spos = pg;
60                     break;
61                 }
62                 else
63                 {
64                     if (expos[expos.Count - 1] == pg)
65                     {
67                         spos = null;
68                     }
69                 }
70             }
71         }
72         else
73         {
74             foreach (var p in pos)
75             {
76                 PuzzlePicture[p.x, p.y] = 1;
77             }
78             spos = pos;
79         }
80         return spos;
81     }```

```1     bool CheckPos(Vector2Int p)
2     {
3         return !(p.x < 0 || p.x >= Size.x || p.y < 0 || p.y >= Size.y || PuzzlePicture[p.x, p.y] != 0);
4     }```

``` 1     /// <summary>
2     /// 从选定位置移除碎片
3     /// </summary>
4     /// <param name="offse">选中的位置</param>
5     /// <returns>是否成功</returns>
6     public bool RemoveFragment(Vector2Int offse)
7     {
8         bool s = false;
9         var spos = new List<Vector2Int>();
10         foreach (var pg in PuzzleFragments.Keys)
11         {
12             if (pg.Contains(offse))
13             {
14                 s = RemoveFragToPos(pg);
15                 spos = pg;
16                 break;
17             }
18         }
19         if (s)
20             PuzzleFragments.Remove(spos);
21         return s;
22     }
23
24     bool RemoveFragToPos(List<Vector2Int> pos)
25     {
26         foreach (var p in pos)
27         {
28             if (PuzzlePicture[p.x, p.y] == 0)
29             {
30                 return false;
31             }
32         }
33
34         foreach (var p in pos)
35         {
36             PuzzlePicture[p.x, p.y] = 0;
37         }
38
39         return true;
40     }```

``` 1 using System.Collections.Generic;
2 using UnityEngine;
3 using UnityEngine.UI;
4
5 public class TestPuzzle : MonoBehaviour
6 {
7     private List<GridView> Grids = new List<GridView>();
8
9     private List<Fragment> Fragments = new List<Fragment>();
10
11     private PuzzleCtrl PuzzleCtrl;
12
13     private Fragment CurSelectFrag;
14     public void Start()
15     {
16         PuzzleCtrl = GetComponent<PuzzleCtrl>();
17         PuzzleCtrl.InitPuzzle(new Vector2Int(3, 3));
18
20         foreach (var f in Fragments)
21         {
22             f.Init();
23
24             var bt = f.GetComponent<Button>();
26             {
27                 if (f.bSelected)
28                 {
29                     f.bSelected = false;
30                     CurSelectFrag = null;
31                 }
32                 else
33                 {
34                     f.bSelected = true;
35                     if (CurSelectFrag != null)
36                         CurSelectFrag.bSelected = false;
37                     CurSelectFrag = f;
38                 }
39             });
40         }
41
43
44         foreach (var g in Grids)
45         {
46             var bt = g.GetComponent<Button>();
48             {
49                 if (CurSelectFrag == null)
50                 {
51                     PuzzleCtrl.RemoveFragment(g.pos);
52                 }
53                 else
54                 {
56                 }
57                 UpdateView(PuzzleCtrl.Size,PuzzleCtrl.PuzzlePicture);
58             });
59         }
60     }
61
62     public void UpdateView(Vector2Int size,int[,] v)
63     {
64         for (int i = 0; i < size.x; i++)
65         {
66             for (int j = 0; j < size.y; j++)
67             {
68                 foreach (var g in Grids)
69                 {
70                     if (g.pos.x == i && g.pos.y == j)
71                     {
72                         g.GetComponent<Image>().color = v[i, j] == 0 ? new Color(0, 0, 0, 169 * 1.0f / 255) : new Color(1, 1, 1, 233 * 1.0f / 255);
73                         break;
74                     }
75                 }
76             }
77         }
78     }
79 }```

0 条评论

• ### Unity 随机房间地图生成

无论是在迷宫还是类似于地牢的游戏地图中，利用程序来生成每次都不一样的地图是一件叫人兴奋不已的事。

• ### Unity 随机地图房间通道生成

https://www.cnblogs.com/koshio0219/p/12604383.html

• ### Unity NavMesh 动态烘焙绘制与随机取点

最初的Unity导航系统很不完善，只能静态烘焙场景图的可行走区域，而且必须在本地保存场景的NavMesh数据，难以运行时动态计算；这使得鲜有开发者愿意再尝试Un...

• ### UI绘制

版权声明：本文为博主原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接和本声明...

• ### Eureka的InstanceInfoReplicator类（服务注册辅助工具）

以下图片来自Netflix官方，图中显示Eureka Client会向注册中心发起Get Registry请求来获取服务列表：

• ### PHP程序员如何简单的开展服务治理架构(二)

服务治理 治理的绝笔是服务，在一家公司有玩各种语言的程序员，如何去统一管理他们开发的服务，这是一个问题。

• ### Collection.toArray()

该方法是一个泛型方法： T[] toArray(T[] a); 如果toArray方法中没有传递任何参数的话返回的是Object类型数组。

• ### 水晶报表常用公式

A.计量单位转换 这是一个非常简单的例子，主要是为了演示在公式中进行不同变量类型的转换和计算。 有时数据库字段的单位和报表中显示的单位不...

• ### JDK动态代理详解

本文主要介绍JDK动态代理的基本原理，让大家更深刻的理解JDK Proxy,知其然知其所以然。明白JDK动态代理真正的原理及其生成的过程，我们以后写JDK Pr...