转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
扫雷外挂的设计与实现(五)         ★★★★

扫雷外挂的设计与实现(五)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:662 更新时间:2009/4/23 18:26:52

文/jorge

如前所述,算法层的实现,不外乎两种操作:1。如果一个方块的数值等于周围未挖开的方块数目,则把周围所有方块标记为雷;2。如果一个方块的数值等于周围已经标记为雷的方块个数,则在该块上同时单击左右键。实际上,这只是最简单的两种判断(简单到甚至不该称之为“判断”,而只是例行公事而已),而比这更复杂的分析判断还可以有很多,但现在我们追求的是程序的简单易懂,而且,就这两种最简单的判断,已经可以达到很好的效果了,在实际中它们绝对占到了扫雷所用时间的一大多半。更高级的判断,在扫雷外挂的0.2版本里也已经实现了,但在此处若要加以叙述,不免还要大幅增加篇幅。

就来看这个最简单的算法:

=================================================================

//根据Cells中的数据进行判断,把适当的操作填入Operations中
procedure AnalyzeCells;
var
  i, j: Integer;
  neighborCount: Integer;      //保存一个方块周围未挖开的方块的数目
begin
  //首先清空输出缓冲区
  for i:=0 to AreaWidth-1 do
  for j:=0 to AreaHeight-1 do
    Operations[i, j] := opNone;
  //扫描输入缓冲区,执行两种最简单的判断
  for i:=0 to AreaWidth-1 do
  for j:=0 to AreaHeight-1 do
  begin
    //取得一个方块周围未挖开的方块的数目
    neighborCount := CountNeighbors(i, j, [csUnknown, csPossible]);
    //只有1~8的数字,并且周围存在未挖开的方块,这样的方块才有分析价值
    if (Cells[i, j]>cs0) and (Cells[i, j]<=cs8) and (neighborCount > 0) then
      //第一种情况
      if neighborCount = Ord(Cells[i, j])-CountNeighbors(i, j, [csMarked]) then
        MarkAllNeighbors(i, j)
      //第二种情况
      else if Ord(Cells[i, j]) = CountNeighbors(i, j, [csMarked]) then
        Operations[i, j] := opBothClick;
  end;
end;


//将指定方块周围8个方块中,未挖开的,包括已标记问号的,都标记为雷。
procedure MarkAllNeighbors(const x, y: Integer);
var
  i,j: Integer;
begin
  //扫描以某个坐标为中心的9个方块
  for i:=x-1 to x+1 do
  for j:=y-1 to y+1 do
  begin
    //去除中心块,并避免数组越界
    if ((i=x) and (j=y)) or (i<0) or (i>=AreaWidth) or (j<0) or (j>=AreaHeight) then
      Continue;
    //未挖开的空白则单击右键,未挖开的标问号的,则双击右键
    if Cells[i, j] = csUnknown then
        Operations[i, j] := opRightClick
    else if Cells[i, j] = csPossible then
        Operations[i, j] := opRightDoubleClick;
  end;
end;


//取得指定方块周围8个方块中等于任一个指定状态的方块的个数。
function CountNeighbors(const x, y: Integer; const targetStates: TCellStates): Integer;
var
  i,j: Integer;
begin
  result := 0;
  //扫描以某个坐标为中心的9个方块
  for i:=x-1 to x+1 do
  for j:=y-1 to y+1 do
  begin
    //去除中心块,并避免数组越界
    if ((i=x) and (j=y)) or (i<0) or (i>=AreaWidth) or (j<0) or (j>=AreaHeight) then
      Continue;
    //计数指定状态的方块
    if Cells[i, j] in targetStates then
      Inc(result);
  end;
end;
=================================================================

其中,由于枚举TCellState的常量位置的安排,Ord函数对cs0~cs8所取得的值正是0~8,即等于该方块的数值。这个算法可以算是中规中矩,没什么取巧的地方,因此应该不那么难懂。不错,至此扫雷外挂已经完全实现完毕。把上述所有函数和全局内容放在一个单元(可以是一个窗体)里,设好TTimer控件的间隔,就可以很理想的工作了。在外挂类程序的开发中,本例用到的也许是最“笨”的一种方法,但对于平面方格类游戏,其原理具有通用性。它不需对游戏底层数据、协议之类有什么了解,只需要了解游戏的屏幕图形就可以了。本例对于Windows窗口相关的某些API,也是一个较好的熟悉机会,对于初学者会有其意义。这个例子本身并不是最完善的,了解了思想,每个人自可以做出更加完善的程序。比如,应用钩子,这会大幅度减少该程序占用的系统资源。

几天时间终于写完了这堆文章,希望能给适当的人带来适当的收益。欢迎交流,信箱:euth@163.com


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台