一,部分游戏规则如下:

二,代码如下:

1. 游戏逻辑核心代码

  1 using System.Collections.Generic;
  2 using UnityEngine;
  3
  4 namespace Modules.UI
  5 {
  6     // 逻辑与UI分离,这是逻辑类
  7     public class LianLianKanController
  8     {
  9         int m_rowCount;
 10         List<LianLianKanCell> m_cells = new List<LianLianKanCell>();
 11         IHandler m_handler;
 12
 13
 14         public int RowCount
 15         {
 16             get { return m_rowCount; }
 17         }
 18
 19         public List<LianLianKanCell> Cells
 20         {
 21             get { return m_cells; }
 22         }
 23
 24         public bool GameFinished
 25         {
 26             get
 27             {
 28                 for (int i = 0; i < m_cells.Count; i++)
 29                 {
 30                     if (m_cells[i].Showing)
 31                     {
 32                         return false;
 33                     }
 34                 }
 35                 return true;
 36             }
 37         }
 38
 39
 40         public interface IHandler
 41         {
 42             void OnResetPos();
 43         }
 44
 45
 46         public LianLianKanController(int rowCount, IHandler handler)
 47         {
 48             m_rowCount = rowCount + 2;      // 为了边缘上的格子也能连线
 49             m_handler = handler;
 50
 51             // 生成cell
 52             for (int x = 0; x < m_rowCount; x++)
 53             {
 54                 for (int y = 0; y < m_rowCount; y++)
 55                 {
 56                     int pos = m_rowCount * y + x;
 57                     LianLianKanCell cell = new LianLianKanCell(this);
 58                     cell.Position = pos;
 59                     cell.Showing = x != 0 && x != m_rowCount - 1 && y != 0 && y != m_rowCount - 1;
 60                     cell.Icon = y - 1;
 61                     m_cells.Add(cell);
 62                 }
 63             }
 64         }
 65
 66         // 打乱
 67         public void ResetPos()
 68         {
 69             List<int> positions = new List<int>();
 70             for (int i = 1; i <= m_rowCount - 2; i++)
 71             {
 72                 for (int j = 1; j <= m_rowCount - 2; j++)
 73                 {
 74                     int pos = m_rowCount * j + i;
 75                     positions.Add(pos);
 76                 }
 77             }
 78
 79             for (int i = 0; i < m_cells.Count; i++)
 80             {
 81                 var cell = m_cells[i];
 82                 if (cell.Showing)
 83                 {
 84                     int ranIndex = Random.Range(0, positions.Count);
 85                     int position = positions[ranIndex];
 86                     positions.RemoveAt(ranIndex);
 87                     cell.Position = position;
 88                 }
 89             }
 90
 91             bool canDraw = CanDrawAnyLine();
 92             if (canDraw)
 93                 m_handler.OnResetPos();
 94             else
 95                 ResetPos();
 96         }
 97
 98         bool CanDrawAnyLine(LianLianKanCell start)
 99         {
100             for (int i = 0; i < m_cells.Count; i++)
101             {
102                 var end = m_cells[i];
103                 if (start != end && end.Showing)
104                 {
105                     List<LianLianKanCell> brokenCells;
106                     bool isMatch = IsMatch(start, end, out brokenCells);
107                     if (isMatch)
108                         return true;
109                 }
110             }
111
112             return false;
113         }
114
115         bool CanDrawAnyLine()
116         {
117             for (int i = 0; i < m_cells.Count; i++)
118             {
119                 var start = m_cells[i];
120                 if (start.Showing)
121                 {
122                     bool canDraw = CanDrawAnyLine(start);
123                     if (canDraw)
124                         return true;
125                 }
126             }
127
128             return false;
129         }
130
131         // 尝试连线
132         public bool TryDrawLine(LianLianKanCell first, LianLianKanCell second, out List<LianLianKanCell> brokenCells)
133         {
134             bool isMatch = IsMatch(first, second, out brokenCells);
135             if (isMatch)
136             {
137                 first.Showing = false;
138                 second.Showing = false;
139
140                 if (!GameFinished && !CanDrawAnyLine())
141                 {
142                     ResetPos();
143                 }
144             }
145             return isMatch;
146         }
147
148         LianLianKanCell GetCellByPos(int x, int y)
149         {
150             for (int i = 0; i < m_cells.Count; i++)
151             {
152                 var cell = m_cells[i];
153                 if (cell.X == x && cell.Y == y)
154                     return cell;
155             }
156             return null;
157         }
158
159         // 0个拐点
160         bool MatchBroken0(LianLianKanCell first, LianLianKanCell second)
161         {
162             // 如果不属于0折连接则返回false
163             if (first.X != second.X && first.Y != second.Y)
164             {
165                 return false;
166             }
167
168             int min, max;
169             // 如果两点的x坐标相等,则在竖直方向上扫描
170             if (first.X == second.X)
171             {
172                 min = first.Y < second.Y ? first.Y : second.Y;
173                 min++;
174                 max = first.Y > second.Y ? first.Y : second.Y;
175
176                 for (int i = min; i < max; i++)
177                 {
178                     var cell = GetCellByPos(first.X, i);
179                     if (cell.Showing)
180                         return false;
181                 }
182             }
183             // 如果两点的y坐标相等,则在水平方向上扫描
184             else
185             {
186                 min = first.X < second.X ? first.X : second.X;
187                 min++;
188                 max = first.X > second.X ? first.X : second.X;
189
190                 for (int i = min; i < max; i++)
191                 {
192                     var cell = GetCellByPos(i, first.Y);
193                     if (cell.Showing)
194                         return false;
195                 }
196             }
197
198             return true;
199         }
200
201         // 1个拐点
202         bool MatchBroken1(LianLianKanCell first, LianLianKanCell second, out LianLianKanCell brokenCell)
203         {
204             if (first.X == second.X || first.Y == second.Y)
205             {
206                 brokenCell = null;
207                 return false;
208             }
209
210             // 测试对角点1
211             brokenCell = GetCellByPos(first.X, second.Y);
212             if (!brokenCell.Showing)
213             {
214                 bool match = MatchBroken0(first, brokenCell) && MatchBroken0(brokenCell, second);
215                 if (match)
216                     return true;
217             }
218
219             // 测试对角点2
220             brokenCell = GetCellByPos(second.X, first.Y);
221             if (!brokenCell.Showing)
222             {
223                 bool match = MatchBroken0(first, brokenCell) && MatchBroken0(brokenCell, second);
224                 if (match)
225                     return true;
226             }
227
228             return false;
229         }
230
231         // 2个拐点
232         bool MatchBroken2(LianLianKanCell first, LianLianKanCell second, ref List<LianLianKanCell> brokenCells)
233         {
234             for (int i = first.Y + 1; i < m_rowCount; i++)
235             {
236                 var cell = GetCellByPos(first.X, i);
237                 if (cell.Showing)
238                     break;
239
240                 LianLianKanCell brokenCell;
241                 if (MatchBroken1(cell, second, out brokenCell))
242                 {
243                     brokenCells.Add(cell);
244                     brokenCells.Add(brokenCell);
245                     return true;
246                 }
247             }
248
249             for (int i = first.Y - 1; i > -1; i--)
250             {
251                 var cell = GetCellByPos(first.X, i);
252                 if (cell.Showing)
253                     break;
254
255                 LianLianKanCell brokenCell;
256                 if (MatchBroken1(cell, second, out brokenCell))
257                 {
258                     brokenCells.Add(cell);
259                     brokenCells.Add(brokenCell);
260                     return true;
261                 }
262             }
263
264             for (int i = first.X + 1; i < m_rowCount; i++)
265             {
266                 var cell = GetCellByPos(i, first.Y);
267                 if (cell.Showing)
268                     break;
269
270                 LianLianKanCell brokenCell;
271                 if (MatchBroken1(cell, second, out brokenCell))
272                 {
273                     brokenCells.Add(cell);
274                     brokenCells.Add(brokenCell);
275                     return true;
276                 }
277             }
278
279
280             for (int i = first.X - 1; i > -1; i--)
281             {
282                 var cell = GetCellByPos(i, first.Y);
283                 if (cell.Showing)
284                     break;
285
286                 LianLianKanCell brokenCell;
287                 if (MatchBroken1(cell, second, out brokenCell))
288                 {
289                     brokenCells.Add(cell);
290                     brokenCells.Add(brokenCell);
291                     return true;
292                 }
293             }
294
295             return false;
296         }
297
298         bool IsMatch(LianLianKanCell first, LianLianKanCell second, out List<LianLianKanCell> brokenCells)
299         {
300             brokenCells = new List<LianLianKanCell>();
301             if (first == second || first.Icon != second.Icon)
302                 return false;
303
304             // 0个拐点
305             if (MatchBroken0(first, second))
306                 return true;
307
308             // 1个拐点
309             LianLianKanCell brokenCell;
310             if (MatchBroken1(first, second, out brokenCell))
311             {
312                 brokenCells.Add(brokenCell);
313                 return true;
314             }
315
316             // 2个拐点
317             if (MatchBroken2(first, second, ref brokenCells))
318                 return true;
319
320             return false;
321         }
322
323
324     }
325 }

