【300行小游戏】二、扫雷

废话不多说了。

二,推箱子

首先,仍然需要明确自己要做什么?做到什么程度?

1、扫雷的重要元素:有雷的格子,没雷的格子,小红旗(用于确认雷,但是手机没有右键一说,懒得整得很复杂,抛弃小红旗)

2、成功条件:除有雷的格子外,其他格子全部被翻开

3、失败条件:翻开有雷的格子

4、其他细节:地图的大小(同上个游戏),点击无雷格子的事件(若周围有雷,显示周围雷数;若周围没累,自动翻开周围格子,直至有雷),点击有雷格子事件(亮出所有雷的位置,报告失败,如果是第一次就点击到了有雷的格子,则重新埋雷后自动翻开格子,直至第一次非雷)等

开始。(笔者再次声明:本人没做过游戏,这个只是写来自己玩的,如有误导,纯属坑爹)

惯例先贴出笔者自定义的常量和枚举类型,看面看不懂的可以回过头看看

#define kCount_Grid 9    //地图大小-小于10
#define kColor_Mine [UIColor clearColor]
#define kColor_Safe [UIColor grayColor]
#define kColor_Normal [UIColor brownColor]

笔者的习惯是首先把地图绘制出來:

-(void)initMap
{
    if (vMap) {
        [vMap removeFromSuperview];
    }
    CGRect frame = self.view.frame;
    CGFloat width_Grid = frame.size.width/kCount_Grid;
    vMap = [[UIView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.width)];
    [vMap setCenter:CGPointMake(frame.size.width/2, frame.size.height/2)];
    [self.view addSubview:vMap];
    for (int i=1; i<kCount_Grid+1; i++) {
        for (int j=1; j<kCount_Grid+1; j++) {
            UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake((i-1)*width_Grid, (j-1)*width_Grid, width_Grid, width_Grid)];
            btn.layer.borderWidth = 1;
            btn.layer.borderColor = [[UIColor lightGrayColor]CGColor];
            [btn setBackgroundColor:kColor_Normal];
            [btn setTag:i+j*10];
            [btn addTarget:self action:@selector(findSafe:) forControlEvents:UIControlEventTouchUpInside];
            [vMap addSubview:btn];
        }
    }
}

由于都是方格游戏,所以笔者采用了上一个游戏的绘制方法,不多说。

然后我们来是埋雷

-(void)initMine
{
    for (int i=0; i<countMine; i++) {
        UIButton *btn = [self randomPoint];
        btn = [self checkRepeat:btn];
        [btn removeTarget:self action:@selector(findSafe:) forControlEvents:UIControlEventTouchUpInside];
        [btn addTarget:self action:@selector(findMine:) forControlEvents:UIControlEventTouchUpInside];
        [arrMine addObject:btn];
    }
}

由于雷的位置是随机的,所以必须的一件事仍然是查重

-(UIButton *)checkRepeat:(UIButton*)btn
{
    if ([arrMine containsObject:btn]) {
        btn = [self randomPoint];
        return [self checkRepeat:btn];
    }else{
        return btn;
    }
}

-(UIButton *)randomPoint
{
    int x = arc4random()%kCount_Grid;
    int y = arc4random()%kCount_Grid;
    x++;
    y++;
    return (UIButton *)[vMap viewWithTag:(x+y*10)];
}

埋完雷游戏就算初始化完了,接下来是游戏过程。

当我们点击一个格子的时候,如果是安全的,那么

