一,部分游戏规则如下:

二,代码如下:

1. 游戏逻辑核心代码

 using System.Collections.Generic;
using UnityEngine; namespace Modules.UI
{
// 逻辑与UI分离,这是逻辑类
public class LianLianKanController
{
int m_rowCount;
List<LianLianKanCell> m_cells = new List<LianLianKanCell>();
IHandler m_handler; public int RowCount
{
get { return m_rowCount; }
} public List<LianLianKanCell> Cells
{
get { return m_cells; }
} public bool GameFinished
{
get
{
for (int i = ; i < m_cells.Count; i++)
{
if (m_cells[i].Showing)
{
return false;
}
}
return true;
}
} public interface IHandler
{
void OnResetPos();
} public LianLianKanController(int rowCount, IHandler handler)
{
m_rowCount = rowCount + ; // 为了边缘上的格子也能连线
m_handler = handler; // 生成cell
for (int x = ; x < m_rowCount; x++)
{
for (int y = ; y < m_rowCount; y++)
{
int pos = m_rowCount * y + x;
LianLianKanCell cell = new LianLianKanCell(this);
cell.Position = pos;
cell.Showing = x != && x != m_rowCount - && y != && y != m_rowCount - ;
cell.Icon = y - ;
m_cells.Add(cell);
}
}
} // 打乱
public void ResetPos()
{
List<int> positions = new List<int>();
for (int i = ; i <= m_rowCount - ; i++)
{
for (int j = ; j <= m_rowCount - ; j++)
{
int pos = m_rowCount * j + i;
positions.Add(pos);
}
} for (int i = ; i < m_cells.Count; i++)
{
var cell = m_cells[i];
if (cell.Showing)
{
int ranIndex = Random.Range(, positions.Count);
int position = positions[ranIndex];
positions.RemoveAt(ranIndex);
cell.Position = position;
}
} bool canDraw = CanDrawAnyLine();
if (canDraw)
m_handler.OnResetPos();
else
ResetPos();
} bool CanDrawAnyLine(LianLianKanCell start)
{
for (int i = ; i < m_cells.Count; i++)
{
var end = m_cells[i];
if (start != end && end.Showing)
{
List<LianLianKanCell> brokenCells;
bool isMatch = IsMatch(start, end, out brokenCells);
if (isMatch)
return true;
}
} return false;
} bool CanDrawAnyLine()
{
for (int i = ; i < m_cells.Count; i++)
{
var start = m_cells[i];
if (start.Showing)
{
bool canDraw = CanDrawAnyLine(start);
if (canDraw)
return true;
}
} return false;
} // 尝试连线
public bool TryDrawLine(LianLianKanCell first, LianLianKanCell second, out List<LianLianKanCell> brokenCells)
{
bool isMatch = IsMatch(first, second, out brokenCells);
if (isMatch)
{
first.Showing = false;
second.Showing = false; if (!GameFinished && !CanDrawAnyLine())
{
ResetPos();
}
}
return isMatch;
} LianLianKanCell GetCellByPos(int x, int y)
{
for (int i = ; i < m_cells.Count; i++)
{
var cell = m_cells[i];
if (cell.X == x && cell.Y == y)
return cell;
}
return null;
} // 0个拐点
bool MatchBroken0(LianLianKanCell first, LianLianKanCell second)
{
// 如果不属于0折连接则返回false
if (first.X != second.X && first.Y != second.Y)
{
return false;
} int min, max;
// 如果两点的x坐标相等,则在竖直方向上扫描
if (first.X == second.X)
{
min = first.Y < second.Y ? first.Y : second.Y;
min++;
max = first.Y > second.Y ? first.Y : second.Y; for (int i = min; i < max; i++)
{
var cell = GetCellByPos(first.X, i);
if (cell.Showing)
return false;
}
}
// 如果两点的y坐标相等,则在水平方向上扫描
else
{
min = first.X < second.X ? first.X : second.X;
min++;
max = first.X > second.X ? first.X : second.X; for (int i = min; i < max; i++)
{
var cell = GetCellByPos(i, first.Y);
if (cell.Showing)
return false;
}
} return true;
} // 1个拐点
bool MatchBroken1(LianLianKanCell first, LianLianKanCell second, out LianLianKanCell brokenCell)
{
if (first.X == second.X || first.Y == second.Y)
{
brokenCell = null;
return false;
} // 测试对角点1
brokenCell = GetCellByPos(first.X, second.Y);
if (!brokenCell.Showing)
{
bool match = MatchBroken0(first, brokenCell) && MatchBroken0(brokenCell, second);
if (match)
return true;
} // 测试对角点2
brokenCell = GetCellByPos(second.X, first.Y);
if (!brokenCell.Showing)
{
bool match = MatchBroken0(first, brokenCell) && MatchBroken0(brokenCell, second);
if (match)
return true;
} return false;
} // 2个拐点
bool MatchBroken2(LianLianKanCell first, LianLianKanCell second, ref List<LianLianKanCell> brokenCells)
{
for (int i = first.Y + ; i < m_rowCount; i++)
{
var cell = GetCellByPos(first.X, i);
if (cell.Showing)
break; LianLianKanCell brokenCell;
if (MatchBroken1(cell, second, out brokenCell))
{
brokenCells.Add(cell);
brokenCells.Add(brokenCell);
return true;
}
} for (int i = first.Y - ; i > -; i--)
{
var cell = GetCellByPos(first.X, i);
if (cell.Showing)
break; LianLianKanCell brokenCell;
if (MatchBroken1(cell, second, out brokenCell))
{
brokenCells.Add(cell);
brokenCells.Add(brokenCell);
return true;
}
} for (int i = first.X + ; i < m_rowCount; i++)
{
var cell = GetCellByPos(i, first.Y);
if (cell.Showing)
break; LianLianKanCell brokenCell;
if (MatchBroken1(cell, second, out brokenCell))
{
brokenCells.Add(cell);
brokenCells.Add(brokenCell);
return true;
}
} for (int i = first.X - ; i > -; i--)
{
var cell = GetCellByPos(i, first.Y);
if (cell.Showing)
break; LianLianKanCell brokenCell;
if (MatchBroken1(cell, second, out brokenCell))
{
brokenCells.Add(cell);
brokenCells.Add(brokenCell);
return true;
}
} return false;
} bool IsMatch(LianLianKanCell first, LianLianKanCell second, out List<LianLianKanCell> brokenCells)
{
brokenCells = new List<LianLianKanCell>();
if (first == second || first.Icon != second.Icon)
return false; // 0个拐点
if (MatchBroken0(first, second))
return true; // 1个拐点
LianLianKanCell brokenCell;
if (MatchBroken1(first, second, out brokenCell))
{
brokenCells.Add(brokenCell);
return true;
} // 2个拐点
if (MatchBroken2(first, second, ref brokenCells))
return true; return false;
} }
}

