为了帮助收集Objective-C感,我正在创建一个非常基本连接4游戏,而不是Cocoa。
在我的课程中,我有三个模块:
理想情况下,我希望Player和Computer类能够通过某种继承来编辑生活在Game中的pieceLoc
的同一个实例,但是我不知道该怎么做。
这是我目前正在考虑的一个片段:
// startGame exists within the "Game" module
char *pieceLoc[42]; // This is a *temporary* global var. I'm still learning about
// the best way to implement this with class and instance
// methods. This is the array that holds the board info.
-(void) startGame {
Player *player =[[Player alloc] init]; // player's symbol = 'X'
Computer *computer =[[Computer alloc] init]; // computer's symbol = 'O'
int i = 0;
while ([game hasPieceWon: 'X'] == NO && [game hasPieceWon: 'O'] == NO) {
//function for player move
if ([game hasPieceWon: 'X'] == NO) {
//function for computer move
}
}
if ([game hasPieceWon: 'X'] == YES)
// Tell the player they've won
else
// Tell the player the computer has won.
char *pieceLoc[42]; // This is a *temporary* global var. I'm still learning about
// the best way to implement this with class and instance
// methods. This is the array that holds the board info.
-(void) startGame {
Player *player =[[Player alloc] init]; // player's symbol = 'X'
Computer *computer =[[Computer alloc] init]; // computer's symbol = 'O'
int i = 0;
while ([game hasPieceWon: 'X'] == NO && [game hasPieceWon: 'O'] == NO) {
//function for player move
if ([game hasPieceWon: 'X'] == NO) {
//function for computer move
}
}
if ([game hasPieceWon: 'X'] == YES)
// Tell the player they've won
else
// Tell the player the computer has won.
用于播放器和计算机移动的函数是以某种方式获取对数组}
的访问所需的函数(一旦我了解有关类与实例的更多信息,它将来会作为实例变量存在)方法)。 pieceLoc
当前作为char *存在,以防我必须通过函数参数传递它。
我觉得这对我如何考虑OOP是一个相当简单的问题,但我无法找到我正在寻找的答案,尽管搜索下午的大部分时间。从我收集的内容来看,我的问题与课程构成有关,但我找不到关于Objective-C的好资源。
所以,再次:我正在寻找一种方法将一个存在于“父类”游戏中的pieceLoc
实例传递给两个“子类”,其中pieceLoc
可以直接操作< em>没有使用其他参数。
如果将数组作为参数传递最终会成为更惯用的事情,我是否能够获得一个关于如何通过引用传递在Objective-C中的示例?
感谢您的帮助!
答案 0 :(得分:4)
正如您可能已经想到的那样,Objective-C实际上没有可以从超类继承的“类变量”。
构建它的一种方法是不必拥有全局变量就是这样的:
你有一个Game对象,可以保存对每个玩家和董事会的引用。每个玩家都要初始化,并参考董事会。你的startGame方法(在游戏中)会有这样的代码:
board = [[Board alloc] init];
player = [[Player alloc] initWithBoard: board];
computer = [[ComputerPlayer alloc] initWithBoard: board];
在Board类中,您可以通过方法查询董事会的状态,采取行动,确定移动是否合法,以及玩家是否赢了(尽管与游戏规则相关的逻辑可能会进入游戏)。
在Player和ComputerPlayer中的initWithBoard方法中,您只需保留棋盘实例,并使用它来传达每个玩家决定制作的动作。游戏将建立移动顺序,并跟踪任何全局状态。当玩家和ComputerPlayer在游戏结束时被释放时,他们会以dealloc方法释放他们对棋盘的引用。
答案 1 :(得分:1)
由于Objective-C本身没有类变量(它们仅使用静态变量进行模拟),如果在同一源文件/编译单元中定义方法,子类只能直接访问静态全局变量。这打破了其他最佳实践(每个编译单元一个类定义)。访问类字段的常用方法是使用访问器。
在这种情况下,请注意不要将couple类过紧。将棋盘(作为对象,而不是数组)传递给Player
(Person
可能是一个更好的名称,因为计算机也是一个玩家)和Computer
,无论是作为一种方法参数或属性比引用另一个类的全局或静态成员更灵活。玩家对象决定放置的位置,然后告诉董事会放置该块的位置。或者,游戏将棋盘的只读版本传递给玩家;玩家的放置方法返回放置一块的位置。首先,解耦和使用板对象可以防止作弊。想象一下有人注入了他们自己的Player类,让他们在轮到他们时放置多个棋子。另一方面,间接使得更容易添加网络支持(对象之间的消息在对本地对象透明的过程中成为网络消息)。
还要考虑玩家的创建地点。让其他东西创建玩家并将其传递给startGame
方法可能更有意义。例如,如果玩家参加锦标赛,这将是有意义的,因此玩家对象需要存在的时间超过单个游戏。
类组合是指一个对象具有另一个作为成员。例如,C不支持继承,但允许嵌套结构。另一种说法是,类的构成是关于“有一个”的关系,而继承是关于“是一个”的关系。例如,玩家类可以有一个指向棋盘的指针,每个指针用来放置棋子。
Objective-C也没有pass-by-reference。相反,它使用指针。
另外,请确保您的游戏处理关系。您可能希望简化游戏循环以实现此目的。在伪代码中,
// nextPlayer returns 'nil' if game is over (win or tie)
while currPlayer := [game nextPlayer]:
// player will tell board where to place piece
[currPlayer move]
或者:
// nextPlayer always returns a valid player
while currPlayer := [game nextPlayer]:
// player's method returns what and where to place
[self place:[currPlayer move] for:currPlayer]
// explicitly test for game end, which includes wins & ties
if [game isOver]:
break