推箱子小游戲

以前做的小游戲阔涉,很多地方不足也不做修改了,比較有趣捷绒,用到了一點(diǎn)算法瑰排,所以摘過來放在這兒

  • 和炸彈人游戲原理差不多,這個(gè)是在它之前寫的暖侨,圖上有游戲規(guī)則
  • 重點(diǎn)分析:根據(jù)深度優(yōu)先搜索算法椭住,得出人能否移動到指定的目標(biāo)點(diǎn)(可以找出最優(yōu)的路線,但無法有序的顯示出來故刪掉了)

下面展示全部代碼和部分注解

ViewController.m文件中

#define rowCount 10 
// 每一行個(gè)數(shù)@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>

@property(nonatomic,strong)UICollectionView *collectView;
@property(nonatomic,strong)NSMutableArray *dataArray;
@property(nonatomic)CGPoint point;// 箱子所在的坐標(biāo)位置    
@property(nonatomic)CGPoint personPoint;// 人所在的坐標(biāo)位置
@property(nonatomic)CGPoint endPoint; // 出口
@property(nonatomic)CGPoint startPoint; // 入口
@property(nonatomic,strong)NSMutableArray *allArray;// 記錄人經(jīng)過的路線所有信息@property(nonatomic)NSInteger success; // 判斷人是否走到了正確的路線上@end

ViewController.m文件中

@implementation ViewController

static NSString *const cellId = @"cellId";// collectView注冊時(shí)的標(biāo)識符

- (void)viewDidLoad {    
    [super viewDidLoad]
     // Do any additional setup after loading the view, typically from a nib.        

    [self layoutCollectionView];        // 游戲規(guī)則注釋
UILabel *explainLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, [UIScreen mainScreen].bounds.size.height - 150, [UIScreen mainScreen].bounds.size.width - 40, 100)];
  
    explainLabel.text = @"箱子推動的規(guī)則:\n點(diǎn)擊非墻非箱子的地方字逗,如果人可以移動過去則移動京郑;點(diǎn)擊箱子宅广,如果人在箱子四周的一位距離則把箱子向人的相反方向推去(那個(gè)方向非墻),人跟著移動一步些举,人和箱子距離在1位以上則沒法進(jìn)行";
    explainLabel.numberOfLines = 0;    [explainLabel setFont:[UIFont systemFontOfSize:12]];
    [self.view addSubview:explainLabel];
    [self.view bringSubviewToFront:explainLabel];        // 箱子起始坐標(biāo) {1跟狱,2},人的起始坐標(biāo){0金拒,2},出口是{9兽肤,7}    // 墻占位符為2,空地為0绪抛,箱子為3资铡,人為1   
    self.point = CGPointMake(1, 2);
    self.personPoint = CGPointMake(0, 2);
    self.startPoint = CGPointMake(0, 2);
    self.endPoint = CGPointMake(9, 7);} // 重新開始

- (IBAction)refreshBtn:(id)sender {// 拉控件
//    if (_personPoint.x != _startPoint.x || _personPoint.y != _startPoint.y ) {
//        // 避免連續(xù)點(diǎn)擊兩次刷新按鈕
//        [_dataArray replaceObjectAtIndex: _personPoint.y * 10 + _personPoint.x  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?/    }
//    if (_point.x != _startPoint.x + 1 || _point.y != _startPoint.y){
//        // 箱子有移動
//        [_dataArray replaceObjectAtIndex: _point.y * 10 + _point.x  withObject:@0];// 箱子曾經(jīng)的位置//    }//    
//    [_dataArray replaceObjectAtIndex: _startPoint.y * 10 + _startPoint.x  withObject:@1];// 人現(xiàn)在的位置
//    [_dataArray replaceObjectAtIndex: _startPoint.y * 10 + _startPoint.x + 1  withObject:@3];// 箱子現(xiàn)在的位置

//PS:開始想的太復(fù)雜導(dǎo)致思路錯(cuò)了走歪了,但邏輯還是經(jīng)得起推敲的    
self.dataArray = nil;// so easy   
 _point = CGPointMake(_startPoint.x + 1, _startPoint.y);    
_personPoint = _startPoint;// 任何箱子的點(diǎn)重新賦值

[self.collectView reloadData];
}

