你将如何构建像数独板一样的网格并与之交互?

问题描述 投票:7回答:7

您认为为本机iPhone应用程序实现类似于Sudoku板的交互式网格的最佳方式是什么?我没有在SDK中看到满足此需求的对象。

我应该为单个单元格进行自定义控制,然后在网格形式中根据需要初始化它们中的多个?

Sudoku grid (来源:4thewww.com

欢迎任何和所有评论。谢谢!

iphone objective-c cocoa-touch
7个回答
3
投票

对于这样一个完全统一的网格,我会创建一个UIView的子类,并使用一个简单的计算确定用户触摸了哪一行和一列:

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

当一个对象足够时,我没有看到在内存中创建81个单独对象的好处。


1
投票

我之前玩过数独游戏,我在一个视图中做了网格线和数字绘图。不是因为内存限制(使用单个控件和可重用的单元格内存不应该是一个问题),而是因为它只需要一些简单的数学来计算网格和数字的位置,并且编程视图将会一开始比较容易。如果稍后您开始对视图类中的绘图和事件处理代码量感到不知所措,您可能希望创建一个可重用的单元格对象来完成大部分工作,类似于UITableView。

如果你需要动画,核心动画肯定也会在这里工作。数独板可能没有太多动画,但如果你这样做(可能是一个滑动的“选择”框?)这可能是更好的选择。


1
投票

我一直使用this code (source: this blog)。这是制作网格的乐趣和不幸事件的一个很好的“入口”。我将这个算法与一个查看“所需”对象数和可用“帧”的算法相结合,并告诉我列/行的最佳数量。想模数.. 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];
}   }   }


1
投票

它非常简单。我使用gridView作为UiViewController类,并在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

这里的数独类是我的nsobject类和方法

+(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;}

希望有人觉得它有用.. :)


0
投票

网格是查看内容的一种手段,而不是存储表示的手段。最终,您的网格由具有内容的单元格组成,因此您的底层模型对象可能最好由单元格体现。有许多方法可以为Sudoku游戏设计底层存储,更大的挑战肯定在于谜题的产生。但是,从中获取的建议是不根据它在屏幕上的显示方式来确定你的模型 - 视图层是完全独立的,所以做一些事情,比如将电路板存储为二维数组,这是一个坏主意。


0
投票

您可以使用UIViews或CALayers作为主要超级视图的子视图。你需要至少81个(在Sudoku网格中每个数字一个)。图层重量更轻,资源更少,但视图功能更多。你选择哪个取决于你想要做什么。


0
投票

有一篇关于如何实现数独求解器的文章。我认为它使用了这样的数据结构:

  • 网格有81个单元格
  • 单元格有三个组成员身份:一列,一行和一个框
  • 一组有9个细胞(参考)

单元格具有更多属性,具体取决于您要对结构执行的操作:

  • 一个值
  • 一个hidden标志(用于游戏)
  • 一组可能的值(对于求解器)
© www.soinside.com 2019 - 2024. All rights reserved.