您认为为本机iPhone应用程序实现类似于Sudoku板的交互式网格的最佳方式是什么?我没有在SDK中看到满足此需求的对象。
我应该为单个单元格进行自定义控制,然后在网格形式中根据需要初始化它们中的多个?
(来源:4thewww.com)
欢迎任何和所有评论。谢谢!
对于这样一个完全统一的网格,我会创建一个UIView
的子类,并使用一个简单的计算确定用户触摸了哪一行和一列:
int touchedRow = 9 * touch.x / [self bounds].width; int touchedCol = 9 * touch.y / [self bounds].width;
当一个对象足够时,我没有看到在内存中创建81个单独对象的好处。
我之前玩过数独游戏,我在一个视图中做了网格线和数字绘图。不是因为内存限制(使用单个控件和可重用的单元格内存不应该是一个问题),而是因为它只需要一些简单的数学来计算网格和数字的位置,并且编程视图将会一开始比较容易。如果稍后您开始对视图类中的绘图和事件处理代码量感到不知所措,您可能希望创建一个可重用的单元格对象来完成大部分工作,类似于UITableView。
如果你需要动画,核心动画肯定也会在这里工作。数独板可能没有太多动画,但如果你这样做(可能是一个滑动的“选择”框?)这可能是更好的选择。
我一直使用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];
} } }
它非常简单。我使用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;}
希望有人觉得它有用.. :)
网格是查看内容的一种手段,而不是存储表示的手段。最终,您的网格由具有内容的单元格组成,因此您的底层模型对象可能最好由单元格体现。有许多方法可以为Sudoku游戏设计底层存储,更大的挑战肯定在于谜题的产生。但是,从中获取的建议是不根据它在屏幕上的显示方式来确定你的模型 - 视图层是完全独立的,所以做一些事情,比如将电路板存储为二维数组,这是一个坏主意。
您可以使用UIViews或CALayers作为主要超级视图的子视图。你需要至少81个(在Sudoku网格中每个数字一个)。图层重量更轻,资源更少,但视图功能更多。你选择哪个取决于你想要做什么。
有一篇关于如何实现数独求解器的文章。我认为它使用了这样的数据结构:
单元格具有更多属性,具体取决于您要对结构执行的操作:
hidden
标志(用于游戏)