LianLianKanController

2. 封装了一个格子

 1 using System;
 2
 3 namespace Modules.UI
 4 {
 5     public class LianLianKanCell
 6     {
 7         LianLianKanController m_controller;
 8         int m_icon;             // icon的索引,从0到7
 9         int m_position;         // 位置索引,从0到63
10         bool m_showing;         // 是否显示中
11
12         public int Icon
13         {
14             get { return m_icon; }
15             set { m_icon = value; }
16         }
17
18         public bool Showing
19         {
20             get { return m_showing; }
21             set { m_showing = value; }
22         }
23
24         public int Position
25         {
26             get { return m_position; }
27             set { m_position = value; }
28         }
29
30         public int X
31         {
32             get { return m_position % m_controller.RowCount; }
33         }
34
35         public int Y
36         {
37             get { return m_position / m_controller.RowCount; }
38         }
39
40         public LianLianKanCell(LianLianKanController controller)
41         {
42             if (controller == null)
43                 throw new ArgumentNullException("controller");
44
45             m_controller = controller;
46         }
47
48         public override string ToString()
49         {
50             return string.Format("{0}_{1}_{2}", m_icon, m_position, m_showing);
51         }
52     }
53 }

LianLianKanCell

3. 游戏界面

  1 using System;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4
  5 namespace Modules.UI
  6 {
  7     public class UI_LianLianKanWnd : UI_AutoSortDepthWnd, UI_LianLianKanCell.IHandler, LianLianKanController.IHandler
  8     {
  9         public static int RowCount = 8;
 10
 11         [SerializeField]
 12         GameObject m_btnClose;
 13         [SerializeField]
 14         UI_LianLianKanCell m_cell;
 15         [SerializeField]
 16         Transform m_parentOfCell;
 17         [SerializeField]
 18         UI_LianLianKanLine m_line;
 19
 20         LianLianKanController m_controller;
 21         UI_LianLianKanCell[] m_uiCells;
 22         Queue<UI_LianLianKanCell> m_selectedCells = new Queue<UI_LianLianKanCell>();
 23
 24
 25         public static void Create()
 26         {
 27             UIManager.ShowUISync(UIFlag.ui_entertainment_war, UIFlag.ui_lianliankan, UIFlag.none, false, null, UIFlag.none);
 28         }
 29
 30         protected override UIFlag UIFlag
 31         {
 32             get { return UIFlag.ui_lianliankan; }
 33         }
 34
 35         protected override void Awake()
 36         {
 37             base.Awake();
 38
 39             UIEventListener.Get(m_btnClose).onClick = OnClickClose;
 40
 41             // 生成icon
 42             m_controller = new LianLianKanController(RowCount, this);
 43             m_uiCells = new UI_LianLianKanCell[m_controller.Cells.Count];
 44             m_cell.Show = false;
 45             float posOfCellsParent = (m_controller.RowCount / 2f - 0.5f) * m_cell.Width;
 46             m_parentOfCell.localPosition = new Vector3(-posOfCellsParent, -posOfCellsParent);
 47             for (int i = 0; i < m_uiCells.Length; i++)
 48             {
 49                 UI_LianLianKanCell cell = m_cell.Instantiate<UI_LianLianKanCell>(m_parentOfCell);
 50                 cell.Init(m_controller.Cells[i], this);
 51                 m_uiCells[i] = cell;
 52             }
 53         }
 54
 55         void OnClickClose(GameObject go)
 56         {
 57             Close();
 58         }
 59
 60         public override void OnShowWnd(UIWndData wndData)
 61         {
 62             base.OnShowWnd(wndData);
 63
 64             ResetWnd();
 65         }
 66
 67         void ResetWnd()
 68         {
 69             m_controller.ResetPos();
 70         }
 71
 72         void OnGameFinished()
 73         {
 74             UIMessageMgr.ShowMessageBoxOnlyOK("成功完成!", base.Close, null);
 75         }
 76
 77         void UI_LianLianKanCell.IHandler.OnClick(UI_LianLianKanCell self)
 78         {
 79             if (m_selectedCells.Contains(self))
 80                 return;
 81
 82             self.Selected = true;
 83             m_selectedCells.Enqueue(self);
 84
 85             if (m_selectedCells.Count < 2)
 86                 return;
 87
 88             var cells = m_selectedCells.ToArray();
 89             List<LianLianKanCell> brokenCells;
 90             bool succeed = m_controller.TryDrawLine(cells[0].Data, cells[1].Data, out brokenCells);
 91             if (succeed)
 92             {
 93                 cells[0].AnimHide();
 94                 cells[1].AnimHide();
 95                 m_selectedCells.Clear();
 96
 97                 // 画线
 98                 DrawLine(cells[0], cells[1], brokenCells);
 99
100                 if (m_controller.GameFinished)
101                     OnGameFinished();
102             }
103             else
104             {
105                 var removedCell = m_selectedCells.Dequeue();
106                 removedCell.Selected = false;
107             }
108         }
109
110         // 画线
111         void DrawLine(UI_LianLianKanCell start, UI_LianLianKanCell end, List<LianLianKanCell> brokenCells)
112         {
113             List<Vector3> points = new List<Vector3>();
114             points.Add(start.transform.localPosition);
115             for (int i = 0; i < brokenCells.Count; i++)
116             {
117                 UI_LianLianKanCell cell = Array.Find<UI_LianLianKanCell>(m_uiCells, c => c.Data == brokenCells[i]);
118                 points.Add(cell.transform.localPosition);
119             }
120             points.Add(end.transform.localPosition);
121             m_line.DrawLine(points);
122         }
123
124         void LianLianKanController.IHandler.OnResetPos()
125         {
126             for (int i = 0; i < m_uiCells.Length; i++)
127                 m_uiCells[i].Reset();
128             m_selectedCells.Clear();
129         }
130     }
131 }

