一款消消乐游戏里有刷子,消费主张吸尘器器

1628人阅读
前段时间玩了一款网页游戏,消消乐(/game/xxk/index.htm?1=0?f=&i=#noref)
游戏规则介绍:
在一个10*10的方格中,有5种颜色的方块,当双击联通块时,联通块消失。(联通块的定义:至少有2个方块颜色相同,并且相连)联通块中的每一块的价值是n,n由联通块中的个数决定。
当双击联通块消失后,联通块上面的方块会下降,填充消失区域。如果某一列消失,右侧的列会向左靠齐。直到没有联通块为止,游戏结束,看谁的得分高。
1、联通块越大,最后得分越高。比如由5个小方格组成的联通块价值:5*5=25.而如果是由10块组成的,那就是10*10=100.所以应该尽量让同种色块组合成一个尽量大的联通块。
2、理想状态:颜色尽可能少,同色块尽可能是连接在一起的。这个主要是为了后来算法评估做准备。数学证明比较简单。
假设有5中颜色,每种颜色的数量为a,b,c,d,e,那么就有a+b+c+d+e=100,需要求a*a+b*b+c*c+d*d+e*e的最大值。取值范围[0~100],所以,当某一个颜色是100,最大。同理,同一个颜色的色块链接在一起价值最大。
有了这些准备,我们再来看算法:
当给定一个图形时:我们能够知道如下价格关键数据
1、图形中有多少个联通块。
2、图形中色块的完美值:各个色块的平方和。
3、由上一个图形状态转换到当前图形状态,已经产生的价值。
当我们拿到一个图形,通过分析会得到N个联通块,每一个联通块消失都会产生一种新的视图。就有N种情况。在这N中情况中,我们会选择评估值最高的去尝试(贪心嘛,总是为了得到最大值),于是就开始了递归查询。
程序设计:
1、一个视图类,用来保存视图的各种数据
2、视图帮助类,用来计算分析视图的,(当然完全可以放在视图类里面)
3、视图管理类,用来处理算法,筛选最优视图去处理,并且调度并行任务。
视图类GameVIew
&/pre& &pre code_snippet_id=&1596212& snippet_file_name=&blog__8130802& name=&code& class=&csharp&&using S
using System.Collections.G
using System.L
using System.T
using System.Threading.T
namespace BlockGame
public class GameView
public GameView()
State = 0;
/// &summary&
/// 0:未检测过
/// &/summary&
public int State
public GameView Parent
public int Col
public int Row
public int Color
public int[,] ViewData
public string
ViewDataString
/// &summary&
/// 转换到当前视图的累计分数
/// &/summary&
public int PreScore
/// &summary&
/// 从上一个视图转换到当前视图的分数
/// &/summary&
public int StepScore
/// &summary&
/// 视图的评估值=当前值+视图完美值
/// &/summary&
public int AppraiseScore
/// &summary&
/// 当前视图的完美值
/// &/summary&
public int PerfectScore
using System.Collections.G
using System.L
using System.T
using System.Threading.T
using System.D
namespace BlockGame
public class GameViewHepler
public void CalcPerfectScore(GameView view)
int[] cs = new int[view.Color];
int c = 0;
for (int x = 0; x & view.R x++)
for (int y = 0; y & view.C y++)
c = view.ViewData[x, y];
if (c != 0)
cs[c-1]++;
int perfectScore = 0;
for (int i = 0; i & cs.L i++)
perfectScore += cs[i] * cs[i];
view.PerfectScore = perfectS
public void CalcAppraiseScore(GameView view)
view.AppraiseScore = view.PreScore + view.PerfectS
/// &summary&
/// 初始化视图ViewDataString属性
/// &/summary&
/// &param name=&view&&&/param&
public void CalcViewDataString(GameView view)
StringBuilder s = new StringBuilder();
for (int x = 0; x & view.R x++)
for (int y = 0; y & view.C y++)
s.Append(view.ViewData[x, y].ToString() + &,&);
view.ViewDataString = s.ToString();
/// &summary&
/// 由字符串初始化GameView
/// GameView已经被正确创建Row,Col,Color,PreScore,StepScore,Parent属性
/// 随后初始化其他属性:ViewData,ViewDataString,PerfectScore,AppraiseScore,
/// &/summary&
/// &param name=&view&&&/param&
/// &param name=&s&&&/param&
public void InitViewDataByString(GameView view,string s)
#region 初始化数据部分
string[] strs = s.Split(',');
for (int x = 0; x & view.R x++)
for (int y = 0; y & view.C y++)
int c = Convert.ToInt32(strs[x * view.Col + y]);
view.ViewData[x, y] =
#endregion
view.ViewDataString =
CalcPerfectScore(view);
CalcAppraiseScore(view);
#region 计算有多少个联通块
/// &summary&
/// 计算有多少个联通块
/// &/summary&
/// &param name=&view&&&/param&
/// &returns&&/returns&
public List&List&Point&& CalcBlocks(GameView view)
int[,] usedView = new int[view.Row, view.Col];
List&List&Point&& ViewBlocks = new List&List&Point&&();
for (int x = 0; x & view.R x++)
for (int y = 0; y & view.C y++)
if (usedView[x, y] == 0)
//没有被使用过
int c = view.ViewData[x, y];
if (c & 0)
usedView[x, y] = 1;
List&Point& block = new List&Point&();
block.Add(new Point(x, y));
analyseNext(c, x, y, block, view, usedView);
if (block.Count == 1)
//只有一个块的,不进入
ViewBlocks.Add( block);
return ViewB
private void analyseNext(int color, int x, int y, List&Point& block,GameView view,int[,] usedView)
if (x - 1 &= 0)
if (view.ViewData[x - 1, y] == color && usedView[x - 1, y] == 0)
block.Add(new Point(x - 1, y));
usedView[x - 1, y] = 1;
analyseNext(color, x - 1, y, block,view,usedView);
if (x + 1 & view.Row)
if (view.ViewData[x + 1, y] == color && usedView[x + 1, y] == 0)
block.Add(new Point(x + 1, y));
usedView[x + 1, y] = 1;
analyseNext(color, x + 1, y, block,view,usedView);
if (y - 1 &= 0)
if (view.ViewData[x, y - 1] == color && usedView[x, y - 1] == 0)
block.Add(new Point(x, y - 1));
usedView[x, y - 1] = 1;
analyseNext(color, x, y - 1, block, view, usedView);
if (y + 1 & view.Col)
if (view.ViewData[x, y + 1] == color && usedView[x, y + 1] == 0)
block.Add(new Point(x, y + 1));
usedView[x, y + 1] = 1;
analyseNext(color, x, y + 1, block, view, usedView);
#endregion
/// &summary&
/// 移除某个联通块,构建一个新的视图
/// &/summary&
/// &param name=&view&&&/param&
/// &param name=&block&&&/param&
/// &returns&&/returns&
public GameView RemoveBlock(GameView view, List&Point& block)
#region Clone新视图
GameView v = new GameView()
Col = view.Col,
Row = view.Row,
Color = view.Color,
Parent = view,
PreScore = view.PreScore + block.Count * block.Count,
StepScore = block.Count * block.Count
v.ViewData = new int[v.Row, v.Col];
InitViewDataByString(v, view.ViewDataString);
#endregion
#region 移除
foreach (Point p in block)
v.ViewData[p.X, p.Y] = 0;
#endregion
ReBuildViewData(v);
CalcViewDataString(v);
CalcPerfectScore(v);
CalcAppraiseScore(v);
/// &summary&
/// 重构视图的数据部分,也就是移动后ViewData
/// &/summary&
private void ReBuildViewData(GameView view)
for (int y = view.Col - 1; y &= 0; y--)
//是否需要向左移动
bool moveleft =
//从上向下找,是否有颜色快存在
bool hasColor =
//找到右侧可以平移的列
bool hasCol =
#region 掉落
for (int x = 0; x & view.R x++)
if (view.ViewData[x, y] != 0)
moveleft =
hasColor =
if (hasColor)
//开始下移
for (int i = i &= 0; i--)
if (i == 0)
view.ViewData[i, y] = 0;
if (view.ViewData[i - 1, y] == 0)
view.ViewData[i, y] = 0;
view.ViewData[i, y] = view.ViewData[i - 1, y];
#endregion
#region 左移
if (moveleft)
if (y == view.Col - 1)
for (int i = 0; i & view.R i++)
if (view.ViewData[i, y + 1] != 0)
if (hasCol)
for (int i = 0; i & view.R i++)
for (int j = j & view.C j++)
if (j == view.Col - 1)
view.ViewData[i, j] = 0;
view.ViewData[i, j] = view.ViewData[i, j + 1];
#endregion
using System.Collections.G
using System.L
using System.T
using System.Threading.T
using System.T
using System.D
using System.D
namespace BlockGame
public class GameViewManager
private List&GameView& gameViewL
private List&GameView& resultViewL
private GameViewH
private object objlock = new object();
private Dictionary&string, int& taskD
private Action&int,long& completedEventH
public Action&int,long& Completed
completedEventHandler =
private void OnCompleted()
if (completedEventHandler != null)
completedEventHandler(max,time);
public GameViewManager()
gameViewList = new List&GameView&();
resultViewList = new List&GameView&();
hepler = new GameViewHepler();
taskDic = new Dictionary&string, int&();
/// &summary&
/// 分析一个GameView,并转换成下一步的若干个GameView
/// &/summary&
/// &param name=&view&&&/param&
private void analyseGameView(GameView view)
List&List&Point&& blocks = hepler.CalcBlocks(view);
if (blocks.Count == 0)
//此视图终结
resultViewList.Add(view);
foreach (List&Point& block in blocks)
GameView v = hepler.RemoveBlock(view, block);
lock(objlock)
if (v.PreScore & max)
max = v.PreS
#region 判断是否存在
GameView evl=
lock(objlock)
evl = (from p in gameViewList
where p.ViewDataString == v.ViewDataString
select p).FirstOrDefault();
if (evl == null)
Console.WriteLine(&添加新view&);
gameViewList.Add(v);
Console.WriteLine(&有相同view存在&);
if (evl.PreScore & v.PreScore)
Console.WriteLine(&有相同view存在,而且新的更优&);
//Thread.Sleep(3000);
#endregion
#region 判断是否是优秀结果
//在选择的时候已经过滤了,所以,这里不用处理
//是不是删除更好?加快查找?但也有可能,删除后会再次加入
var bv = from p in gameViewList
where p.AppraiseScore &= max && p.State == 0
lock(objlock)
Console.WriteLine(&将会淘汰{0}&, bv.Count());
#endregion
//Console.WriteLine(&执行完毕&);
private Task analyseGameViewAsync(string taskid)
return Task.Run(()=&
bool flag =
while (flag)
GameView view=
lock (objlock)
view = (from p in gameViewList
where p.State == 0 && p.AppraiseScore &= max
orderby p.AppraiseScore descending
select p).FirstOrDefault();
if (view != null)
view.State = 1;
taskDic[taskid] = 1;
taskDic[taskid] = 0;
if (view == null)
//其他线程都完成了,整个任务完成,
bool completed =
lock(objlock)
foreach (KeyValuePair&string, int& kvp in taskDic)
if (kvp.Value == 1)
completed =
if (completed)
Console.WriteLine(&线程{0}处理一条数据&, taskid);
analyseGameView(view);
OnCompleted();
void AddTask(string taskid)
if (taskDic.ContainsKey(taskid))
throw new Exception(&重复taskid&);
lock(objlock)
taskDic.Add(taskid, 1);
Stopwatch watch = new Stopwatch();
await analyseGameViewAsync(taskid);
public async void StartTask()
List&Task& task = new List&Task&();
lock(objlock)
foreach (var taskid in taskDic)
Task t = analyseGameViewAsync(taskid.Key);
task.Add(t);
Stopwatch watch = new Stopwatch();
watch.Start();
await Task.WhenAll(task);
watch.Stop();
time = watch.ElapsedM
Console.WriteLine(&共用时:{0}&, watch.ElapsedMilliseconds);
OnCompleted();
public void AddFirstGameView(GameView view)
gameViewList.Clear();
resultViewList.Clear();
gameViewList.Add(view);
窗体里面调用
首先初始化第一个视图
& & & & & & int x = Convert.ToInt16(this.textBox1.Text);
& & & & & & int y = Convert.ToInt16(this.textBox2.Text);
& & & & & & int c = Convert.ToInt16(this.textBox3.Text);
& & & & & & gv = new GameView() { Row = x, Col = y, Color = c, PreScore = 0, StepScore = 0 };
& & & & & & gv.ViewData = new int[gv.Row, gv.Col];
& & & & & & string str = &&;
& & & & & & for (int i = 0; i & i++)
& & & & & & {
& & & & & & & & for (int j = 0; j & j++)
& & & & & & & & {
& & & & & & & & & & Random r = new Random(Guid.NewGuid().GetHashCode());
& & & & & & & & & & int rc = r.Next(1, c + 1);
& & & & & & & & & & str += rc.ToString() + &,&;
& & & & & & & & }
& & & & & & }
& & & & & & hepler.InitViewDataByString(gv, str);
开始计算任务
GameViewManager manager = new GameViewManager();
& & & & & & manager.AddFirstGameView(gv);
& & & & & & pleted = new Action&int,long&(Show);
& & & & & & manager.AddTask(&1&);
& & & & & & manager.AddTask(&2&);
& & & & & & manager.AddTask(&3&);
& & & & & & manager.AddTask(&4&);
& & & & & & manager.StartTask();
程序运行效果图
源代码即下载地址:http://download.csdn.net/detail/mamihong/9452014
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:106791次
积分:1650
积分:1650
排名:第19629名
原创:38篇
转载:20篇
评论:37条
(2)(3)(3)(5)(7)(5)(2)(1)(3)(1)(2)(12)(2)(1)(2)(1)(3)(1)(1)(1)(1)(1)(1)(1)(1)(2)(3)(5)您的当前位置: > 正文
宾果消消乐特殊消除方法内容汇总攻略
来源:作者:思奇焉者
在一款消除游戏中,玩家们都知道其中的消除内容和方式虽然简单,并不是玩家们所见的那样易于识别的。同样的游戏宾果消消乐也是如此,那么宾果消消乐其中又会有怎样的消除方法和方式呢?接下来小编来为玩家们汇总一下。
在面对着一场充满挑战的挑战邪恶女巫的场景中,星星点点的操作已经不能够满足和武装小女孩儿对Q弹的糖果进行操作了,快来欣赏一些特殊的消除方法吧!
交换相邻两个糖果的位置,使4个颜色相同的糖果在同一行或同一列上连成直线,会在交换点处形成一个特殊效果。再次在该特殊效果上进行消除会消除掉一整行或者一整列的糖果。
交换相邻两个糖果的位置,使5个颜色相同的糖果形成&T&、&L&或&+&型,会在交换点处形成一个特殊效 果。再次在该特殊效果上进行消除会消除掉一整行和一整列的糖果。
交换相邻两个糖果的位置,使5个颜色相同的糖果在同一行或者同一列上相连,会在交换点处形成一个特 殊效果。再次在该特殊效果上进行消除会消除掉所有和激活糖果颜色相同的糖果。

我要回帖

更多关于 吸尘器消音器 的文章

 

随机推荐