Могу ли я использовать goto в такой ситуации? - PullRequest
1 голос
/ 12 марта 2012

Хотелось бы знать, если в такой ситуации использовать goto ok? Можете ли вы предложить лучшее решение? Я вижу единственного, кто делает второе время в cicle, но тогда необходимо будет дважды вызвать makeMove.

void BoardView::startGame()
{
    int currStep=0;
    int x,y;
    while (board_->isWin()==none)
    {
        currStep++;
        show();
    wrong:
        std::cout << " Player " << (currStep%2==0 ? 1 : 2) << ": ";
        std::cin >> x;
        y=x%10;
        x/=10;
        if (!board_->makeMove(x,y,(currStep%2==0 ? cross : zero)))
        {
            std::cout << "Wrong move! Try again.\n";
            goto wrong;
        }
    }
}

Ответы [ 7 ]

4 голосов
/ 12 марта 2012

Не используйте goto.Используйте петлю while (true) и break из нее, когда вы сделали успешный ход.

while (true) {
    std::cout << " Player " << (currStep%2==0 ? 1 : 2) << ": ";
    std::cin >> x;
    y=x%10;
    x/=10;
    if (board_->makeMove(x,y,(currStep%2==0 ? cross : zero)))
        break;
    std::cout << "Wrong move! Try again.\n";
}
1 голос
/ 12 марта 2012

Общий совет - избегать выражения GOTO, однако, смотрите модифицированный код с помощью do while

    void BoardView::startGame()
{
    int currStep=0;
    int x,y;
    while (board_->isWin()==none) {

        currStep++;
        show();
        int retry = 0; /* So that 'retry' is visible to do while loop */ 
        do {
              retry = 0;
              std::cout << " Player " << (currStep%2==0 ? 1 : 2) << ": ";
              std::cin >> x;
              y=x%10;
              x/=10;
             if (!board_->makeMove(x,y,(currStep%2==0 ? cross : zero))) {

                std::cout << "Wrong move! Try again.\n";
                retry = 1
             } 

       } while (retry);
    }
}
1 голос
/ 12 марта 2012

Да, вам разрешено делать такой прыжок, хотя обычно лучше избегать goto. Вы можете переписать это, например, так:

void BoardView::startGame()
{
    int currStep=1;
    int x,y;
    show();
    while (board_->isWin()==none)
    {
        std::cout << " Player " << (currStep%2==0 ? 1 : 2) << ": ";
        std::cin >> x;
        y=x%10;
        x/=10;
        if (board_->makeMove(x,y,(currStep%2==0 ? cross : zero)))
        {
            currStep++;
            show();
        }
        else
        {
            std::cout << "Wrong move! Try again.\n";
        }
    }
}
1 голос
/ 12 марта 2012

Может быть:

void BoardView::startGame()
{
    int currStep=1;
    int x,y;
    show();
    while (board_->isWin()==none)
    {
        std::cout << " Player " << (currStep%2==0 ? 1 : 2) << ": ";
        std::cin >> x;
        y=x%10;
        x/=10;
        if (!board_->makeMove(x,y,(currStep%2==0 ? cross : zero)))
        {
            std::cout << "Wrong move! Try again.\n";
            continue;
        }
        ++currStep;
        show();
    }
}

Это не совсем то же самое, но оно не использует goto.

0 голосов
/ 06 февраля 2013

Два цикла, без постоянного условного выражения и только один вызов makeMove:

void BoardView::startGameLoop()
{
    int currStep = 0;
    int x,y;
    while (none == board_->isWin())
    {
        ++currStep;
        show();

        for (;;)
        {
            std::cout << " Player " << ((currStep & 1) + 1) << ": ";
            std::cin >> x;
            y = x % 10;
            x /= 10;
            if (!board_->makeMove(x, y, (currStep & 1) ? zero : cross))
            {
                std::cout << "Wrong move! Try again.\n";
                continue;
            }
            break;
        }
    }
}
0 голосов
/ 12 марта 2012

Что не так с:

std::pair<int, int> BoardView::getNextMove()
{
    std::cout << " Player " << (currStep & 2 == 0 ? 1 : 2) << ": ";
    int tmp;
    std::cin >> temp;
    return std::pair<int, int>( tmp / 10, tmp % 10 );
}

void BoardView::startGame() 
{
    int currentStep = 0;
    while ( myBoard->isWin() == none ) {
        std::pair<int, int> move = getNextMove();
        while ( ! myBoard->makeMove( move, (currentStep % 2 == 0 ?  cross : zero) ) {
            std::cout << "Wrong move! Try again" << std::endl;
            move = getNextMove();
        }
    }
}

(хотя я бы предпочел явный класс для типа Move, а не просто std::pair. Члены row и column намного более явные чем first и second.)

Обычно, если вас соблазняет goto (или даже continue или break), это признак того, что слишком много в одной функции.

0 голосов
/ 12 марта 2012

Вы должны избегать goto настолько, насколько можете. Используйте только при использовании в больших вложенных программах.в противном случае использование goto делает программу ненадежной, нечитаемой и трудной для отладки.Еще одна большая проблема с goto заключается в том, что когда мы их используем, мы никогда не можем быть уверены, как мы достигли определенной точки в нашем коде. Они скрывают поток управления.так что избегайте их.

Я предлагаю использовать два цикла while .... это будет лучше ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...