LianLianKanController

2. 封装了一个格子

 using System;

 namespace Modules.UI
{
public class LianLianKanCell
{
LianLianKanController m_controller;
int m_icon; // icon的索引,从0到7
int m_position; // 位置索引,从0到63
bool m_showing; // 是否显示中 public int Icon
{
get { return m_icon; }
set { m_icon = value; }
} public bool Showing
{
get { return m_showing; }
set { m_showing = value; }
} public int Position
{
get { return m_position; }
set { m_position = value; }
} public int X
{
get { return m_position % m_controller.RowCount; }
} public int Y
{
get { return m_position / m_controller.RowCount; }
} public LianLianKanCell(LianLianKanController controller)
{
if (controller == null)
throw new ArgumentNullException("controller"); m_controller = controller;
} public override string ToString()
{
return string.Format("{0}_{1}_{2}", m_icon, m_position, m_showing);
}
}
}

LianLianKanCell

3. 游戏界面

 using System;
using System.Collections.Generic;
using UnityEngine; namespace Modules.UI
{
public class UI_LianLianKanWnd : UI_AutoSortDepthWnd, UI_LianLianKanCell.IHandler, LianLianKanController.IHandler
{
public static int RowCount = ; [SerializeField]
GameObject m_btnClose;
[SerializeField]
UI_LianLianKanCell m_cell;
[SerializeField]
Transform m_parentOfCell;
[SerializeField]
UI_LianLianKanLine m_line; LianLianKanController m_controller;
UI_LianLianKanCell[] m_uiCells;
Queue<UI_LianLianKanCell> m_selectedCells = new Queue<UI_LianLianKanCell>(); public static void Create()
{
UIManager.ShowUISync(UIFlag.ui_entertainment_war, UIFlag.ui_lianliankan, UIFlag.none, false, null, UIFlag.none);
} protected override UIFlag UIFlag
{
get { return UIFlag.ui_lianliankan; }
} protected override void Awake()
{
base.Awake(); UIEventListener.Get(m_btnClose).onClick = OnClickClose; // 生成icon
m_controller = new LianLianKanController(RowCount, this);
m_uiCells = new UI_LianLianKanCell[m_controller.Cells.Count];
m_cell.Show = false;
float posOfCellsParent = (m_controller.RowCount / 2f - 0.5f) * m_cell.Width;
m_parentOfCell.localPosition = new Vector3(-posOfCellsParent, -posOfCellsParent);
for (int i = ; i < m_uiCells.Length; i++)
{
UI_LianLianKanCell cell = m_cell.Instantiate<UI_LianLianKanCell>(m_parentOfCell);
cell.Init(m_controller.Cells[i], this);
m_uiCells[i] = cell;
}
} void OnClickClose(GameObject go)
{
Close();
} public override void OnShowWnd(UIWndData wndData)
{
base.OnShowWnd(wndData); ResetWnd();
} void ResetWnd()
{
m_controller.ResetPos();
} void OnGameFinished()
{
UIMessageMgr.ShowMessageBoxOnlyOK("成功完成!", base.Close, null);
} void UI_LianLianKanCell.IHandler.OnClick(UI_LianLianKanCell self)
{
if (m_selectedCells.Contains(self))
return; self.Selected = true;
m_selectedCells.Enqueue(self); if (m_selectedCells.Count < )
return; var cells = m_selectedCells.ToArray();
List<LianLianKanCell> brokenCells;
bool succeed = m_controller.TryDrawLine(cells[].Data, cells[].Data, out brokenCells);
if (succeed)
{
cells[].AnimHide();
cells[].AnimHide();
m_selectedCells.Clear(); // 画线
DrawLine(cells[], cells[], brokenCells); if (m_controller.GameFinished)
OnGameFinished();
}
else
{
var removedCell = m_selectedCells.Dequeue();
removedCell.Selected = false;
}
} // 画线
void DrawLine(UI_LianLianKanCell start, UI_LianLianKanCell end, List<LianLianKanCell> brokenCells)
{
List<Vector3> points = new List<Vector3>();
points.Add(start.transform.localPosition);
for (int i = ; i < brokenCells.Count; i++)
{
UI_LianLianKanCell cell = Array.Find<UI_LianLianKanCell>(m_uiCells, c => c.Data == brokenCells[i]);
points.Add(cell.transform.localPosition);
}
points.Add(end.transform.localPosition);
m_line.DrawLine(points);
} void LianLianKanController.IHandler.OnResetPos()
{
for (int i = ; i < m_uiCells.Length; i++)
m_uiCells[i].Reset();
m_selectedCells.Clear();
}
}
}