- (void)layoutCollectionView{    
if (!_collectView) {       
     
CustomViewFlowLayout *layout = [[CustomViewFlowLayout alloc]init];
        UICollectionView *collevtView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:layout];
        collevtView.backgroundColor = [UIColor whiteColor];
        collevtView.delegate = self;
        collevtView.dataSource = self;
        [self.view addSubview:collevtView];
        _collectView = collevtView;
                [_collectView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellId];// collectView注冊    }
}
// delegate和datasource方法
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{    
if (self.dataArray.count % rowCount == 0) {       
 return self.dataArray.count / rowCount;    
}else   
     return self.dataArray.count / rowCount + 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{    
return rowCount;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    
UICollectionViewCell *collectCell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];// 重用機(jī)制幢码,上面別忘了注冊
    NSInteger inter = (indexPath.section) * rowCount + indexPath.row;
        if ([self.dataArray[inter] isEqualToNumber:@2]) {      
  collectCell.backgroundColor = [UIColor blackColor];
    }   
 if ([self.dataArray[inter] isEqualToNumber:@0]) {        
collectCell.backgroundColor = [UIColor groupTableViewBackgroundColor];
    }   
 if (indexPath.row == self.point.x && indexPath.section == self.point.y) {        
collectCell.backgroundColor = [UIColor redColor];    
}// 代表箱子
    if ([self.dataArray[inter] isEqualToNumber:@1]) { 
       collectCell.backgroundColor = [UIColor greenColor];    
}// 代表人 
   return collectCell;
}
/* 箱子推動的規(guī)則:    點(diǎn)擊非墻非箱子的地方笤休,如果人可以移動過去則移動;     點(diǎn)擊箱子症副,如果人在箱子四周的一位距離則把箱子向人的相反方向推去(那個(gè)方向非墻)店雅,人跟著移動一步,人和箱子距離在1位以上則沒法進(jìn)行 */

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{    
NSIndexPath *path = [NSIndexPath indexPathForRow:_personPoint.x inSection:_personPoint.y];
        if (indexPath.row == self.point.x && indexPath.section == self.point.y) {        // 點(diǎn)擊了箱子
                if (indexPath.row - 1 == self.personPoint.x && indexPath.section == self.personPoint.y && [_dataArray[indexPath.section * rowCount + indexPath.row + 1] isEqualToNumber:@0]) {
            // 人在箱子左邊一位贞铣,人和箱子向右移動一位
            _personPoint = CGPointMake(indexPath.row, indexPath.section);
            _point = CGPointMake(indexPath.row + 1, indexPath.section);
                        NSInteger inter = indexPath.section * 10 + indexPath.row;
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter  withObject:@1];// 人現(xiàn)在的位置
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter - 1  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?            [_dataArray replaceObjectAtIndex: (NSUInteger)inter + 1  withObject:@3];// 箱子現(xiàn)在的位置
            [self.collectView reloadItemsAtIndexPaths:@[indexPath,path,
[NSIndexPath indexPathForRow:_point.x inSection:_point.y] ]]; 
           }       
 if (indexPath.row + 1 == self.personPoint.x && indexPath.section == self.personPoint.y &&  [_dataArray[indexPath.section * rowCount + indexPath.row - 1] isEqualToNumber:@0]) {    // 人在箱子右邊一位闹啦,人和箱子向左移動一位
            _personPoint = CGPointMake(indexPath.row, indexPath.section);
            _point = CGPointMake(indexPath.row - 1, indexPath.section);
     NSInteger inter = indexPath.section * 10 + indexPath.row;
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter  withObject:@1];// 人現(xiàn)在的位置
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter + 1  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?            [_dataArray replaceObjectAtIndex: (NSUInteger)inter - 1  withObject:@3];// 箱子現(xiàn)在的位置
            [self.collectView reloadItemsAtIndexPaths:@[indexPath,path,
[NSIndexPath indexPathForRow:_point.x inSection:_point.y] ]]; 
                   }        
