VB实现可调节难度的九宫格拼图

来源:互联网 发布:易语言远程控制源码 编辑:程序博客网 时间:2024/06/04 17:58

VB实现可调节难度的九宫格拼图

实现本游戏需要熟练掌握paintpicture函数的应用,如果读者对该函数不熟练,需要读一下前面两篇博客哦
http://blog.csdn.net/wf824284257/article/details/53221631
http://blog.csdn.net/wf824284257/article/details/53222996

源码可以在作者的个人主页下载http://www.dawufan.cn/

九宫格拼图,这个游戏,怎么说呢,第一感觉就是给小孩子玩的,很弱智。。。。但是我们是练习代码,所以就拿这个来练练手了,结果在博主写完整个代码并且调试好了以后,自己玩了一下,发现真提莫的难玩。。感觉3*3就是自己的极限了。。。。

先把效果图给出,下面是难度设定为3的时候(3*3)
1
2

好,下面我们来分析一下如何做出这个游戏。

1.游戏功能分析

九宫格拼图游戏,默认难度为3,在开始的时候给出一个窗体,用户选择一张图片载入,之后程序会把图片切割成3*3块,并且拿掉右上角这块,之后随机打乱顺序显示在窗体上,这个时候用户可能会点击 显示 菜单 来显示原图,并且根据原图来拼。在拼图过程中,用户会点击某小块图片,如果该图片周围有空位,则交换这块图片以及空位的位置。每次点击后都要判断是否已经拼好了,如果拼好了,就给出胜利提示。

2.抽象化,数据化

可以理解为内层表示与外层表示,内层是基础层或者说运算层,而外层是显示层。

内层主要用到2个矩阵,一个是正确顺序矩阵,一个是随机顺序矩阵,用户点击图片块,相当于对该随机矩阵进行元素交换,每次点击都程序都会将随机矩阵与正确矩阵元素一一对比,若完全相同,则表明拼图成功。

外层是显示层,主要用到paintpicture函数来实现对源图片的切割显示,在随机矩阵元素交换后,相应控件显示的图片也要交换。

3.控件,界面

这里用到2个窗体和一个模块。form1是主窗体,form2用来显示原图,module1用来定义变量以及写一些代码。窗体如下图所示

3

form1 上设置2个菜单按钮,以及一个picture控件,改名为pic,设置index为0,要在游戏开始后动态加载该pic数组

form2 上放一个picture控件,改名picshow,用来显示原图

3.变量参数

主要游戏变量:

Public MatrixRight() As Integer '正确矩阵Public MatrixNow() As Integer   '当前随机矩阵Public level As Integer         '难度Public i, j, k As Integer  '循环变量

主要界面参数:

Public BW, BH As Integer '大格子宽高,(所有小格子的总宽高)Public sw, sh As Integer  '小格子的宽高Public lk As Integer '留空Public ssw, ssh As Integer ' 源图片的每个小格子宽高 source picture’s sw and sh

使用这些界面参数作为基底可以很方便的设计各个控件的位置

4.功能代码介绍

默认难度为3(level=3),切割成3*3共9块,我们需要一个pic控件来存放源图片并且不可见,9个pic控件来显示切割出来的小图片并且可见,所以我们除了放在form1上的pic(0)以外,还需要动态加载9个pic ,pic(0)用来加载源图片,其他9个pic显示的图片都用paintpicture从pic(0)上切割显示。这里pic(0)的autosize和autoredraw 都要设置为true,这是为了完整的加载图片。

首先我们matrixright矩阵赋值如下

1   2   34   5   67   8   9

再把右上角这一块赋值为-1,用来标识不显示的那块图片

然后通过随机产生matrixnow矩阵,并且把里面的3换成-1。这里随机产生可以通过这样的方式:首先定义一个一维数组randnum(9),则下标为0到8,我们对于矩阵元素1到9来循环。对于1,先产生一个0到8的随机数r,再检测randnum(r)是否有数字了,如果没有就把1放进去,如果有了就再次产生随机数重复以上过程,直到找到一个空位放进去为止,然后再看2. 通过这样的方式在randnum中产生了1到9的随机序列。然后对于matrixnow矩阵,把randnum中的数字一个一个放进去就好了。代码如下

Dim randnum() As IntegerReDim randnum(1 To level ^ 2)Dim r As Integer'creat random num arrayFor i = 1 To level ^ 2    r = Int(level ^ 2 * Rnd) + 1    If randnum(r) = 0 Then        randnum(r) = i    Else        i = i - 1    End IfNext i' change "level" to "-1"For i = 1 To level ^ 2    If randnum(i) = level Then        randnum(i) = -1        Exit For    End IfNext i'put the num array into the matrixnowp = 1For i = 0 To level - 1    For j = 0 To level - 1        MatrixNow(i, j) = randnum(p)        p = p + 1    Next jNext i

比如产生了这样的随机矩阵

5   4   68   2   79   3   1

把3变成-1,然后初始的图片就按这个顺序切割显示,-1的那块不显示,就好了。

这样我们内层的初步工作就做完了,下面要显示form1,并且动态加载好控件,设置好他们的位置,以及窗体大小。