UI_LianLianKanWnd

4. 游戏界面上的格子UI

 using System;
using UnityEngine; namespace Modules.UI
{
public class UI_LianLianKanCell : UI_BaseWidget
{
[SerializeField]
UISprite m_spriteIcon;
[SerializeField]
GameObject m_objSelected;
[SerializeField]
UILabel m_labelName;
[SerializeField]
BackAndForthWindow m_anim; LianLianKanCell m_data;
IHandler m_handler; public int Width
{
get { return m_spriteIcon.width; }
} public bool Selected
{
set { m_objSelected.SetActive(value); }
get { return m_objSelected.activeSelf; }
} public LianLianKanCell Data
{
get { return m_data; }
} public interface IHandler
{
void OnClick(UI_LianLianKanCell self);
} void Awake()
{
UIEventListener.Get(m_spriteIcon.gameObject).onClick = OnClickSelf;
} void OnClickSelf(GameObject go)
{
m_handler.OnClick(this);
} // icon: 索引从0到7
public void Init(LianLianKanCell data, IHandler handler)
{
if (data == null)
throw new ArgumentNullException("data");
if (handler == null)
throw new ArgumentNullException("handler"); m_data = data;
m_handler = handler;
} public void Reset()
{
m_spriteIcon.spriteName = "icon_" + m_data.Icon; transform.localPosition = new Vector3(m_data.X * Width, m_data.Y * Width);
transform.name = m_data.ToString();
m_labelName.text = string.Format("{0}({1},{2})", m_data.Position, m_data.X, m_data.Y);
m_labelName.gameObject.SetActive(false); base.Show = m_data.Showing; Selected = false;
} public void AnimHide()
{
m_anim.Hide();
m_anim.OnHide = () =>
{
Show = false;
};
} }
}

