绘制圆圈给定区域内的命中 - 设置变得臃肿的代码

时间:2013-12-21 15:41:57

标签: objective-c class optimization syntax nsmutablearray

[user1118321给出的替代方法,列出了新旧代码供参考]

我正在忙着写一个小应用程序,它可以让飞镖501游戏得分。我已经设置了一个类来包含各个得分区域(GDSBoardArea)和一个可变数组,它代表整个飞镖板并保存所有单独的得分类实例。

我已经编写了一个部分的代码(20分,内部和外部,三重和双重20),但我遇到的问题是,这个代码相当臃肿,如果有更好的方法可以使用所有区域都有更少,更可管理的代码,因为我将不得不在其他部分再重复19次以上?

我有一个类,它包含各个区域的设置,一个类用于保存所有这些区域和辅助函数。

我确实试图重用CGPoints和区域数组,但这只会导致我认为与更新引用有关的问题,因为scoringAreas addObject不会复制数组对象(如果我错了请纠正我)。

当应用程序使用 createAreas 函数运行时,我设置了一次评分区域,我似乎无法重用CGPoints和包含它们的数组。

我的问题是

1 - 有没有办法将CGPoints的变量数组传递给“GDSBoardArea”的最后一个参数,而不必创建CGPoints,将它们添加到数组中并传入数组。

2 - mutable数组方法addobject复制或引用传递给它的对象吗?是否有任何方法可以更新数组,然后将其复制到“主”可变数组,以便主数组有效地在每个元素中保存不同的数组。我基本上试图避免为每个主数组元素创建一个新数组。

createAreas

-(void)createAreas
{
scoringAreas = [[NSMutableArray alloc] init];

/*
    20 scoring section
*/

// 20 score - Inner triangle area
/////////////////////////////////////////

// Set up CGPoints for area
CGPoint pt_inner20_1 = CGPointMake(368.0f, 234.0f);
CGPoint pt_inner20_2 = CGPointMake(413.0f, 234.0f);
CGPoint pt_inner20_3 = CGPointMake(389.0f, 360.0f);

// Add points to array for passing to GDSBoardArea Class
NSMutableArray * areaPointsArray_Inner20 = [NSMutableArray array];
[areaPointsArray_Inner20 addObject:[NSValue valueWithCGPoint:pt_inner20_1]];
[areaPointsArray_Inner20 addObject:[NSValue valueWithCGPoint:pt_inner20_2]];
[areaPointsArray_Inner20 addObject:[NSValue valueWithCGPoint:pt_inner20_3]];

// Create GDSBoardArea Instance with init values
GDSBoardArea *scoreAreaFor_Inner20 = [[GDSBoardArea alloc] initWithName:@"20-Inner" abbrev:@"20" areaValue:20 pointsArray:NULL];

// Add Array of CGPoints to GDSScoreArea
[scoreAreaFor_Inner20 setPointsForPath:areaPointsArray_Inner20];

// Add ScoreArea to ScoreAreas Class
[scoringAreas addObject:scoreAreaFor_Inner20];

// 20 score - Outer Quadrilateral
/////////////////////////////////////////
CGPoint pt_outer20_1 = CGPointMake(353.0f, 125.0f);
CGPoint pt_outer20_2 = CGPointMake(429.0f, 127.0f);
CGPoint pt_outer20_3 = CGPointMake(415.0f, 208.0f);
CGPoint pt_outer20_4 = CGPointMake(365.0f, 209.0f);

NSMutableArray * areaPointsArray_Outer20 = [NSMutableArray array];
[areaPointsArray_Outer20 addObject:[NSValue valueWithCGPoint:pt_outer20_1]];
[areaPointsArray_Outer20 addObject:[NSValue valueWithCGPoint:pt_outer20_2]];
[areaPointsArray_Outer20 addObject:[NSValue valueWithCGPoint:pt_outer20_3]];
[areaPointsArray_Outer20 addObject:[NSValue valueWithCGPoint:pt_outer20_4]];

GDSBoardArea *scoreAreaFor_Outer20 = [[GDSBoardArea alloc] initWithName:@"20-Outer" abbrev:@"20" areaValue:20 pointsArray:NULL];
[scoreAreaFor_Outer20 setPointsForPath:areaPointsArray_Outer20];
[scoringAreas addObject:scoreAreaFor_Outer20];

// Double 20 Quadrilateral
/////////////////////////////////////////

CGPoint pt_d20_1 = CGPointMake(351.0f, 102.0f);
CGPoint pt_d20_2 = CGPointMake(353.0f, 118.0f);
CGPoint pt_d20_3 = CGPointMake(430.0f, 119.0f);
CGPoint pt_d20_4 = CGPointMake(433.0f, 104.0f);

NSMutableArray * areaPointsArray_Double20 = [NSMutableArray array];
[areaPointsArray_Double20 addObject:[NSValue valueWithCGPoint:pt_d20_1]];
[areaPointsArray_Double20 addObject:[NSValue valueWithCGPoint:pt_d20_2]];
[areaPointsArray_Double20 addObject:[NSValue valueWithCGPoint:pt_d20_3]];
[areaPointsArray_Double20 addObject:[NSValue valueWithCGPoint:pt_d20_4]];

GDSBoardArea *scoreAreaFor_double20 = [[GDSBoardArea alloc] initWithName:@"20-Double" abbrev:@"d20" areaValue:40 pointsArray:NULL];
[scoreAreaFor_double20 setPointsForPath:areaPointsArray_Double20];
[scoringAreas addObject:scoreAreaFor_double20];

// Triple 20 Quadrilateral
/////////////////////////////////////////

CGPoint pt_t20_1 = CGPointMake(367.0f, 214.0f);
CGPoint pt_t20_2 = CGPointMake(368.0f, 226.0f);
CGPoint pt_t20_3 = CGPointMake(412.0f, 226.0f);
CGPoint pt_t20_4 = CGPointMake(413.0f, 214.0f);

NSMutableArray * areaPointsArray_Triple20 = [NSMutableArray array];
[areaPointsArray_Triple20 addObject:[NSValue valueWithCGPoint:pt_t20_1]];
[areaPointsArray_Triple20 addObject:[NSValue valueWithCGPoint:pt_t20_2]];
[areaPointsArray_Triple20 addObject:[NSValue valueWithCGPoint:pt_t20_3]];
[areaPointsArray_Triple20 addObject:[NSValue valueWithCGPoint:pt_t20_4]];

GDSBoardArea *scoreAreaFor_triple20 = [[GDSBoardArea alloc] initWithName:@"20-Triple" abbrev:@"t20" areaValue:60 pointsArray:NULL];
[scoreAreaFor_triple20 setPointsForPath:areaPointsArray_Triple20];
[scoringAreas addObject:scoreAreaFor_triple20];

}

