Рекурсивная функция не возвращает значение условия отмены

#c #if-statement #return-value

#c #if-оператор #возвращаемое значение

Вопрос:

У меня есть рекурсивная функция, которая имитирует игру в Башни (разновидность игры в шашки). Моя функция получает поле и мой цвет. Он проверяет, закончилась ли игра, что является условием отмены моей рекурсии. Для -1 это означает, что игра не закончена, поэтому она вызывает себя рекурсивно с измененным цветом и новой игровой доской. Если игра окончена, она возвращает либо 0, либо 1.

 int simulate(int myColour, char field[WIDTH][HEIGTH][MAX_TOWER_LENGTH]){
    int cancel = checkForEndOfGame(field); 
    //int returnValue=50;
    struct moveArray moves;
    memset(amp;moves, 0, sizeof(moves)); 
    printf("DEBUG: CANCEL-Value: %in", cancel);
    if(cancel==-1){
        moves=calculatePossibleMoves(moves, field, myColour);
        int indexMove = rand() % moves.count;
        makeMove(field, moves.moves[indexMove]);
        printGameboard(field);
        int colourChange;
        if(myColour==WHITE){
            colourChange=BLACK;
        } else colourChange=WHITE;
        simulate(colourChange, field);
    }
    if(cancel==0){
        printGameboard(field);
        return 1;
    }
    if(cancel==1){
        printGameboard(field);
        return 0;
    }
    return 13;
}
 

Даже если cancel имеет значение 1 (что означает, что я должен получить возврат 0), моя функция возвращает 13.
Я ввожу значение return 13 только потому, что в противном случае мой компилятор (gcc) выдает мою ошибку:

 error: non-void function does not return a value in all control paths
      [-Werror,-Wreturn-type]
 

Комментарии:

1.Поскольку компилятор не может проверить checkForEndOfGame , он должен предположить, что может быть возвращено любое int значение. Например, если бы он вернулся 2 , ни одно из ваших if значений не было бы истинным. Таким образом, элемент управления будет находиться в нижней части функции. Компилятор понимает, что return для этого управляющего пути не существует, поэтому он помечает его. Вот почему вам это нужно.

2. Подсказка: когда cancel == -1 , что simulate() вернется?

3. но даже если я добавлю: else возвращает 12; он не будет компилироваться

4. @Нейт Элдридж: но разве не так работает рекурсия, что она переходит к условию отмены и возвращает 0 или 1 в конце?

5. В этом пути кода он вызывает simulate() . Когда рекурсивный вызов simulate() возвращает, выполнение продолжается. Значение cancel в этом экземпляре simulate() не изменилось и остается -1 неизменным, поэтому ни один из оставшихся if блоков не выполняется, и мы переходим к return 13 концу.

Ответ №1:

Ваш рекурсивный вызов не предпринимает никаких попыток передать причину отмены вызывающему. Кажется, вы ожидаете, что это произойдет как-то автоматически, но этого не произойдет. Каждый рекурсивный вызов simulate имеет свои собственные локальные переменные — что очень важно, cancel — поэтому после возврата рекурсивного вызова локальное значение cancel останется неизменным (и все равно -1), и поэтому будет возвращено 13.

То, что вы, вероятно, хотели сделать, это просто передать возвращаемое значение, сделав рекурсивный вызов конечным вызовом:

  return simulate(colourChange, field);