UI_LianLianKanCell

5. 游戏界面上的线

 using System;
using System.Collections.Generic;
using UnityEngine; namespace Modules.UI
{
public class UI_LianLianKanLine : UI_BaseWidget
{
[SerializeField]
UISprite m_spriteLine; List<UISprite> m_lines = new List<UISprite>(); void DrawLine(Vector3 start, Vector3 end)
{
UISprite spriteLine = GetOrCreateLine();
Vector3 center = (start + end) / 2f;
Vector3 fromStart = end - start;
Vector3 horVector = Vector3.right;
Quaternion rot = Quaternion.FromToRotation(horVector, fromStart); spriteLine.transform.localPosition = center;
spriteLine.transform.localRotation = rot;
spriteLine.width = Mathf.CeilToInt(fromStart.magnitude);
spriteLine.alpha = ;
spriteLine.gameObject.SetActive(true); // 播放消隐动画
var anim = spriteLine.GetComponent<BackAndForthWindow>();
anim.Hide();
anim.OnHide = () => { anim.gameObject.SetActive(false); };
} UISprite GetOrCreateLine()
{
for (int i = ; i < m_lines.Count; i++)
{
var line = m_lines[i];
if (!line.gameObject.activeSelf)
return line;
} GameObject obj = NGUITools.AddChild(gameObject, m_spriteLine.gameObject);
UISprite sprite = obj.GetComponent<UISprite>();
m_lines.Add(sprite);
return sprite;
} void Start()
{
m_spriteLine.gameObject.SetActive(false);
} public void DrawLine(List<Vector3> points)
{
if (points.Count < || points.Count > )
throw new ArgumentException("points.Count < 2 || points.Count > 4, points count is: " + points.Count); for (int i = ; i <= points.Count - ; i++)
{
DrawLine(points[i], points[i + ]);
}
}
}
}

UI_LianLianKanLine

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

三,效果如下:

