`
arust
  • 浏览: 95388 次
  • 性别: Icon_minigender_1
  • 来自: 海底
社区版块
存档分类
最新评论

与众不同的扫雷之二

    博客分类:
  • lang
阅读更多

继续扫雷

扫雷游戏中最核心的算法,当属显示空白区域的算法,当点中的方格位于一片空白区域之中时,游戏界面上要把这一片空白区域以及包围该区域的数字边界都显示出来。首先需要明确的一点是:包围空白区域的方格只可能为数字,不可能含有地雷,这个可以用反证法证明。

网上关于这个算法的实现,几乎都是低效地搜索相邻的空白区域,直到遇到数字边界为止,通常是用递归来实现的。我没有采用这种算法,从本能上我就排斥类似于这样的弱智算法。既然我采用字符串的形式来保存地图数据,理所当然的,我也应当利用 Lua 内置的高效字符串处理库来计算空白区。

另外,如果从效率上来考虑的话,最好是在第一次点击某块空格的时候,将所有的空白区域计算出来,并保存,以后每一次点击空格操作,就只需要查找点击的位置属于那一片空白区,然后显示出来即可。

思考算法实现的时候,单纯从数学的角度去考虑,未免枯燥了点。不妨把自己想象成一位具有非凡勇气的探险家,心怀梦想以及对未知世界的强烈渴望,驾驶着帆船航行于茫茫的大海,去探索新的海域,去发现新的大陆。嗯,再把时代背景安排在人类开始认识地球,观察宇宙,思考人生的文艺复兴时期,这样去思考算法就比较生动有趣了。

在我的每一次航行中,我都会到达许多未知的海域。为了能够探索到地球上全部的海域,我决定按照纬度,从零度经线开始向东行驶。每当完成一次环球旅行,我便向南行驶,到达一片新海域,然后继续从零度经线向东行驶,周而复始,直到探索完全部的海域,绘制一张精确的航海图,我的目的就达到了。

绘制一副精确的航海图是一件十分困难的事情,因为海洋是巨大而神秘的,而我们人类只是沧海一粟,为了将未知的海域逐一探索,首先,我要按照纬度,把海洋分成不同的海域。同一纬度上,连续不断的一片水域,我都把它们作为同一片海域对待。随着旅程不断增加,也许我会发现不同纬度的海域之间,它们在某一条或者多条经度线上,海水是互相连接着的,两片海域仿佛有海峡相连,这样,我就可以把这些水域在海图上全部划入相同的海域。最后,当我完成了全球探险之旅,我就可以知道,为陆地所包围着的海洋,或者说被海洋所包围着的陆地,究竟是什么样子的。某一片海洋,它的海面分布是从北纬多少,到南纬多少,从西经多少,到东经多少,我都会航海图上详细标明,一目了然。当有人想知道某一个经纬度已知的位置位于哪一片海洋,我就可以查看绘制好的航海图后,明确无误地告诉他了。



首先,我必须在海图上把相连的海域全部连成一片。


function classfy_sea_area(origin_map, current_map, width)
    local uncharted_water = split_sea_area(origin_map, current_map, width)
    local new_horizon = {}
    while #uncharted_water > 0 do
        local u_w = {}
        local sea_area = uncharted_water[1]
        for i, v in ipairs(uncharted_water) do
            if i > 1 then
                local n_h = has_strait_between(sea_area, v, width)
                if n_h then
                    sea_area = n_h
                else
                    u_w[#u_w + 1] = v
                end
            end
        end
        if #sea_area == #uncharted_water[1] then
            new_horizon[#new_horizon + 1] = sea_area
        else
            u_w[#u_w + 1] = sea_area
        end
        uncharted_water = u_w 
    end
    return new_horizon 
end



这样来划分海域。

function split_sea_area(origin_map, current_map, width)
    local col = 1
    local t3 = {}
    while true do
        local s1 = string.sub(origin_map, col, col + width - 1)
        local s2 = string.sub(current_map, col, col + width - 1)
        local i = 0
        local j = 0
        while true do
            i, j = string.find(s2, "?+", j + 1)
            if i == nil then break end
            local s = string.sub(s1, i, j)
            local off1 = 0
            local off2 = 0
            while true do
                off1, off2 = string.find(s, "0+", off2 + 1)
                if off1 == nil then break end
                local t1 = {}
                t1[#t1 + 1] = col + i + off1 - 2
                t1[#t1 + 1] = col + i + off2 - 2
                local t2 = {}
                t2[1] = t1
                t3[#t3 + 1] = t2
            end
        end
        col = col + width
        if col > #origin_map then
            break
        end
    end
    return t3
end



两片海域之间是否有海峡相邻?可以这样来判断:


function has_strait_between(sea_area1, sea_area2, width)
    for i1, v1 in ipairs(sea_area1) do
        for i2, v2 in ipairs(sea_area2) do
            local min_dist1 = v1[1] - v2[2] - 1
            local max_dist1 = v1[2] - v2[1] + 1
            local min_dist2 = v2[1] - v1[2] - 1
            local max_dist2 = v2[2] - v1[1] + 1
            if min_dist1 >= 0 then
                if (min_dist1 < width and width < max_dist1) 
                    or (min_dist1 == width and (v1[1] % width) ~= 1) 
                    or (max_dist1 == width and (v1[2] % width) ~= 0) then
                    return sea_area_union(sea_area1, sea_area2)
                end
            elseif min_dist2 >= 0 then
                if (min_dist2 < width and width < max_dist2) 
                    or (min_dist2 == width and (v2[1] % width) ~= 1) 
                    or (max_dist2 == width and (v2[2] % width) ~= 0) then
                    return sea_area_union(sea_area1, sea_area2)
                end
            end 
        end
    end
    return nil
end



如果发现两片海域属于同一个海洋,那么我需要在海图上把两片海域连起来


function sea_area_union(a, b)
    local c = {}
    for i,v in ipairs(a) do
        c[#c + 1] = v
    end
    for i,v in ipairs(b) do
        c[#c + 1] = v
    end
    return c
end

分享到:
评论

相关推荐

    java小游戏 扫雷 java小游戏 扫雷

    java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java小游戏 扫雷java...

    扫雷小游戏2

    扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1扫雷小游戏1...

    扫雷 扫雷 扫雷 扫雷 扫雷

    扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷扫雷

    vc++游戏源代码 第2章 扫雷

    vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷vc++游戏源代码 第2章 扫雷...

    C++扫雷 C++扫雷

    C++扫雷 C++扫雷 C++扫雷程序

    扫雷扫雷程序的

    扫雷程序的外挂和扫雷程序

    经典版本的扫雷图片素材

    1. **数组和二维数组**:扫雷游戏的核心是二维格子布局,我们可以使用二维数组来表示游戏地图,每个元素代表一个格子,存储该位置的信息,如是否为雷、周围雷的数量等。 2. **随机数生成**:C语言的`&lt;stdlib.h&gt;`库...

    java扫雷代码详解

    由于扫雷游戏是一个二维网格,因此二维数组是存储游戏数据的理想选择。数组的行和列的大小可以根据游戏的难度来设定,行和列的每个元素代表网格中的一个单元格,单元格中可能包含雷,或者与周围的雷有一定的数学关系...

    扫雷源程序 扫雷源程序 扫雷源程序

    扫雷源程序扫雷源程序扫雷源程序扫雷源程序扫雷源程序扫雷源程序

    saolei.rar_CMD版扫雷_cmd打开扫雷_cmd扫雷_cmd游戏_扫雷

    首先,CMD版扫雷新奇之处在于它不依赖于图形化界面,而是利用命令行界面来呈现游戏。在传统的Windows扫雷中,玩家通过鼠标点击来揭开雷区的方块,而在CMD版扫雷中,你需要输入特定的命令来执行这些操作。例如,你...

    java实现扫雷游戏.zip

    java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java...

    扫雷源程序及exe

    2. **二维数组的使用**:扫雷游戏通常使用二维数组来存储雷区的状态,每一格代表游戏地图上的一个位置,数组元素的值表示该位置的状态(如雷、数字、空白等)。 3. **事件处理**:当用户点击游戏区域时,程序需要...

    cocos2d-x扫雷

    二、游戏逻辑实现 扫雷的核心逻辑包括生成雷区、标记雷、扫雷过程中的判断和提示。在Cocos2d-x中,这通常通过自定义的C++类实现,例如`MineField`类表示雷区,`Cell`类代表单个格子。这些类会包含各自的属性(如雷的...

    java扫雷(javaSE实现扫雷)

    2. **二维数组**:扫雷游戏的棋盘通常用二维数组表示,每个数组元素对应棋盘上的一个格子。数组的索引可以映射到屏幕上的坐标,方便进行位置转换和逻辑处理。 3. **随机数生成**:在初始化棋盘时,需要随机地在特定...

    扫雷游戏.exe

    扫雷游戏.exe

    扫雷的java程序.rar_JAVA 扫雷_java 游戏_扫雷_游戏编程

    2. **图形用户界面(GUI)**:如Java的Swing或JavaFX库,用于创建窗口、按钮、面板等组件,实现用户与程序的交互。 3. **事件处理**:理解事件监听器和事件处理机制,如MouseListener和ActionListener,实现用户点击...

    扫雷.zip_扫雷;matlab

    matlab版扫雷,主程序为saolei.m ,操作方法与Windows自带扫雷类似。

    扫雷游戏MATLAB代码

    扫雷游戏MATLAB代码

    扫雷程序可执行文件

    由于win10去掉了原先自带的扫雷程序,因而这里从网上找了一个扫雷程序过来,作为目标进行分析

Global site tag (gtag.js) - Google Analytics