7

What do you think is the best way to implement an interactive grid similar to a Sudoku board for a native iPhone application? I did not see an object to fill this need in the SDK.

Should I make a custom control for an individual cell, then initialize as many of them as I need in a grid form?

Sudoku grid
(source: 4thewww.com)

Any and all comments are welcome. Thanks!

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
JWD
  • 12,188
  • 3
  • 34
  • 32
  • Hi, I too need the grid with interactive objects in it. I should be able to move the objects from one place to another like chess game. And, when I touch the object a path should be shown with another color . So, I think I need the openGl and coreGraphics for this. Or should I use cocos2d for this, Thank You. – srikanth rongali May 31 '10 at 12:04
  • Which one did you find useful? I also need one! – Dinesh Jan 26 '14 at 18:29

7 Answers7

3

For such a completely uniform grid, I would create a subclass of UIView and have it determine which row and column the user has touched using a simple calculation:

int touchedRow = 9 * touch.x / [self bounds].width;
int touchedCol = 9 * touch.y / [self bounds].width;

I don't see much benefit in creating 81 individual objects in memory, when one object would suffice.

e.James
  • 116,942
  • 41
  • 177
  • 214
  • This is the good answer but i can't get the idea how i can implement with all those gray and black borders + zooming functionality on selection of a section..! check my post below for more details what i want to do.. Thanks.! – Paresh Thakor May 23 '10 at 05:37
1

I use this code (source: this blog) ALL the time. It is a great "entry" into the fun and misadventures of making grids. I couple this with an algorithm that looks at the number of objects "desired" and the available "frame", and tells me the best number of columns / rows. Think modulo.. int % int

- (void)awakeFromNib {
    self.wantsLayer = YES;
    CALayer *grid = self.layer;
    grid.backgroundColor = CGColorCreateGenericRGB(0.1, 0.1, 0.4, .8);
    grid.layoutManager = [CAConstraintLayoutManager layoutManager];   
    int rows = 8;    int columns = 8;
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < columns; c++) {
            CALayer *cell = [CALayer layer];
            cell.borderColor = CGColorCreateGenericGray(0.8, 0.8);
            cell.borderWidth = 1;  cell.cornerRadius = 4;
            cell.name = [NSString stringWithFormat:@"%u@%u", c, r];
            [cell addConstraint:
            [CAConstraint constraintWithAttribute: kCAConstraintWidth
                relativeTo: @"superlayer"
                attribute: kCAConstraintWidth
                scale: 1.0 / columns  offset: 0]];
            [cell addConstraint:
            [CAConstraint constraintWithAttribute: kCAConstraintHeight
                relativeTo: @"superlayer"
                attribute: kCAConstraintHeight
                scale: 1.0 / rows   offset: 0]];
            [cell addConstraint:
            [CAConstraint constraintWithAttribute: kCAConstraintMinX
                relativeTo: @"superlayer"
                attribute: kCAConstraintMaxX
                scale: c / (float)columns   offset: 0]];
            [cell addConstraint:
            [CAConstraint constraintWithAttribute: kCAConstraintMinY
                relativeTo: @"superlayer"
                attribute: kCAConstraintMaxY
                scale: r / (float)rows    offset: 0]];
        [grid addSublayer:cell];
}   }   }

enter image description here

Alex Gray
  • 16,007
  • 9
  • 96
  • 118
  • but what if you have to resize your view? To make a GridView based on the width and height isn't something too hard. But if your view gets bigger, and you have always to calculate everything it will start laging. – Alex Cio Mar 13 '14 at 10:29
  • There's no slowdown at all, IF you just take the extra care to disable resizing "implicit animations" on the "grid" and the "cells" by setting each layer's "actions" dictionary with something like `@{@"bounds": NSNull.null, @"position": NSNull.null}`. – Alex Gray Mar 18 '14 at 01:15
  • I don't really understand the way you would solve the problem. Look I have opened a post based on this problem http://stackoverflow.com/questions/22358563/scroll-on-a-two-dimensional-uicollectionview-with-uipinchgesture – Alex Cio Mar 18 '14 at 12:03
1

Its very Simple.I use gridView as a UiViewController class and add the following code in gridView.m

#import "SudokuClass.h"
#import "GridView.h"

@interface GridView ()

@end

@implementation GridView