if (indexPath.row  == self.personPoint.x && indexPath.section - 1 == self.personPoint.y &&  [_dataArray[(indexPath.section + 1) * rowCount + indexPath.row] isEqualToNumber:@0]) {    // 人在箱子上邊一位,人和箱子向下移動一位
            _personPoint = CGPointMake(indexPath.row, indexPath.section);
            _point = CGPointMake(indexPath.row , indexPath.section + 1);
           NSInteger inter = indexPath.section * 10 + indexPath.row;
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter withObject:@1];// 人現(xiàn)在的位置
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter - 10  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?            [_dataArray replaceObjectAtIndex: (NSUInteger)inter + 10  withObject:@3];// 箱子現(xiàn)在的位置
            [self.collectView reloadItemsAtIndexPaths:@[indexPath,path,
[NSIndexPath indexPathForRow:_point.x inSection:_point.y] ]];                    }   
     if (indexPath.row == self.personPoint.x && indexPath.section + 1 == self.personPoint.y && [_dataArray[(indexPath.section - 1) * rowCount + indexPath.row] isEqualToNumber:@0]) {            // 人在箱子下邊一位辕坝,人和箱子向上移動一位
            _personPoint = CGPointMake(indexPath.row, indexPath.section);
            _point = CGPointMake(indexPath.row, indexPath.section - 1);
                        NSInteger inter = indexPath.section * 10 + indexPath.row;
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter  withObject:@1];// 人現(xiàn)在的位置
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter + 10  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?            [_dataArray replaceObjectAtIndex: (NSUInteger)inter - 10  withObject:@3];// 箱子現(xiàn)在的位置
            [self.collectView reloadItemsAtIndexPaths:@[indexPath,path,
[NSIndexPath indexPathForRow:_point.x inSection:_point.y] ]]; 
                   }           
 }else if (_personPoint.x == indexPath.row && _personPoint.y == indexPath.section){        // 點(diǎn)了人自身窍奋,不做任何變化
            }else  if (
![_dataArray[(indexPath.section) * rowCount + indexPath.row] isEqualToNumber:@2]) {        // 點(diǎn)擊的地方不是墻且能夠有路線達(dá)到那兒(不一定是最優(yōu)方案--暫時(shí)先這樣)       
 [self.allArray removeAllObjects];        
self.success = 0;
        NSInteger success = [self judgeTwoPointRouteWithStartPiontX:(NSInteger)_personPoint.x y:(NSInteger)_personPoint.y endPointX:(indexPath.row) y:(indexPath.section)];
                if (success == 1) {         
   [self.dataArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {   
             if ([obj isEqualToNumber:@1]) {                 
   //                    [self.allArray addObject:obj];
//                    NSIndexPath *path1 = [NSIndexPath indexPathForRow:( idx / rowCount) inSection:(idx % rowCount) ];
                    //                    NSLog(@"= %@",obj);
//                    [self.collectView reloadItemsAtIndexPaths:@[path1]];
                    [_dataArray replaceObjectAtIndex: (NSUInteger)idx  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?               
}
            }];     
                   NSInteger inter = indexPath.section * 10 + indexPath.row;
            [_dataArray replaceObjectAtIndex: (NSUInteger)inter  withObject:@1];// 人現(xiàn)在的位置
            self.personPoint = CGPointMake(indexPath.row, indexPath.section);
            [self.collectView reloadItemsAtIndexPaths:@[indexPath,path]];
        }    
}    
if (_point.x == _endPoint.x && _point.y == _endPoint.y) {        NSLog(@"過關(guān)啦");
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"過關(guān)了" preferredStyle:(UIAlertControllerStyleAlert)];// 比alertView好用且齊全
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"確定" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
//            [_dataArray replaceObjectAtIndex: _startPoint.y * 10 + _startPoint.x  withObject:@1];// 人現(xiàn)在的位置
//            [_dataArray replaceObjectAtIndex: _personPoint.y * 10 + _personPoint.x  withObject:@0];// 人曾經(jīng)的位置變?yōu)榭盏?//            [_dataArray replaceObjectAtIndex: _startPoint.y * 10 + _startPoint.x + 1  withObject:@3];// 箱子現(xiàn)在的位置
//            [_dataArray replaceObjectAtIndex: _point.y * 10 + _point.x  withObject:@0];// 箱子曾經(jīng)的位置// 和重新按鈕 那一塊同理
            self.dataArray = nil;            
_point = CGPointMake(1, 2);
            _personPoint = CGPointMake(0, 2);
            [self.collectView reloadData];        
}];
        [alertController addAction:action];
        [self presentViewController:alertController animated:YES completion:nil];   
 }
    }// 輸入起始點(diǎn)和結(jié)束點(diǎn),判斷這兩點(diǎn)在地圖內(nèi)有沒有連通的路線酱畅?有幾條琳袄?