NGUI之实现连连看小游戏的更多相关文章

  1. 软件设计之基于Java的连连看小游戏(一)——开题及游戏首页的制作

    原本计划紧张忙碌的考试月在图书馆和实验室度过,结果突如其来为期两周的软件设计把课余时间几乎捆绑在了机房.软设没有太多知识上的要求,只要成品简洁美观.实用准确即可.考虑了很久决定要用Java swing ...

  2. 软件设计之基于Java的连连看小游戏(二)——游戏基础界面的制作及事件的添加

    上次完成到游戏首页的制作,今天完成了游戏基础界面的制作以及事件的简单添加.由于功能尚未完全实现,因此游戏界面的菜单列表只是简单地添加了一下,其余菜单列表以及倒计时等在后续的制作中逐一完善. 1.首先在 ...

  3. 软件设计之基于Java的连连看小游戏(三)——所有功能的实现

    新年快乐!期末接二连三的考试实在太忙了忘记连连看没有更新完,今天想要学习生信时才发现.所以这次直接把连连看所有功能全部放上. 在传统的连连看的基础上,我增加了上传头像的功能,即可以自行上传图片作为游戏 ...

  4. javascrpit开发连连看记录-小游戏

        工作之余,总想做点什么有意思的东西.但是苦于不知道做什么,也就一直没有什么动作.在一个午饭后,跟@jedmeng和@墨尘聊天过程中,发现可以写一些小东西来练练手,有以下几点好处:     1. ...

  5. 使用NGUI实现拖拽功能(拼图小游戏)

    上一次用UGUI实现了拼图小游戏,这次,我们来用NGUI来实现 实现原理 NGUI中提供了拖拽的基类UIDragDropItem,所以我们要做的就是在要拖拽的图片上加一个继承于该类的脚本,并实现其中的 ...

  6. Android开发系列(十五):【Android小游戏成语连连看】第一篇

            学了一个多月安卓.由于暑假的时候要给朋友说写个小游戏.并且也想检測下自己的能力,所以说从7号開始就着手写这个小游戏了,前前后后带上课到今天总算是写完了,可是写的这个小游戏还是有非常多问 ...

  7. Android开发系列(十六):【Android小游戏成语连连看】第二篇

    写的晚了,在分工个Z市高中的一个成绩查询的系统,原系统居然是用VB写的,我不得不佩服原本写系统的那位哥们真能耐得住. 明天搭建下SVN就等着先发project款然后開始项目了.想想有工资进账,心里也为 ...

  8. 自制Unity小游戏TankHero-2D(1)制作主角坦克

    自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  9. 分享几个cocos2dx的小游戏

    先上几个自己写的,因为最近要用cocos2dx,所以就边学边开发几个小游戏玩玩,有捕鱼,连连看,还有打地鼠!都不算完整的项目,不过拿来学习还是可以的,或者在基础上再二次开发,扩展自己! 1:捕鱼的 先 ...

随机推荐

  1. css position各种定位及区别

    position定位: static:静态定位;是position的默认值,元素框正常生成,也就是没有定位时的正常显示. relative:相对定位; 用法一:元素相对自身的原位置偏移某个距离,但是原 ...

  2. LeetCode 709.To Lower Case

    Description Implement function ToLowerCase() that has a string parameter str, and returns the same s ...

  3. vw实现移动端自适应页面

    一.设备支持情况 测试网站:https://caniuse.com/#search=vw css3test:https://airen.github.io/css3test/,https://gith ...

  4. python3 配置logging日志类

    配置类config_file: from configparser import ConfigParser class config_file: def __init__(self,conf_file ...

  5. 【洛谷】SAC E#1 Factorial

    别人可以眼杀我却研究了一个小时看了题解才懂的数学题 输入: n, k 输出: n!在k进制下后缀0的个数 n,k <= 10^12 将 n! 表示成 x×2y5z 的形式,其中 x mod 2 ...

  6. 版本管理_git

    git 世界上最好的版本管理工具,分布式版本控制系统. 林纳斯-托瓦斯,自由主义教皇(git.linux) git 不管理空文件夹 对比于 SVN mkdir XX        创建一个空目录 XX ...

  7. 根据屏幕自适应宽度:@media

    @media screen and (min-width: 1490px){ .w1224{ width: 1400px !important; }}@media screen and (max-wi ...

  8. js数组元素,获得某个元素的最大值。

    var rows=[{项次:1},{项次:2},{项次:3}]; Math.max.apply(Math, rows.map(function (o) { return o.项次 })) //结果:3 ...

  9. GParted: GNOME Partition Editor, sharp weapon to modify disk partitions.

    GParted Projects GNOME Partition Editor for creating, reorganizing, and deleting disk partitions. It ...

  10. pycharm 的 激活流程

    激活流程 一.通过Activation code 方式激活 注册码获取地址为:http://idea.lanyus.com/ 在idea或者pycharm的Activation code中输入 注册码 ...