UI_LianLianKanWnd

4. 游戏界面上的格子UI

 1 using System;
 2 using UnityEngine;
 3
 4 namespace Modules.UI
 5 {
 6     public class UI_LianLianKanCell : UI_BaseWidget
 7     {
 8         [SerializeField]
 9         UISprite m_spriteIcon;
10         [SerializeField]
11         GameObject m_objSelected;
12         [SerializeField]
13         UILabel m_labelName;
14         [SerializeField]
15         BackAndForthWindow m_anim;
16
17         LianLianKanCell m_data;
18         IHandler m_handler;
19
20
21         public int Width
22         {
23             get { return m_spriteIcon.width; }
24         }
25
26         public bool Selected
27         {
28             set { m_objSelected.SetActive(value); }
29             get { return m_objSelected.activeSelf; }
30         }
31
32         public LianLianKanCell Data
33         {
34             get { return m_data; }
35         }
36
37
38         public interface IHandler
39         {
40             void OnClick(UI_LianLianKanCell self);
41         }
42
43
44         void Awake()
45         {
46             UIEventListener.Get(m_spriteIcon.gameObject).onClick = OnClickSelf;
47         }
48
49         void OnClickSelf(GameObject go)
50         {
51             m_handler.OnClick(this);
52         }
53
54         // icon: 索引从0到7
55         public void Init(LianLianKanCell data, IHandler handler)
56         {
57             if (data == null)
58                 throw new ArgumentNullException("data");
59             if (handler == null)
60                 throw new ArgumentNullException("handler");
61
62             m_data = data;
63             m_handler = handler;
64         }
65
66         public void Reset()
67         {
68             m_spriteIcon.spriteName = "icon_" + m_data.Icon;
69
70             transform.localPosition = new Vector3(m_data.X * Width, m_data.Y * Width);
71             transform.name = m_data.ToString();
72             m_labelName.text = string.Format("{0}({1},{2})", m_data.Position, m_data.X, m_data.Y);
73             m_labelName.gameObject.SetActive(false);
74
75             base.Show = m_data.Showing;
76
77             Selected = false;
78         }
79
80         public void AnimHide()
81         {
82             m_anim.Hide();
83             m_anim.OnHide = () =>
84             {
85                 Show = false;
86             };
87         }
88
89     }
90 }

