【问题标题】:Objective-C State Machine pass in ParametersObjective-C 状态机传入参数
【发布时间】:2011-10-25 10:48:08
【问题描述】:

我感兴趣地阅读了 StackOverflow 上的这篇文章: How to Make a Basic Finite State Machine in Objective-C

我以此为基础为一个简单的足球比赛构建了我的状态机。我有状态防御,攻击,停止,中立。我已经创建了状态机,它会打印出 NSLog "Now Entering State Defend" 等。

现在我想将我的 Football Team 的引用传递给状态机,这样我就可以让我的球队根据状态做一些事情。即如果它的防守,我可以派我的球员站在对手旁边。

我尝试了许多不同的方法,但都以语法错误告终。我很感激朝着正确的方向前进

TeamState.h 请注意我在 cmets 中遇到的错误

@class TeamState;

#import <Foundation/Foundation.h>
#import "FootballTeam.h"

@protocol TeamStateProt 

-(void) enterTeamState:(TeamState*)team;
-(void) executeTeamState:(TeamState*)team;
-(void) exitTeamState:(TeamState*)team;

@end


@interface TeamState : NSObject{
    id<TeamStateProt> currentTeamState;

    id<TeamStateProt> Stoppage;
    id<TeamStateProt> Neutral;
    id<TeamStateProt> Defend;
    id<TeamStateProt> Attack;

    FootballTeam *footballTeam;  //ERROR Unknown Type name FootballTeam 
}

@property (nonatomic, retain) id<TeamStateProt> currentTeamState;
@property (nonatomic, retain) id<TeamStateProt> Stoppage;
@property (nonatomic, retain) id<TeamStateProt> Neutral;
@property (nonatomic, retain) id<TeamStateProt> Defend;
@property (nonatomic, retain) id<TeamStateProt> Attack;

- (id)initWithFootBallTeam:(FootballTeam*) team; //Error Expected a Type
-(void)update;
-(void)changeState:(id<TeamStateProt>) newState;
-(void)executeState:(id<TeamStateProt>) State;
@end

TeamState.m

#import "TeamState.h"
#import "FootballTeam.h"
#import "Stoppage_TS.h"
#import "Neutral_TS.h"
#import "Defend_TS.h"
#import "Attack_TS.h"


@implementation TeamState 

@synthesize currentTeamState;
@synthesize Stoppage, Neutral, Defend, Attack;

- (id)init
{
    self = [super init];
     if (self) {
        // Initialization code here.
        id<TeamStateProt>  s = [[Stoppage_TS alloc] init];
        self.Stoppage = s;

        id<TeamStateProt>  n = [[Neutral_TS alloc] init];
        self.Neutral = n;

        id<TeamStateProt>  d = [[Defend_TS alloc] init];
        self.Defend = d;

        id<TeamStateProt>  a = [[Attack_TS alloc] init];
        self.Attack = a;

        self.currentTeamState = n;
        [self.currentTeamState enterTeamState:self];
        [self executeState:self.currentTeamState];
    }

    return self;
}

- (id)initWithFootBallTeam:(FootballTeam*) team
{
    self = [super init];
    if (self) {
        // Initialization code here.
        id<TeamStateProt>  s = [[Stoppage_TS alloc] init];
        self.Stoppage = s;


        id<TeamStateProt>  n = [[Neutral_TS alloc] init];
        self.Neutral = n;

        id<TeamStateProt>  d = [[Defend_TS alloc] init];
        self.Defend = d;

        id<TeamStateProt>  a = [[Attack_TS alloc] init];
        self.Attack = a;

        self.currentTeamState = n;
        [self.currentTeamState enterTeamState:self];
        [self executeState:self.currentTeamState];

        footballTeam = team;
    }

    return self;
}

-(void)changeState:(id<TeamStateProt>) newState{
    NSLog(@"Changing State");
    if (newState != nil) {
        NSLog(@"Changing a state which isn't nil");
        [self.currentTeamState exitTeamState:self];
        self.currentTeamState = newState;
        [self.currentTeamState enterTeamState:self];
        [self executeState:self.currentTeamState];
    }

}

-(void)executeState:(id<TeamStateProt>) State{
    [self.currentTeamState executeTeamState:self];
}

// Each update, execute the execute state on the current team state
-(void)update{
    [self executeState:self.currentTeamState];
}
@end

FootballTeam.h

#import <Foundation/Foundation.h>
#import "Player.h"
#import "TeamState.h"
#import "Football.h"

typedef enum  {
    Home,
    Away
} TeamType;

@interface FootballTeam : NSObject{
    Player *ReceivingPlayer;    //Player to receive the ball
    Player *ClosestToBall;      //Player closest to the ball
    Player *ControllingPlayer;  //Player who has the ball can be NULL
    Player *SupportingPlayer;   //Player in a position to receive the ball

    NSMutableArray *players;    //Array of all the Players on this team

    TeamState *state;           //Current state of the teams state machine

    TeamType type;              //Defines if Home team or Away team
}

@property (nonatomic) TeamType type;
@property(nonatomic, retain) TeamState *state;

-(void) sendPlayersToHome;
-(Player*) playerClosestToBall:(Football*) ball;
-(BOOL) areAllPlayersAtHome;

@end

【问题讨论】:

    标签: objective-c state-machine


    【解决方案1】:

    你有循环引用。您在 FootballTeam.h 中导入 TeamState.h,反之亦然。

    为避免这种情况,请仅在 .m 文件中导入 .h 文件,并在 .h 文件中添加前向声明。

    所以,在 TeamState.h 中:

    @class FootballTeam;
    

    并将导入移动到 TeamState.m

    在 FootballTeam 中也是如此。

    【讨论】:

    • 对此进行扩展:#import 是一个预处理指令,与 C 的 #include 完全相同,只是它会自动忽略已经 #imported 的文件。因此,当您导入 FootballTeam.h 时,它会导入 TeamState.h,然后 TeamState.h 尝试导入 FootballTeam.h 但预处理器拒绝,因为 FootballTeam.h 已经导入。正如 jrturton 正确建议的那样,前向声明解决了这个问题,因为它们为编译器提供了足够的信息来继续进行而不依赖于导入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 2012-01-03
    • 2023-03-13
    • 2011-09-30
    相关资源
    最近更新 更多