2015-01-21 3 views
1

Фон: Я создаю игру «kinda», как connect 4. У меня большая часть работы, единственная часть, за которой я застрял, теперь определяет, есть ли 5 ​​одинаковых цветов в ряд (слева, справа, вверх, вниз & диагонали)Поиск 5 в строке

Вопрос:

Как я могу получить код для цикла и посмотреть, если есть 5 штук в ряд с тем же цветом в любом направлении.

Примечание. Каждый ход воспроизводится путем перемещения одной части на доске на новое место и в нее входят 3 новых фигуры. Это означает, что он должен будет проверить соответствие 5 после поворота, а также после того, как 3 новых предмета случайно попадут на доску.

Спасибо!

Мой код для игры до сих пор есть ..

ViewController (.m)

#import "ViewController.h" 
#import "BoardCell.h" 
#import <QuartzCore/QuartzCore.h> 

@interface ViewController() 

@property (strong,nonatomic) NSArray *imageNames; 
@property (strong,nonatomic) NSMutableArray *board; 
@property NSInteger lastMove; 
#define BOARDWIDTH 9 
#define BOARDHEIGHT 9 

@end 

static int moves[]={-BOARDWIDTH,-1,1,BOARDWIDTH}; 
bool preSelect; 
BoardCell *startCell; 
@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
     // Do any additional setup after loading the view, typically from a nib. 
    preSelect = NO; 
    self.imageNames = @[@"marble_red",@"marble_blue",@"marble_purple",@"marble_orange",@"marble_green"]; 

    self.board = [NSMutableArray new]; 

    for (int y=0; y < BOARDWIDTH; y++) { 
     for (int x = 0; x < BOARDHEIGHT; x++) { 
      UIButton * button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
      button.frame = CGRectMake(5+ 35 * x, 100 + 35 * y, 30, 30); 
      button.tag = y*BOARDWIDTH+x; 
       //[button setTitle:[NSString stringWithFormat:@"%ld", button.tag] forState:UIControlStateNormal]; 
      button.selected = NO; 
      [button.layer setCornerRadius:15]; 
      [button setBackgroundColor:[UIColor colorWithWhite:.7 alpha:.5]]; 
      [button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
      [self.view addSubview: button]; 
      [self.board addObject:[[BoardCell alloc] initWithButton:button]]; 
     } 
    } 

    self.lastMove=arc4random_uniform(BOARDWIDTH*BOARDHEIGHT); 
    UIButton *button=(UIButton *)[self.view viewWithTag:self.lastMove]; 
    [button setBackgroundImage:[UIImage imageNamed:@"greensquare"] forState:UIControlStateNormal]; 

    [self addRandoms:3]; 


} 