UI_LianLianKanCell

5. 游戏界面上的线

 1 using System;
 2 using System.Collections.Generic;
 3 using UnityEngine;
 4
 5 namespace Modules.UI
 6 {
 7     public class UI_LianLianKanLine : UI_BaseWidget
 8     {
 9         [SerializeField]
10         UISprite m_spriteLine;
11
12         List<UISprite> m_lines = new List<UISprite>();
13
14         void DrawLine(Vector3 start, Vector3 end)
15         {
16             UISprite spriteLine = GetOrCreateLine();
17             Vector3 center = (start + end) / 2f;
18             Vector3 fromStart = end - start;
19             Vector3 horVector = Vector3.right;
20             Quaternion rot = Quaternion.FromToRotation(horVector, fromStart);
21
22             spriteLine.transform.localPosition = center;
23             spriteLine.transform.localRotation = rot;
24             spriteLine.width = Mathf.CeilToInt(fromStart.magnitude);
25             spriteLine.alpha = 1;
26             spriteLine.gameObject.SetActive(true);
27
28             // 播放消隐动画
29             var anim = spriteLine.GetComponent<BackAndForthWindow>();
30             anim.Hide();
31             anim.OnHide = () => { anim.gameObject.SetActive(false); };
32         }
33
34         UISprite GetOrCreateLine()
35         {
36             for (int i = 0; i < m_lines.Count; i++)
37             {
38                 var line = m_lines[i];
39                 if (!line.gameObject.activeSelf)
40                     return line;
41             }
42
43             GameObject obj = NGUITools.AddChild(gameObject, m_spriteLine.gameObject);
44             UISprite sprite = obj.GetComponent<UISprite>();
45             m_lines.Add(sprite);
46             return sprite;
47         }
48
49         void Start()
50         {
51             m_spriteLine.gameObject.SetActive(false);
52         }
53
54         public void DrawLine(List<Vector3> points)
55         {
56             if (points.Count < 2 || points.Count > 4)
57                 throw new ArgumentException("points.Count < 2 || points.Count > 4, points count is: " + points.Count);
58
59             for (int i = 0; i <= points.Count - 2; i++)
60             {
61                 DrawLine(points[i], points[i + 1]);
62             }
63         }
64     }
65 }

