2小时完成HTML5拼图小游戏

澳门新葡亰赌995577 5

初学lufylegend.js之日,我用lufylegend.js开发了第一个HTML5小游戏——拼图游戏,还写了篇博文来炫耀一下:HTML5小游戏《智力大拼图》发布,挑战你的思维风暴。不过当时初学游戏开发,经验浅薄,所以没有好好专研游戏里的算法和代码的缺陷,导致游戏出现了很多bug,甚至拼图打乱后很可能无法复原。最近经常有朋友问起这个游戏,希望我能把代码里的bug改一下方便初学者学习,顺便我也打算测试一下自己写这种小游戏的速度,所以就抽出了一些时间将这个游戏从头到尾重新写了一遍,计算了一下用时,从准备、修改素材到最后完成游戏,一共用了大约2h的时间。

效果图&DEMO

以下是游戏地址:

澳门新葡亰赌995577 1

效果图

这是我的游戏记录,欢迎各位挑战:

一、准备工作

先了解一个定义和定理

定义:在一个1,2,…,n的排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。——这是北大《高等代数》上的定义。

定理:交换一个排列中的两个数,则排列的奇偶性发生改变。

澳门新葡亰赌995577 2

二、实现过程

以3*3拼图为例进行分析

接下来就来讲讲如何开发完成这款游戏的。(按“编年体”)

1、随机打乱拼图

1)初始化从0-8的数组initializeNums

NSMutableArray *initializeNums = [NSMutableArray array];//初始化0-n数字
for (int i = 0; i < _puzzleCount; i++) {
    [initializeNums addObject:@(i)];
}

2)从initializeNums随机抽取数字add到数组randomNums,得到随机数组

NSMutableArray *randomNums = [NSMutableArray array];//随机数组
for (int i = 0; i < _puzzleCount; i++) {   
    int randomNum = arc4random() % initializeNums.count;
    [randomNums addObject:initializeNums[randomNum]];
    [initializeNums removeObjectAtIndex:randomNum];   
}

3)判断拼图是否可还原

图1,通过移动要还原到的拼图状态
图2,随机打乱的拼图状态

图3,将图2中的空白块移动到拼图右下角的拼图状态,用来计算打乱的拼图是否可以还原
④ 空白块处相当于数字8

我们的目的是把打乱拼图如图2通过移动(空白块与相邻数字块位置交换)还原到图1状态

不是每个随机打乱的拼图都能还原到图1状态(根据定义定理有50%概率随机打乱的拼图不能还原)
⑦ 根据定义定理
图1的逆序数为0,为偶排列。所以只有图3也为偶排列,图2才有可能还原到图1状态

澳门新葡亰赌995577 3

图1

澳门新葡亰赌995577 4

图2

如何计算图3的逆序数

① 先计算图2的逆序数
② 再计算图2澳门新葡亰赌995577,到图3变换步数
③ 将两者相加即得图3逆序数

澳门新葡亰赌995577 5

图3

判断图2是否可还原代码:

//判断是否可还原拼图
inverCount = 0;
int curNum = 0;
int nextNum = 0;
for (int i = 0; i < _puzzleCount; i++) {
    curNum = [randomNums[i] intValue];
    if (curNum == _puzzleCount - 1) {
        inverCount += _difficulty - 1 - (i / _difficulty);
        inverCount += _difficulty - 1 - (i % _difficulty);
    }
    for (int j = i + 1; j < _puzzleCount; j++) {
        nextNum = [randomNums[j] intValue];
        if (curNum > nextNum) {
            inverCount++;
        }
    }

}
if (!(inverCount % 2)) {//对2求余,余0,逆序数为偶数,即偶排列;否则,为奇排列
    return randomNums;
}

获得随机可还原的数组randomNums

- (NSMutableArray *)getNewAvailableRandomNums {

    //随机数字
    int inverCount = 0;
    while (1) {
        NSMutableArray *initializeNums = [NSMutableArray array];//初始化0-n数字
        for (int i = 0; i < _puzzleCount; i++) {
            [initializeNums addObject:@(i)];
        }

        NSMutableArray *randomNums = [NSMutableArray array];//随机数组
        for (int i = 0; i < _puzzleCount; i++) {

            int randomNum = arc4random() % initializeNums.count;

            [randomNums addObject:initializeNums[randomNum]];

            [initializeNums removeObjectAtIndex:randomNum];

        }
        //判断是否可还原拼图
        inverCount = 0;
        int curNum = 0;
        int nextNum = 0;
        for (int i = 0; i < _puzzleCount; i++) {
            curNum = [randomNums[i] intValue];
            if (curNum == _puzzleCount - 1) {
                inverCount += _difficulty - 1 - (i / _difficulty);
                inverCount += _difficulty - 1 - (i % _difficulty);
            }
            for (int j = i + 1; j < _puzzleCount; j++) {
                nextNum = [randomNums[j] intValue];
                if (curNum > nextNum) {
                    inverCount++;
                }
            }

        }
        if (!(inverCount % 2)) {//对2求余,余0,逆序数为偶数,即偶排列;否则,为奇排列
            return randomNums;
        }

    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图