我正在为iOS开发一个BlackJack游戏。跟踪当前状态和需要做的事情变得越来越困难。例如,我有一个跟踪当前游戏的C++类:
class Game {
queue<Player> playerQueue;
void hit();
void stand();
}目前我正在使用事件实现它(方法A):
- (void)hitButtonPress:(id)sender {
game->hit();
}
void Game::hit() {
dealCard(playerQueue.top());
}
void Game::stand() {
playerQueue.pop();
goToNextPlayersTurn();
}随着越来越多的选项被添加到游戏中,为每个选项创建事件变得单调乏味,很难跟踪。
我想到的另一种实现方式是这样的(方法B):
void Game::playersTurn(Player *player) {
dealCards(player);
while (true) {
string choice = waitForUserChoice();
if (choice == "stand") break;
if (choice == "hit")
dealCard(player);
// etc.
}
playerQueue.pop();
goToNextPlayersTurn();
}其中,waitForUserChoice是一个特殊函数,它允许用户与UIViewController交互,一旦用户按下按钮,就会将控制权返回给playersTurn函数。换句话说,它会暂停程序,直到用户单击一个按钮。
使用方法A,我需要在每次需要用户交互时拆分我的功能。方法B让一切都保持在更好的控制之下。从本质上讲,方法A和方法B之间的区别如下:
答:
function A() {
initialize();
// now wait for user interaction by waiting for a call to CompleteA
}
function CompleteA() {
finalize();
}B:
function B() {
initialize();
waitForUserInteraction();
finalize();
}注意B是如何使代码更有条理的。有没有办法用Objective-C做到这一点呢?或者有没有我没有推荐的不同的方法呢?
我能想到的第三种选择是使用有限状态机。我听说过一些关于他们的事情,但我确信这对我在这种情况下是否有帮助。
对于我的问题,推荐的设计模式是什么?
发布于 2013-02-21 18:28:34
我理解你所面临的困境。当我第一次启动iOS的时候,我有一段非常艰难的时间来考虑放弃对操作系统的控制。
通常,iOS会鼓励您使用方法A。通常,您的ViewController中有在方法A()中设置的变量,然后在CompleteA()中检查这些变量,以验证A()是否先运行等等。
关于你关于有限状态机的问题,我认为它可能会帮助你解决你的问题。我用iOS写的第一个东西是一个有限状态机(这是一个相当糟糕的代码),但是你可以看看这里(在first ViewController.m的底部附近:
https://github.com/esromneb/ios-finite-state-machine
一般的想法是将其放入.h文件中的@interface块中
static int state = 0;
static int running = 0;在你的.m中,你有这个:
- (void) tick {
switch (state) {
case 0:
//this case only runs once for the fsm, so setup one time initializations
// next state
state = 1;
break;
case 1:
navBarStatus.topItem.title = @"Connecting...";
state = 2;
break;
case 2:
// if something happend we move on, if not we wait in the connecting stage
if( something )
state = 3;
else
state = 1;
break;
case 3:
// respond to something
// next state
state = 4;
break;
case 4:
// wait for user interaction
navBarStatus.topItem.title = @"Press a button!";
state = 4;
globalCommand = userInput;
// if user did something
if( globalCommand != 0 )
{
// go to state to consume user interaction
state = 5;
}
break;
case 5:
if( globalCommand == 6 )
{
// respond to command #6
}
if( globalCommand == 7 )
{
// respond to command #7
}
// go back and wait for user input
state = 4;
break;
default:
state = 0;
break;
}
if( running )
{
[self performSelector:@selector(tick) withObject:nil afterDelay:0.1];
}
}在本例中(从github上的修改而来),globalCommand是一个表示用户输入的整数。如果globalCommand为0,则有限状态机仅在状态4中旋转,直到globalCommand为非零。
要启动有限状态机,只需将running设置为1,然后从viewController调用self tick。FSM将每隔0.1秒“滴答”一次,直到running设置为0。
在我最初的FSM设计中,我必须对运行自己软件的windows计算机的用户输入和网络输入做出响应。在我的设计中,windows PC也运行类似但不同的FSM。对于这个设计,我使用NSMutuableArray构建了两个命令的先进先出队列对象。用户交互和网络数据包将命令入队到队列中,而FSM将出队项目并对其作出响应。我最终使用了https://github.com/esromneb/ios-queue-object来处理队列。
如果您需要任何澄清,请发表意见。
https://stackoverflow.com/questions/14995611
复制相似问题