UI_LianLianKanLine

转载请注明出处:https://www.cnblogs.com/jietian331/p/10653450.html

三,效果如下:

转载于:https://www.cnblogs.com/jietian331/p/10653450.html

NGUI之实现连连看小游戏相关推荐

  1. 原生js实现一个连连看小游戏(一)

    前几天使用原生的js写了一个连连看小游戏,地址:连连看(js),基本功能都实现了,运行截图为: 根据游戏规则获取开发思路 创建棋盘格 生成随机不重复数字 映射到棋盘格 鼠标点击事件 寻路,无通路,则到 ...

  2. python连连看小游戏_利用Python制作一个连连看小游戏,边学边玩!

    导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环 ...

  3. python连连看小游戏_python递归法实现简易连连看小游戏

    问题:简单版连连看小游戏 一个分割成w*h个正方格子的矩形板上,每个正方格子可以有游戏卡,也可以没有游戏卡 两个游戏卡之间有一条路径相连需满足以下三个条件: 1.路径只包含水平和垂直的直线段 2.路径 ...

  4. MATLAB连连看小游戏

    这是一款MATLAB连连看小游戏,基本实现了连连看的功能,不过目前没有写出死局判定的模块,日后可能会对其进行改进. 目录 游戏截图 游戏组装说明 完整代码 其他说明 后记 游戏截图 游戏组装说明 我们 ...

  5. H5——连连看小游戏实现思路及源码

    部门要求推广新产品用连连看小游戏的方式, 设计那边UI还没有排期,先撸个功能demo,正好记录一下: 连连看都玩过,程序的关键在于判断连续点击的两张图片是否能够消除,两个图片消除的条件有两个: 图片相 ...

  6. java游戏开发——连连看小游戏

    本次课程主要为大家详细介绍了Java制作--<连连看>小游戏,示例代码介绍的非常详细,具有想当的参考价值,感兴趣的小伙伴们可以学习一下! 小伙伴们应该都玩过连连看吧,今天呢叫大家用Java ...

  7. python应用学习(六)——tkinter制作连连看小游戏

    python 制作连连看小游戏 前言 一.准备 二.游戏简单介绍 1.游戏规则 2.游戏设计所需的图片库: 三.游戏设计 I.创建Point点类 II.定义函数 III.游戏的主函数逻辑 IV.完整代 ...

  8. java连连看小游戏

    目录 运行界面图 代码如下(示例): 2.运行演示 这是一个用java编写的小游戏,连连看是一种消除类益智游戏,核心要求是在规定的时间内,消除游戏界面中选中的两张相同的图案,直至完全消除所有图案.这款 ...

  9. python3+pygame制作的连连看小游戏,好玩,酷炫,

    使用Python3+pygame模块制作的连连看小游戏,好玩,酷炫,很适合初学Python的同学练习 连连看源码下载: 长按左侧二维码 2 秒 回复「连连看」即可获取源码 (非本号) 一.运行效果 二 ...

