[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;
}
答案 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轴的角度,并以逆时针顺序增加。因此,您可能需要旋转分数才能正确定位电路板。