连连看游戏是老少爷们喜爱玩的游戏, 因此 我就 写了 连连看游戏。
要完成一个连连看游戏,以面向对象的思想 来思考这个游戏。首先, 我需要一个类
每个连连看的需要 连连看的画框, 由于要设置不同级别,因此要 一个游戏级别的类。
你怎么能确保正确的开展游戏 因此 需要游戏的引擎。
他的类图如下:
你会问我GameConfig 这个类究竟是干什么的,英译过来就是游戏的配置的类,简而言之,就是放游戏的配置文件的类吗,这是
放游戏更加的有趣,加载相应的背景音乐和背景图片的效果 。 那startMenu 又是什么啊,加载的开始的窗口 进行一些游戏参数配置的页面。
那topMenu 只不过是顶级的菜单,
相当于显示栏与游戏重置栏把
各行各业的软件有不同的侧重点把,比如 普通系统的软件侧重点是业务知识的精通把,而互联网网站也分成几个层次,首先网站的都要侧重的是性能的优化,而像google,度娘
这样的搜索引擎他更突出与算法是别致,而像facebook,人人网这样的社交网络更倾向与社会工程学的展示。游戏的核心是巧夺天工的算法与别出心裁的玩法设置。
而 我这是一个简单的游戏, 麻雀虽小五脏俱全, 他有一个相应的算法
游戏要将 相应的 图片杂乱无章展示出来,此时需要一个FillBoard(初始化砖块)方法
首先 确定这是在相应的画布上来作图,产生相应级别的所产生数目一半组数的砖块(譬如说这个级别的产生60个图片,我此时就通过这个方法产生30组相应配对的图片)。再通过相应的随机的函数来放在画布不同的位置。你会问我怎么能使游戏可连。因为能确定相应的边线 ,底线可连。根据相应的数学知识证明之,此游戏是可玩的
最终的效果图如下
相应的源代码如下:
public static void FillGrid()
{
GameBackGrid.Width = CurLevel.Backgrid.X * ItemSize.Width;
GameBackGrid.Height = CurLevel.Backgrid.Y * ItemSize.Height;
List<ImgItem> CreatedItems = new List<ImgItem>();
Random rand = new Random();
for (int i = 0; i < ItemCount / 2; i++)
{
int index = rand.Next(CurLevel.BackGrid.Length - 1);
ImgItem item = new ImgItem();
item.ItemImg = CurLevel.BackGrid[index];
ImgItem item2 = new ImgItem() { ItemImg = item.ItemImg };
item.SelectIt += item_SelectIt;
item2.SelectIt += item_SelectIt;
CreatedItems.Add(item);
CreatedItems.Add(item2);
}
for (int i = 0; i < ItemCount; i++)
{
int x = (int)(i % CurLevel.Backgrid.X);
int y = (int)(i / CurLevel.Backgrid.X);
int index = rand.Next(CreatedItems.Count - 1);
ImgItem item = CreatedItems[index];
item.Width = ItemSize.Width;
item.Height = ItemSize.Height;
item.Location = new Point(x, y);
item.Parent = GameBackGrid;
item.Show();
AllItems[x][y] = item;
CreatedItems.Remove(item);
}
}
连连看 中最关键,最核心的算法就是 相连的算法 一般底线,边线的方块上的图片和相邻方块上的图片是可以相连的。如果两张方块上的图片是没有其他方块相连的。
我这里是由于十字形的上没有相隔的头像相同的图片是可以相连的。 相连就是用以循环来遍历周围图片是否有间隔图片,如果没有相应的间隔是可以相连的。
相应算法的源代码如下:
#region 二点是否可连算法
/// <summary>
/// 判断二个点是否可以连
/// </summary>
/// <param name="item1"></param>
/// <param name="item2"></param>
/// <returns></returns>
public static bool IsCanLink(ImgItem item1, ImgItem item2)
{
//如果二个图片不相同。则直接返回否.且如果二个为同一个也不可连
if (item1.ItemImg != item2.ItemImg || item1 == item2) return false;
ItemDer itemder = GetItemDer(item1, item2);
switch (itemder)
{
case ItemDer.LineX://二点在同一X轴上
{
return CheckLineX(item1, item2);
}
case ItemDer.LineY://二点在同一Y轴上
{
return CheckLineY(item1, item2);
}
}
return false;
}
/// <summary>
/// 在同一X轴上的判断
/// </summary>
/// <param name="item1"></param>
/// <param name="item2"></param>
/// <returns></returns>
private static bool CheckLineX(ImgItem item1, ImgItem item2)
{
//判断二点间的直线是否可连,或为最顶部点,或为最底部点
if (CheckInPointsIsEmpty(item1.Location, item2.Location, ItemDer.LineX) || (item1.Location.Y == 0 && item2.Location.Y == 0) ||
(item1.Location.Y == CurLevel.Backgrid.Y - 1 && item2.Location.Y == CurLevel.Backgrid.Y - 1))
{
return true;
}
//向上开始判断
//每次向上伸一个编移量,如果有连通的则可以连
for (int i = (int)item1.Location.Y - 1; i >= 0; i--)
{
Point p1 = new Point(item1.Location.X, i);
Point p2 = new Point(item2.Location.X, i);
//如果这二点有任意一点不为空
//则向上的方向不可行
if (!CheckPointIsEmpty(p1) || !CheckPointIsEmpty(p2)) break;
if (CheckInPointsIsEmpty(p1, p2, ItemDer.LineX)) //如果它们之间为空
{
return true;
}
if (i == 0)//如果这二点为最顶部,所以可以连
{
return true;
}
}
//向上开始判断
//每次向下伸一个编移量,如果有连通的则可以连
for (int i = (int)item1.Location.Y + 1; i <= CurLevel.Backgrid.Y - 1; i++)
{
Point p1 = new Point(item1.Location.X, i);
Point p2 = new Point(item2.Location.X, i);
//如果这二点有任意一点不为空
//则向下的方向不可行
if (!CheckPointIsEmpty(p1) || !CheckPointIsEmpty(p2)) break;
if (CheckInPointsIsEmpty(p1, p2, ItemDer.LineX)) //如果它们之间为空
{
return true;
}
if (i == CurLevel.Backgrid.Y - 1)//如果这二点为最底部,所以可以连
{
return true;
}
}
return false;
}
/// <summary>
/// 在同一Y轴上的判断
/// </summary>
/// <param name="item1"></param>
/// <param name="item2"></param>
/// <returns></returns>
private static bool CheckLineY(ImgItem item1, ImgItem item2)
{
//判断二点间的直线是否可连,或为最左边,或为最右边
if (CheckInPointsIsEmpty(item1.Location, item2.Location, ItemDer.LineY) || (item1.Location.X == 0 && item2.Location.X == 0) ||
(item1.Location.X == CurLevel.Backgrid.X - 1 && item2.Location.X == CurLevel.Backgrid.X - 1))
{
return true;
}
//向左开始判断
//每次向左伸一个编移量,如果有连通的则可以连
for (int i = (int)item1.Location.X - 1; i >= 0; i--)
{
Point p1 = new Point(i, item1.Location.Y);
Point p2 = new Point(i, item2.Location.Y);
//如果这二点有任意一点不为空
//则向左的方向不可行
if (!CheckPointIsEmpty(p1) || !CheckPointIsEmpty(p2)) break;
if (CheckInPointsIsEmpty(p1, p2, ItemDer.LineY)) //如果它们之间为空
{
return true;
}
if (i == 0)//如果这二点为最左边,所以可以连
{
return true;
}
}
//向右开始判断
//每次向右伸一个编移量,如果有连通的则可以连
for (int i = (int)item1.Location.X + 1; i <= CurLevel.Backgrid.X - 1; i++)
{
Point p1 = new Point(i, item1.Location.Y);
Point p2 = new Point(i, item2.Location.Y);
//如果这二点有任意一点不为空
//则向右的方向不可行
if (!CheckPointIsEmpty(p1) || !CheckPointIsEmpty(p2)) break;
if (CheckInPointsIsEmpty(p1, p2, ItemDer.LineY)) //如果它们之间为空
{
return true;
}
if (i == CurLevel.Backgrid.X - 1)//如果这二点为最右,所以可以连
{
return true;
}
}
return false;
}
/// <summary>
/// 判断左上右下的二点
/// </summary>
/// <param name="item1"></param>
/// <param name="item2"></param>
/// <returns></returns>
/// <summary>
/// 判断左下右上的二点
/// </summary>
/// <param name="item1"></param>
/// <param name="item2"></param>
/// <returns></returns>
/// <summary>
/// 判断二点之间是否都为空
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
private static bool CheckInPointsIsEmpty(Point p1, Point p2, ItemDer iDer)
{
//如果二点为X轴方向
if (iDer == ItemDer.LineX)
{
//如果二点在一起
if (Math.Abs(p1.X - p2.X) == 1 || (p1.X - p2.X) == 0)
{
return true;
}
//得到二点的X轴偏移量
int offsetx = (int)(p1.X - p2.X);
//p1在p2的左边
if (offsetx < 0)
{
for (int i = 1; i < Math.Abs(offsetx); i++)
{
//如果二点之间有不为空的点
if (!CheckPointIsEmpty(new Point(p1.X + i, p1.Y)))
{
return false;
}
}
return true;
}
else//1在2的右边
{
for (int i = 1; i < Math.Abs(offsetx); i++)
{
//如果二点之间有不为空的点
if (!CheckPointIsEmpty(new Point(p2.X + i, p1.Y)))
{
return false;
}
}
return true;
}
}
else if (iDer == ItemDer.LineY) //如果为Y轴方向
{
//如果二点在一起
if (Math.Abs(p1.Y - p2.Y) == 1 || p1.Y - p2.Y == 0)
{
return true;
}
//得到二点的Y轴偏移量
int offsety = (int)(p1.Y - p2.Y);
//p1在p2的上边
if (offsety < 0)
{
for (int i = 1; i < Math.Abs(offsety); i++)
{
//如果二点之间有不为空的点
if (!CheckPointIsEmpty(new Point(p1.X, p1.Y + i)))
{
return false;
}
}
return true;
}
else//1在2的下边
{
for (int i = 1; i < Math.Abs(offsety); i++)
{
//如果二点之间有不为空的点
if (!CheckPointIsEmpty(new Point(p2.X, p2.Y + i)))
{
return false;
}
}
return true;
}
}
return false;
}
/// <summary>
/// 检查查此位置是否为空
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
private static bool CheckPointIsEmpty(Point p)
{
//foreach (ImgItem item in Config.SLConfig.AllItems)
//{
// if (item.Location == p)
// {
// return false;
// }
//}
return AllItems[(int)p.X][(int)p.Y] == null;
}
/// <summary>
/// 判断二点的方位
/// </summary>
/// <param name="item1"></param>
/// <param name="item2"></param>
/// <returns></returns>
private static ItemDer GetItemDer(ImgItem item1,ImgItem item2)
{
if (item1.Location.X == item2.Location.X)
{
return ItemDer.LineY;
}
if (item1.Location.Y==item2.Location.Y)
{
return ItemDer.LineX;
}
return ItemDer.Unkown;
}
#endregion
真的 最后我要强调一点的是,这一个方块是一个imgItem 类 他本质是由一个个imgBrush的笔刷将图片画在上面的。那他怎么有点击事件。我这里是通过一个DelegateSelectItem 自定义事件触发了_Rect_MouseLeftButtonDown 完成的
项目开源地址 http://51aspx.com/Code/WP7LianLianKan