最新文章

  1. html5网页代码模板简单,简洁蓝色风格HTML5网页模板
  2. 转 Wireshark和TcpDump抓包分析心得
  3. react native windows 搭建(完整版)
  4. HBase数据迁移到Kafka实战
  5. 2021年峰峰春晖中学高考成绩查询,峰峰春晖中学2019年录取分数线
  6. java web Jersey_使用CXF和Jersey框架来进行Java的WebService编程
  7. ACwing 829 模拟队列
  8. 微服务入门到入土(08)-消息队列RabbitMQ
  9. android Launcher 自定义View 高仿hola一键清理效果
  10. Halcon 算子 convexity
  11. 使用pytorch进行深度学习网络模型训练,实现车型识别
  12. js数组按中文拼音排序_学习排序算法,结合这个方法太容易理解了
  13. 使用Blinker APP+NodeMCU控制多路接口
  14. AAA与AAM指令代码实验
  15. [kuangbin]专题三 Dancing Links Squiggly Sudoku HDU - 4069【DFS】【精确覆盖】
  16. ARM工控主板LS1012A
  17. oracle 存储过程语法例子
  18. java_枚举类型(支付方式枚举)
  19. HTML5自造字,电脑中的造字程序怎么用啊怎么造字
  20. 心情日记——20071109(发泄一下)

热门文章

  1. windows10更改切换输入法快捷键
  2. 间隔时间Delta T和时间总长的计算方法
  3. Vert.x(vertx) 简明介绍
  4. 智能网联的核心系统Tsp介绍
  5. InputStream.read()阻塞
  6. 一名优秀的程序员应该向谁提问
  7. JVM 参数及含义(适用于 JDK7及之前)
  8. 云端液位数据的由来与变送器的使用
  9. Java计算排名通用方法
  10. linux火狐网页无声音,解决Firefox在Ubuntu下播放Flash无声音的问题