// 詳解可看上一篇文章(炸彈人游戲),只是將BOOL值替換成了nsinteger- (NSInteger )judgeTwoPointRouteWithStartPiontX:(NSInteger)startX y:(NSInteger)startY endPointX:(NSInteger)endX y:(NSInteger)endY{    NSInteger inter = startY * rowCount + startX;
    [_dataArray replaceObjectAtIndex: (NSUInteger)inter  withObject:@1];// 人走過的路線
        if (startX == endX && startY == endY) {    
    self.success = 1;        
//        for (int i = 0; i < _dataArray.count; i ++) {
//            if ([_dataArray[i] isEqualToNumber:@1]) {
//                // 記錄走過的每一個(gè)點(diǎn)
//                [self.allArray addObject:
[NSNumber numberWithInt:i]];//                //       
     }//      
  }    
}        // 上下左右四個(gè)方向是否能移動
    if (_success != 1 && [_dataArray[startX + (startY - 1) * rowCount] isEqualToNumber:@0]) {        
[self judgeTwoPointRouteWithStartPiontX:startX y:(startY - 1) endPointX:endX y:endY];
    }    
if (_success != 1 && [_dataArray[startX + (startY + 1) * rowCount] isEqualToNumber:@0]) {    
    [self judgeTwoPointRouteWithStartPiontX:startX y:(startY + 1) endPointX:endX y:endY];
    }   
 if (_success != 1 && [_dataArray[startX - 1 + (startY ) * rowCount] isEqualToNumber:@0]) {   
     [self judgeTwoPointRouteWithStartPiontX:(startX - 1) y:(startY) endPointX:endX y:endY];
    }   
 if (_success != 1 && [_dataArray[startX + 1 + (startY ) * rowCount] isEqualToNumber:@0]) {   
     [self judgeTwoPointRouteWithStartPiontX:(startX + 1) y:(startY) endPointX:endX y:endY];
    }   
 if (_success != 1) {   
     [_dataArray replaceObjectAtIndex: (NSUInteger)inter  withObject:@0]; 
   }   
 return _success;}

#pragram mark ----getter
- (NSMutableArray *)dataArray{   
 if (!_dataArray) {    
    _dataArray = [NSMutableArray arrayWithArray:@[@2,@2,@2,@2,@2,@2,@2,@2,@2,@2,  @2,@0,@0,@0,@0,@0,@0,@0,@0,@2,  @1,@3,@0,@2,@2,@0,@2,@2,@0,@2,  @2,@0,@0,@2,@0,@0,@2,@0,@0,@2,@2,@0,@0,@2,@0,@2,@0,@2,@0,@2,@2,@0,@0,@0,@0,@0,@0,@2,@0,@2,@2,@0,@0,@2,@2,@2,@0,@2,@2,@2,@2,@0,@0,@0,@0,@0,@0,@0,@0,@0,@2,@2,@2,@2,@2,@2,@2,@2,@2,@2] ];   
 }       
 return _dataArray;
}

- (NSMutableArray *)allArray{ 
   if (!_allArray) {   
     _allArray = [NSMutableArray arrayWithCapacity:20];  
  }
    return _allArray;
}

此工程先于炸彈人編寫纺酸,邏輯不如其嚴(yán)謹(jǐn)窖逗,可兩者結(jié)合比較,更好的理解

  • PS:文章排版有問題餐蔬,以前是富文本格式碎紊,現(xiàn)在轉(zhuǎn)換為markdown格式,改的頭疼
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末樊诺,一起剝皮案震驚了整個(gè)濱河市仗考,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啄骇,老刑警劉巖痴鳄,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘟斜,死亡現(xiàn)場離奇詭異缸夹,居然都是意外死亡痪寻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門虽惭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來橡类,“玉大人,你說我怎么就攤上這事芽唇」嘶” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵匆笤,是天一觀的道長研侣。 經(jīng)常有香客問我,道長炮捧,這世上最難降的妖魔是什么庶诡? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮咆课,結(jié)果婚禮上末誓,老公的妹妹穿的比我還像新娘。我一直安慰自己书蚪,他們只是感情好喇澡,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著殊校,像睡著了一般晴玖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上箩艺,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天窜醉,我揣著相機(jī)與錄音,去河邊找鬼艺谆。 笑死榨惰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的静汤。 我是一名探鬼主播琅催,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼虫给!你這毒婦竟也來了藤抡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤抹估,失蹤者是張志新(化名)和其女友劉穎缠黍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體药蜻,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓷式,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年替饿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贸典。...
    茶點(diǎn)故事閱讀 40,912評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡视卢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出廊驼,到底是詐尸還是另有隱情据过,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布妒挎,位于F島的核電站绳锅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏酝掩。R本人自食惡果不足惜榨呆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望庸队。 院中可真熱鬧积蜻,春花似錦、人聲如沸彻消。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宾尚。三九已至丙笋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間煌贴,已是汗流浹背御板。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牛郑,地道東北人怠肋。 一個(gè)月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像淹朋,于是被迫代替她去往敵國和親笙各。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容