-(void)isSafe:(UIButton *)btn
{
    if ([btn isKindOfClass:[UIButton class]] == NO || [btn isSelected] == YES) {
        return;
    }
    [btn setSelected:YES];
    countSafe++;
    if (countMine+countSafe == kCount_Grid*kCount_Grid) {
        NSLog(@"Success");
        [self alertSetSucceed];
    }
    [btn setBackgroundColor:kColor_Safe];
    int tag = btn.tag;
    int x = tag%10;
    int y = tag/10;
    NSMutableArray *nearGrid = [NSMutableArray new];

    UIButton *btn1 = (UIButton *)[vMap viewWithTag:(x-1)+(y-1)*10];
    UIButton *btn2 = (UIButton *)[vMap viewWithTag:x+(y-1)*10];
    UIButton *btn3 = (UIButton *)[vMap viewWithTag:(x+1)+(y-1)*10];
    UIButton *btn4 = (UIButton *)[vMap viewWithTag:(x-1)+y*10];
    UIButton *btn5 = (UIButton *)[vMap viewWithTag:(x+1)+y*10];
    UIButton *btn6 = (UIButton *)[vMap viewWithTag:(x-1)+(y+1)*10];
    UIButton *btn7 = (UIButton *)[vMap viewWithTag:x+(y+1)*10];
    UIButton *btn8 = (UIButton *)[vMap viewWithTag:(x+1)+(y+1)*10];
    (btn1) ? ([nearGrid addObject:btn1]):(nil);
    (btn2) ? ([nearGrid addObject:btn2]):(nil);
    (btn3) ? ([nearGrid addObject:btn3]):(nil);
    (btn4) ? ([nearGrid addObject:btn4]):(nil);
    (btn5) ? ([nearGrid addObject:btn5]):(nil);
    (btn6) ? ([nearGrid addObject:btn6]):(nil);
    (btn7) ? ([nearGrid addObject:btn7]):(nil);
    (btn8) ? ([nearGrid addObject:btn8]):(nil);
    int i = [self getNearMineCount:nearGrid];
    if (i != 0) {
        NSString *count = [NSString stringWithFormat:@"%d",i];
        [btn setTitle:count forState:UIControlStateNormal];
    }else{
        [self isSafe:btn1];
        [self isSafe:btn2];
        [self isSafe:btn3];
        [self isSafe:btn4];
        [self isSafe:btn5];
        [self isSafe:btn6];
        [self isSafe:btn7];
        [self isSafe:btn8];
    }
}

Selected是一个标识,表明这个格子被检查过了没。如果安全,再检查周围8个格子,如果有雷,则注明雷数。如果无雷,就依次检查周围的8个按钮是否有雷。注意边界检查。

检查雷数的方法:

-(int)getNearMineCount:(NSMutableArray *)nearGrid
{
    int count = 0;
    for (int i=0; i<[nearGrid count]; i++) {
        UIButton *btn = nearGrid[i];
        if (!btn) {
            break;
        }
        if ([arrMine containsObject:btn]) {
            count++;
        }
    }
    return count;
}

如果点击的格子是雷,那直接把所有的雷区都标明出来,再提示一个失败就好了。

理论上是,但是:

有例外,按照和谐的、友好的、通常的玩法,点击的第一个格子无论如何不能是雷的。如果第一次就踩shit点到雷了呢?笔者的做法是把雷重埋一次,再自动去翻点击的格子,还是雷就再埋,直至不是雷为止。

-(void)findMine:(UIButton *)btn
{
    if (countSafe == 0) {
        [self reStart];
        btn = (UIButton *)[vMap viewWithTag:btn.tag];
        if ([arrMine containsObject:btn]) {
            [self findMine:btn];
        }else{
            [self findSafe:btn];
        }
        return;
    }
    for (int i=0; i<[arrMine count]; i++) {
        UIButton *mine = arrMine[i];
        [self isMine:mine];
    }
    [self alertSetFailed];
}
-(void)isMine:(UIButton *)btn
{
    [btn setBackgroundColor:kColor_Mine];
    [btn setTitle:@"💢" forState:UIControlStateNormal];
}

再然后呢、扫雷基本上也没啥可做的了。当然还有一些细节我没说,比如成功或者失败后格子就不能再翻啦,比如雷设置时的数量啦等等,虽没说,但都做了。有兴趣的可以自己下载来看看。

ok,扫雷,竣工。

完整代码下载:Demo

 

posted @ 2014-04-16 15:47  John.Lv  阅读(298)  评论(0编辑  收藏  举报