-(void)createNumberButton {

    int cellWidth = 34;
    int cellHeight = 34;
    int xSta = 7 - cellWidth;
    int ySta = 50 - cellHeight;
    //NSMutableDictionary *buttonTable = [[NSMutableDictionary alloc] initWithCapacity:81];
    for (int i = 1; i < 10; i++) {
        xSta = xSta + cellWidth;
        for (int j = 1 ; j < 10; j++) {
            ySta = ySta + cellHeight;
            CGRect pos = CGRectMake(xSta, ySta, cellWidth, cellHeight);
            UIButton *b = [SudokuClass createSudokuButtonForView:self atPos:pos 
                                                           withTag:j*10+i forAction:@selector(numButtonPressed:)];
            NSString *picName = @"ButtonPic.jpg";
            [b setBackgroundImage:[[UIImage imageNamed:picName] stretchableImageWithLeftCapWidth:0 topCapHeight:0]  forState:0];
            [self.view addSubview:b];
            //[numButtons addObject:b];
        }
        ySta = 50 - cellHeight;
    }}
-(void)viewDidLoad
{

    [self createNumberButton];
    [super viewDidLoad];
}
@end

here sudoku class is my nsobject class with method

+(UIButton *)createSudokuButtonForView:(UIViewController *)view atPos:(CGRect)position withTag:(int)tag forAction:(SEL)action {
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setFrame:position];
[b.titleLabel setFont:[UIFont boldSystemFontOfSize:15]];
[b setTag:tag];
[b addTarget:view action:action forControlEvents:UIControlEventTouchDown];
[b setTitle:@"" forState:0];
[b setTitleColor:[UIColor blackColor] forState:0];
//b.layer.frame = CGRectMake(xSta-1, ySta-1, 31, 31);
//[b.layer setBorderWidth:borderWidth];


b.userInteractionEnabled = YES;
return b;}

hope anyone find it useful..:)

andrewsi
  • 10,807
  • 132
  • 35
  • 51
Himanshu Gupta
  • 207
  • 1
  • 6
1

I've fooled around with a Sudoku game before and I did the gridlines and number drawing in a single view. Not because of memory constraints (using a single control and a reusable cell memory shouldn't be much of a concern) but because it only takes some simple math to figure out the locations of the grid and numbers, and programming a view is going to be easier at first. If later on down the road you start to feel overwhelmed with the amount of drawing and event handling code in your view class, you might want to make a reusable cell object that does much of the work, similar to UITableView.

Core animation would certainly work here too, if you need animation or not. A Sudoku board probably wouldn't have much animation, but if you do (maybe a sliding 'selection' box?) this might be the better choice.

Marc Charbonneau
  • 40,399
  • 3
  • 75
  • 82
  • Yess.....! We need to add the sliding and zooming functionality on the grid.. could you unveil how i can do this? Please help me out..! I had used n x n uiimageviews for such functions, but when i zoom, autoresize is not working fine, some of the images get stretched... and also, the animation is slow...! by the way, i'd put the grid construction logic in ViewDidLoad() so, navigation's push animation is also not well, Do i need to use OpenGL..? Please help me out of the grid..! – Paresh Thakor May 23 '10 at 05:43
  • please check my post below..! – Paresh Thakor May 23 '10 at 05:44
0

The grid is a means of viewing contents, not of storing the representation. Ultimately, your grid is made of cells which have contents and therefor your underlying model object is perhaps best embodied by the cell. There are a number of ways to design the underlying storage for a Sudoku game and the bigger challenge will certainly lie in the generation of puzzles. However, the advice to take from this is to not determine your model based on how it appears on screen - the view layer is totally separate and so doing something like storing the board a a two-dimensional array would be a bad idea.

wisequark
  • 3,288
  • 20
  • 12
0

You can do this with either UIViews or CALayers as subviews of the main superview. You'll need at least 81 of them (one for each number in the Sudoku grid). Layers are lighter weight and less resource intensive, but views have a little more functionality. Which you choose depends on what you're trying to do.

August
  • 12,139
  • 3
  • 29
  • 30
0

There was an article somewhere about how to implement a Sudoku solver. I think that it used a data structure like this:

  • a grid has 81 cells
  • a cell has three group memberships: one column, one row, and one box
  • a group has 9 cells (references)

A cell has some more properties, depending on what you want to do with the structure:

  • a value
  • a hidden flag (for a game)
  • a set of possible values (for a solver)
Svante
  • 50,694
  • 11
  • 78
  • 122
  • This is the reasonable answer i think but i don't know how to leverage UITableViewCell for sudoku grid + zooming functionality i need to add.. Please check my post below for more details and if any answer lemme know.. Thanks..! – Paresh Thakor May 23 '10 at 05:39