ScoringAreas 是一个可变阵列,它简化了板的所有区域,定义为:

@property (strong, atomic) NSMutableArray  *scoringAreas;

GDSBoardArea类以防相关

// GDSBoardArea.h

#import <Foundation/Foundation.h>

@interface GDSBoardArea : NSObject
@property NSMutableArray *pointsForPath;
@property int areaValue;
@property NSString *name;
@property NSString *abbrev;

-(id) init;
-(id)initWithName:(NSString *)name_ abbrev:(NSString *)abbrev_ areaValue:(int)areaValue_ pointsArray:(NSMutableArray*)pointsArray;
@end

-

// GDSBoardArea.m

#import "GDSBoardArea.h"

@implementation GDSBoardArea

-(id)init{
if (self = [super init]) {
    /* perform your post-initialization logic here */
    [self setName:@""];
    [self setAbbrev:@""];
    [self setAreaValue:0];
    [self setPointsForPath:NULL];
}

return self;
}

-(id)initWithName:(NSString *)name_ abbrev:(NSString *)abbrev_ areaValue:(int)areaValue_ pointsArray:(NSMutableArray*)pointsArray
{
self = [super init];
if (self) {
    self.name = name_;
    self.abbrev = abbrev_;
    self.areaValue = areaValue_;
    self.pointsForPath = pointsArray;
}
return self;
}

@end

根据user1118321的回答更改代码

createAreas函数已完全删除,并按如下方式完成直接计算(将添加更多内容,直到完成为止)

-(GDSBoardArea *)checkPointsScore:(CGPoint)tappedPoint
{
#define NUM_PIE_SLICES 20
#define NUM_RINGS 7
#define DEG_PER_SLICE 18
#define PII 3.141592653
#define OFFSETFORBOARD 99.3f

float radius_board = 344.0f;

float thickness_innerbull = 16.0f;
float thickness_outerbull = 18.0f;
float thickness_innerSingleScore = 116.0f;
float thickness_double = 16.0f;
float thickness_outerSingleScore = 80.0f;
float thickness_triple = 20.0f;
float thickness_noscore = 78.0f;

GDSBoardArea *tappedScoreArea = NULL;

double dartX = tappedPoint.x;
double dartY = tappedPoint.y;

double centerX = 390.0f;
double centerY = 390.0f;

double angle = atan2((dartY - centerY), (dartX - centerX)) * 180 / PII;
angle = angle + OFFSETFORBOARD; // To force slice 0 to correspond to Score of 20
int slice = (int)floor(angle / DEG_PER_SLICE);

NSLog(@"angle: %f", angle);
NSLog(@"slice #: %i", slice);

return tappedScoreArea;
}

1 个答案:

答案 0 :(得分:3)

如果是我,我根本不会打扰存放电路板的各个区域。首先,它们不是三角形和四边形,其次,计算它们相当容易。你可以通过获得飞镖着陆点的反正切来找出你所在的“馅饼切片”,如下所示:

double angle = atan2((dartY - centerY) / (dartX - centerX));

然后,您可以将其转换为1到1个切片之间的整数,如下所示:

int slice = (int)floor(angle / anglePerSlice);

接下来,您可以通过使用距离主板中心的距离来确定用户所在的戒指:

double deltaX = dartX - centerX;
double deltaY = dartY - centerY;
double distFromCenter = sqrt (deltaX * deltaX + deltaY * deltaY);

然后,您可以通过在数组中查找它将其转换为索引。您有一个包含单个切片中所有边界的数组。所有切片的边界都在相同的距离。所以它看起来像这样:

double concentricBounds[kNumBounds] = { 10, 15, 100, 110, 200, 210 }; // Just made up - I don't know what distances you're using.
bool done = false;
int index = 0;
for (int i = 0; (i < kNumBounds) && (!done); i++)
{
    if (distFromCenter < concentricBounds [ i ])
    {
        done = true;
        index = i;
    }
}
if (!done)
{
    ...point was off the board...
}

所以现在你有它所在的切片和它所在的环。你可以只有一个2D数组的点值来查找:

int points [][] = { {50, 25, 20, 60, 20, 40 }, { 50, 25, 5, 15, 5, 15 }, ...etc... };

请注意,atan2()返回0°平行于X轴的角度,并以逆时针顺序增加。因此,您可能需要旋转分数才能正确定位电路板。