lk = 200   '留空200Form1.Width = 9000  '窗体宽9000,高8000Form1.Height = 8000BW = Me.ScaleWidth - 2 * lk '窗体中减去左右的留空,作为所有图片块的总宽BH = Me.ScaleHeight - 2 * lksw = BW \ level  '每个图片块的宽,高sh = BH \ levelFor i = 1 To level ^ 2 '加载picture控件,并按index设置位置    Load pic(i)    j = (i - 1) \ level    k = (i - 1) Mod level    pic(i).Top = lk + j * sh    pic(i).Left = lk + k * sw    pic(i).Width = sw    pic(i).Height = sh    pic(i).Visible = TrueNext i

当用户点击 打开 时,我们调用commondialog控件来打开图片,该控件需要手动添加

On Error GoTo errhandlercmdlg.InitDir = App.Pathcmdlg.Filter = "所有文件(*.*)|*.*"cmdlg.ShowOpenpic(0).Picture = LoadPicture(cmdlg.FileName)ssw = pic(0).ScaleWidth / levelssh = pic(0).ScaleHeight / level

这里我们相当于把pic(0)也进行了3*3切割,ssw表示source pic’s small width ,源图片的小块的宽,ssh表示源图片小块的高。pic(0)的属性要设置为不可见,autosize为true,这样就把源图片原原本本的加载到pic(0)了。

接下来在pic( 1 to 9)中画出相应的图片,这里我们把源图片拉伸到BW*BH的大小后切割,再画出来的,代码为

' paint the level^2 pics out of orderDim p As Integerp = 1      '  pic's pointer hereFor i = 0 To level - 1    For j = 0 To level - 1        Dim mn As Integer        mn = MatrixNow(i, j)        If mn <> -1 Then ' when -1 no pic            Dim m, n As Integer            m = (mn - 1) \ level            n = (mn - 1) Mod level            pic(p).PaintPicture pic(0).Picture, 0, 0, pic(p).ScaleWidth, pic(p).ScaleHeight, n * ssw, m * ssh, ssw, ssh        End If        p = p + 1    Next jNext i

这里的paintpicture函数将源图片的相应小块拉伸放入了pic(p)中,关于这个函数如果看不懂,可以参考本文最上面给出的2个链接,这里就不再讲述。

图片的点击事件是比较关键的一点,我们需要判断被点击图片的4个方向是否存在空位,如果存在,就交换位置

Private Sub pic_Click(index As Integer)    i = (index - 1) \ level    j = (index - 1) Mod level    'click on the -1 pic    If MatrixNow(i, j) = -1 Then Exit Sub    'swap judge on 4 derections    Dim m, n As Integer    'left    m = i - 1    n = j    If Judge(m, n, index) Then Exit Sub    'right    m = i + 1    n = j    If Judge(m, n, index) Then Exit Sub    'up    m = i    n = j - 1    If Judge(m, n, index) Then Exit Sub    'down    m = i    n = j + 1    If Judge(m, n, index) Then Exit Sub    'cannot swap,do nothingEnd Sub

Judge函数用来判断该方向是否存在空位,如果存在就交换,并判断是否已拼完,返回true,否则返回false。

Private Function Judge(ByVal m As Integer, ByVal n As Integer, ByVal index As Integer) As Boolean    'judge if the matrixnow(i,j) (m,n) can swap        If (m >= 0 And m <= level - 1) And (n >= 0 And n <= level - 1) Then            If MatrixNow(m, n) = -1 Then                'swap pic                SavePicture pic(index).Image, "temp.jpg"                pic(m * level + n + 1).Picture = LoadPicture("temp.jpg")                pic(index).Picture = LoadPicture("")                'swap matrixnow 's value                Dim temp As Integer                temp = MatrixNow(i, j)                MatrixNow(i, j) = MatrixNow(m, n)                MatrixNow(m, n) = temp                Judge = True                Dim x, y As Integer                Dim victory As Boolean                victory = True                For x = 0 To level - 1                    For y = 0 To level - 1                        If MatrixNow(x, y) <> MatrixRight(x, y) Then                            victory = False                            Exit For                        End If                    Next y                    If victory = False Then Exit For                Next x                If victory Then                    MsgBox "victory!", , "caguatations!"                    Kill "temp.jpg"                End If                Exit Function            End If    End If    Judge = FalseEnd Function

这里的图片交换我们是通过这样的方式

SavePicture pic(index).Image, "temp.jpg"pic(m * level + n + 1).Picture = LoadPicture("temp.jpg")pic(index).Picture = LoadPicture("")

通过保存后再载入,可以很方便的实现图片的交换。这里为什么不用paintpicture来做呢?原因有2个:一是如果想直接将pic(1)中的图片画到pic(2)中,那pic(1)中的图片不可以是用paintpicture画上去的,也就是说用paintpicture画上去的图片是不算图片的,picture属性仍未0;二是如果想从pic(0)中将对应部分的图片画上去,那还要再进行坐标的转换,好麻烦。。。

所以最终是利用了中间文件的思路,再最后退出的时候,再将”temp.jpg” kill掉就可以了。

5难度设置

写代码的时候要考虑代码的通用性,可变性等,所以虽然游戏的难度默认为3,但是代码中都是用level来表示的,只要之前加个level=3就好了。需要其他难度可以直接改变level值,或者用inputbox输入。

不过博主玩了一下,感觉3*3已经非常难了- -,哎,虽然玩了几遍找到一点技巧,感觉还不错,但是博主把level调成10以后,是这个样子的
4

啊,对这个游戏绝望了,这个可能拼起来嘛!!

结束

关于这个游戏的主要部分已经说完啦,该游戏源代码在博主的主页http://www.dawufan.cn/下载

1 0