-(void) addRandoms:(NSInteger)randomCount { 
    for (int i = 0; i < randomCount; i++) { 
     int space = arc4random_uniform(BOARDWIDTH*BOARDHEIGHT); 
     BoardCell *cell=self.board[space]; 
     if (!cell.occupied) { 
      int pic = arc4random_uniform((u_int32_t)self.imageNames.count); 
      NSString *string = [self.imageNames objectAtIndex:pic]; 
      NSString *highlighted = [NSString stringWithFormat:@"%@_highlighted",string]; 
      NSLog(@"HIGHLIGHTED = %@",highlighted); 
      [cell.button setBackgroundImage:[UIImage imageNamed:string] forState:UIControlStateNormal]; 
      [cell.button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; 
      [cell.button setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; 
      cell.button.selected = NO; 
      cell.occupied=YES; 
     } 
     else { 
      i--; 
     } 

    } 
} 

-(void)buttonPressed:(UIButton *)button 
{ 
    NSInteger buttonId=button.tag; 
    BoardCell *cell=self.board[buttonId]; 
    if (!preSelect) { 
     if (cell.occupied) { 
       //cell.button.selected = YES; 
      [[cell.button layer] setBorderWidth:3.5f]; 
      [cell.button.layer setBorderColor:[[UIColor colorWithWhite:.85 alpha:.7]CGColor]]; 
      cell.button.highlighted = YES; 
      preSelect = YES; 
      self.lastMove = buttonId; 
      startCell = cell; 
     }else{ 
     cell.button.selected = NO; 
      cell.button.highlighted = NO; 
      [cell.button.layer setBorderColor:[[UIColor clearColor]CGColor]]; 

     } 
    }else{ 
     NSLog(@"SECOND STEP"); 
     if (!cell.occupied) { 

      BoardCell *startCell=self.board[self.lastMove]; 
      startCell.occupied=NO; 
      if ([self validMoveFromSquare:self.lastMove toDestination:buttonId]) { 
       [cell.button setBackgroundImage:[startCell.button backgroundImageForState:UIControlStateNormal] 
forState:UIControlStateNormal]; 
       [startCell.button setBackgroundImage:[UIImage imageNamed:@""] forState:UIControlStateNormal]; 

       NSLog(@"FROM %ld, TO %ld",(long)self.lastMove,(long)buttonId); 
        cell.button.selected = NO; 
       cell.button.highlighted = NO; 
        startCell.button.selected = NO; 
       startCell.button.highlighted = NO; 
       self.lastMove=buttonId; 
       cell.occupied=YES; 
       preSelect = NO; 
       [self addRandoms:3]; 

      }else{ 
      startCell.occupied=YES; 
      preSelect = NO; 
      cell.button.selected = NO; 
      cell.button.highlighted = NO; 
        startCell.button.selected = NO; 
      startCell.button.highlighted = NO; 
      NSLog(@" INVALID FROM %ld, TO %ld",(long)self.lastMove,(long)buttonId); 
      } 
     } 
     preSelect = NO; 
     cell.button.selected = NO; 
     cell.button.highlighted = NO; 
     startCell.button.selected = NO; 
     startCell.button.highlighted = NO; 
     [cell.button.layer setBorderColor:[[UIColor clearColor]CGColor]]; 
     [startCell.button.layer setBorderColor:[[UIColor clearColor]CGColor]]; 


    } 

} 


-(BOOL) validMoveFromSquare:(NSInteger)startSquare toDestination:(NSInteger)destination { 

    for (int limit=1;limit<10;limit++) { 
     NSMutableIndexSet *visitList=[NSMutableIndexSet new]; 
     if ([self DFSFromStart:startSquare toGoal:destination withLimit:limit andVisitList:visitList]) { 
      return YES; 
     } 
    } 

    return NO; 

} 

-(BOOL) DFSFromStart:(NSInteger)start toGoal:(NSInteger)goal withLimit:(NSInteger)limit andVisitList:(NSMutableIndexSet *)visitList { 



    if (limit >=0) { 

     if (((BoardCell *)self.board[start]).occupied) { 
      NSLog(@"Self Board = %@",self.board[start]); 
      return NO; 
     } 

     [visitList addIndex:start]; 

     for (int i=0;i<4;i++) { 
      NSInteger nextPosition=start+moves[i]; 
      NSLog(@"Next spot = %ld",(long)nextPosition); 
      if (nextPosition == goal) { 
       return YES; 
      } 
      if (nextPosition >=0 && nextPosition < BOARDWIDTH*BOARDHEIGHT) { 
       if (![visitList containsIndex:nextPosition]) { 
        if ([self DFSFromStart:nextPosition toGoal:goal withLimit:limit-1 andVisitList:visitList]) { 
         return YES; 
        } 
       } 

      } 
     } 
    } 
    return NO; 

} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
     // Dispose of any resources that can be recreated. 
} 

BoardCell.m

#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 

@interface BoardCell : NSObject 


@property (weak,nonatomic,readonly) UIButton *button; 
@property BOOL occupied; 


-(id) initWithButton:(UIButton *)button; 

@end 

Еще раз спасибо!

ответ

2

Вы можете использовать рекурсивный алгоритм для работы в каждом из восьми направлений, пока не ударил границу или другой цвет -

-(void) clearRunsOfColor:(Colors)color fromPoint:(NSInteger)startPoint { 
    NSInteger left=[self runFromStart:startPoint-1 ofColor:color inDirection:-1]; 
    NSInteger right=[self runFromStart:startPoint+1 ofColor:color inDirection:1]; 
    BOOL cleared=NO; 
    if (left+right+1 >4) { 
     [self clearBoardFromStart:startPoint-1 inDirection:-1 forLength:left]; 
     [self clearBoardFromStart:startPoint+1 inDirection:1 forLength:right]; 
     cleared=YES; 
    } 

    NSInteger up=[self runFromStart:startPoint-BOARDWIDTH ofColor:color inDirection:-BOARDWIDTH]; 
    NSInteger down=[self runFromStart:startPoint+BOARDWIDTH ofColor:color inDirection:BOARDWIDTH]; 
    if (up+down+1 > 4) { 
     [self clearBoardFromStart:startPoint-BOARDWIDTH inDirection:-BOARDWIDTH forLength:up]; 
     [self clearBoardFromStart:startPoint+BOARDWIDTH inDirection:BOARDWIDTH forLength:down]; 
     cleared=YES; 
    } 

    NSInteger NW=[self runFromStart:startPoint-BOARDWIDTH-1 ofColor:color inDirection:-BOARDWIDTH-1]; 
    NSInteger SE=[self runFromStart:startPoint+BOARDWIDTH+1 ofColor:color inDirection:+BOARDWIDTH+1]; 

    if (NW+SE+1 > 4) { 
     [self clearBoardFromStart:startPoint-BOARDWIDTH-1 inDirection:-BOARDWIDTH-1 forLength:NW]; 
     [self clearBoardFromStart:startPoint+BOARDWIDTH+1 inDirection:BOARDWIDTH+1 forLength:SE]; 
     cleared=YES; 
    } 

    NSInteger NE=[self runFromStart:startPoint-BOARDWIDTH+1 ofColor:color inDirection:-BOARDWIDTH+1]; 
    NSInteger SW=[self runFromStart:startPoint+BOARDWIDTH-1 ofColor:color inDirection:+BOARDWIDTH-1]; 

    if (NE+SW+1 > 4) { 
     [self clearBoardFromStart:startPoint-BOARDWIDTH+1 inDirection:-BOARDWIDTH+1 forLength:NE]; 
     [self clearBoardFromStart:startPoint+BOARDWIDTH-1 inDirection:BOARDWIDTH-1 forLength:SW]; 
     cleared=YES; 
    } 

    if (cleared) { 
     [self occupyCell:startPoint withPiece:nil]; 
    } 
} 

-(void) clearBoardFromStart:(NSInteger)start inDirection:(NSInteger)direction forLength:(NSInteger) length { 
    NSInteger pos=start; 
    for (int i=0;i<length;i++) { 
     [self occupyCell:pos withPiece:nil]; 
     pos+=direction; 
    } 

} 

-(NSInteger) runFromStart:(NSInteger)start ofColor:(Colors)color inDirection:(NSInteger)direction { 
    if ([self inBounds:start]) { 
     BoardCell *thisCell=self.board[start]; 
     if (thisCell.gamepiece != nil && thisCell.gamepiece.color == color) { 
      if ([self validDestination:start+direction withMove:(int)direction fromSquare:start]) { 
       return ([self runFromStart:start+direction ofColor:color inDirection:direction]+1); 
      } 
      else { 
       return 1; 
      } 
     } 
    } 
    return 0; 
} 

-(BOOL) inBounds:(NSInteger) position { 
    if (position >=0 && position < BOARDHEIGHT*BOARDWIDTH) { 
     return YES; 
    } 
    else { 
     return NO; 
    } 
} 
+0

Работает отлично, за исключением того, что верхний левый угол не распознается как пространство. Так что если это 5 в ряд из левого верхнего угла, он не обнаружит 5 подряд.Может быть и с другими углами, но это тот, который я нашел до сих пор. Любая идея? – huddie96

+0

Была ошибка в методе 'inBounds' - это должно быть> = 0 – Paulw11

+0

Perfect thanks Again – huddie96

0

Ни один из приведенных ниже кодов не проверен на правильность.

Вы можете обновить свой BoardCell класс следующим образом:

typedef enum { 
    TopLeft, Top, TopRight, 
    Left,    Right, 
    BottomLeft, Bottom, BottomRight, 
    NumberOfDirections 
} BoardCellAdjacentDirection; 

@interface BoardCell 
- (void)addAdjacentCell:(BoardCell *)cell forDirection:(BoardCellAdjacentDirection)direction; 
- (NSInteger)occupiedCellsInDirection:(BoardCellAdjacentDirection)direction; 
@end 

@implementation BoardCell { 
    NSMutableArray *adjacentCells; 
} 
- (instancetype)init { 
    if (self = [super init]) { 
    adjacentCells = [[NSMutableArray alloc] init]; 
    for (NSInteger i = 0; i < (NSInteger)NumberOfDirections; i++) { 
     [adjacentCells addObject:[NSNull null]]; 
    } 
    } 
    return self; 
} 
- (void)addAdjacentCell:(BoardCell *)cell forDirection:(BoardCellAdjacentDirection)direction { 
    [adjacentCells setObject:cell atIndex:(NSInteger)direction]; 
} 
- (NSInteger)occupiedCellsInDirection:(BoardCellAdjacentDirection)direction { 
    if (!self.occupied) return 0; 
    if (adjacentCells[direction] == [NSNull null]) return 1; 
    return [adjacentCells[direction] occupiedCellsInDirection:direction]+1; 
} 
@end 

Везде, где вы создаете свои BoardCell объекты, вам нужно добавить соответствующие соседние ячейки. Вы также, вероятно, захотите провести несколько проверок здравомыслия, чтобы убедиться, что смежность соты - это двусторонняя связь (т. Е. Ячейка A находится слева от B и B справа смежна с A).

Редактировать Возможно, вы также захотите добавить метод, чтобы определить, введен ли ячейка в центр линии.

typedef enum { 
    BackSlash, 
    ForwardSlash, 
    Vertical, 
    Horizontal 
} BoardCellAxis; 

... 

- (NSInteger)occupiedCellsOnAxis:(BoardCellAxis)axis { 
    switch (axis) { 
    case BackSlash: 
    return MAX(0, [self occupiedCellsInDirection:TopLeft] 
        + [self occupiedCellsInDirection:BottomRight] 
        - 1); // Don't count yourself twice. 
    case ForwardSlash: 
    return MAX(0, [self occupiedCellsInDirection:TopRight] 
        + [self occupiedCellsInDirection:BottomLeft] 
        - 1); // Don't count yourself twice. 
    case Vertical: 
    return MAX(0, [self occupiedCellsInDirection:Top] 
        + [self occupiedCellsInDirection:Bottom] 
        - 1); // Don't count yourself twice. 
    case Horizontal: 
    return MAX(0, [self occupiedCellsInDirection:Left] 
        + [self occupiedCellsInDirection:Right] 
        - 1); // Don't count yourself twice. 
    } 
} 
+0

Im еще начинающий Xcode, так что я мог бы задавать глупые вопросы, но делает проверьте, что части рядом с движением, которые вы перемещаете, имеют один и тот же цвет или просто занимают эти пробелы? Также мне нужно поместить любой код в свой контроллер просмотра? Благодаря! – huddie96

+0

Это только проверяет, заняты ли они. Вам нужно будет изменить 'busyCellsInDirection', чтобы он соответствовал определенному цвету. Поскольку это связано с данными, ваш цвет должен храниться как часть вашего BoardCell. Вам нужно будет выполнить 'busyCellsInDirection:' где бы вы ни хотели знать, сколько ячеек занято в определенном направлении, начиная с определенного «BoardCell». Если это в вашем контроллере просмотра, то да, вам нужно будет поместить код в контроллер вашего вида. –

+0

Мне жаль, что я действительно не понимаю, как это работает или как его реализовать так, как мне нужно. Если вы объясните, что больше id будет очень благодарен, так как это ключевая часть моего приложения, в противном случае спасибо вам. – huddie96