#arrays #c #function #scope
Вопрос:
Я пытаюсь сделать игру в крестики-нолики и использую отдельный метод, который обновлял бы доску после каждого хода. Однако, похоже , я не могу получить доступ к 2D-массиву board
, который был инициализирован main()
. Я пытался сделать это общедоступным, как вы сделали бы на Java, но, похоже, это не работает. Любая помощь будет очень признательна.
#include <stdio.h>
#include <stdlib.h>
#define public
#define static
#define private static
int main(void) {
public char board[5][8] = { " | | ", "-- -- --", " | | ", "-- -- --", " | | " };
int turn = 0;
public static int base = 0;
for (size_t row = 0; row < sizeof(board) / sizeof(board[0]); row ) {
for (size_t col = 0; col < sizeof(board[0]) / sizeof(board[0][0]); col )
printf("%c", board[row][col]);
printf("n");
}
printf("Player1's turnn ");
fflush(stdout);
scanf("%i", amp;turn);
updateBoard(amp;turn);
}
void updateBoard(int a){
switch (a) {
case 1:
board[0][0] = 'X';
break;
case 2:
board[0][4] = 'X';
break;
case 3:
board[0][6] = 'X';
break;
case 4:
board[2][0] = 'X';
break;
case 5:
board[2][4] = 'X';
break;
case 6:
board[2][6] = 'X';
break;
case 7:
board[4][0] = 'X';
break;
case 8:
board[4][4] = 'X';
break;
case 9:
board[4][6] = 'X';
break;
default:
printf("Please input a correct value (1-9)");
}
for (size_t row = 0; row < sizeof(board) / sizeof(board[0]); row ) {
for (size_t col = 0; col < sizeof(board[0]) / sizeof(board[0][0]); col )
printf("%c", board[row][col]);
printf("n");
}
base = 1;
}
Комментарии:
1. отправьте доску в качестве аргумента для доски обновления функций.
2. Или объявите его «глобально» вне основной функции.
3.
#define private static
кажется, это плохо.static
имеет несколько значений в c. Это может означать либо «область действия для этой единицы перевода (например, файл *.c)», только если она находится в объявлении за пределами области действия функции, а внутри области действия это означает (упрощение) «сохранять значение этой переменной при повторных вызовах этой функции». Кроме того , поступая#define static
так, вы можете нарушить множество вещей, даже не подозревая об этом, например, если в заголовочных файлах естьstatic
где угодно.
Ответ №1:
Самое простое решение-объявить board
(и base
, предполагая, что оно будет использоваться для чего-то в будущем) в области файла, часто называемой «глобальной областью».:
static int base = 0;
static char board[5][9] = { " | | ", "-- -- --", " | | ", "-- -- --", " | | " };
void updateBoard(int a);
int main(void)
{
int turn = 0;
// ...
Они объявлены static
, что означает, что они будут видны только коду в этом файле и не могут быть доступны из других файлов той же программы.
Я удалил #define
буквы «с». Ключевые public
слова и private
не существуют в C; они обычно используются только в языках, поддерживающих объектно-ориентированное (или основанное на классах) программирование. Ключевое static
слово действительно существует, но имеет другое значение в зависимости от контекста. Его лучше не переопределять.
Обратите внимание, что второе измерение должно быть 9: 8 символов и 1 нуль-терминатор.
Недостатком наличия переменных в области действия файла является то, что они видны во всем файле, и при наличии нескольких функций, изменяющих их содержимое, может стать трудно контролировать и рассуждать о поведении программы.
Возможно , лучшее решение-сохранить board
и base
main
сохранить, а затем передать их updateBoard
кому угодно . Хотя это сразу же вводит некоторые более продвинутые C-концепции. Добавление необходимых дополнительных аргументов/параметров к прототипу функции и вызову функции, вероятно, вам знакомо. Проблема в том, что аргументы массива преобразуются в указатели (см. Здесь, часто называемый «распад массива на указатель»). Это означает, что sizeof
теперь предоставляется не размер всего массива, а размер указателя на первый элемент массива. В приведенном ниже решении это разрешается путем получения измерений один раз в основном, сохранения их в переменных и передачи этих значений функции. Это, возможно, лучшее решение, чем использовать sizeof
вычисления везде. И как только переменные будут установлены, это также будет работать с динамически выделяемыми массивами.
// Forward declaring the function, so main knows it exists
void updateBoard(char board[5][9], size_t nRows, size_t nCols, int base, int a);
int main(void)
{
int base = 0;
// Note the 9 for the second dimension
char board[5][9] = { " | | ", "-- -- --", " | | ", "-- -- --", " | | " };
int turn = 0;
// Initializing the variables for the dimensions...
size_t nRows = sizeof(board) / sizeof(board[0]);
size_t nCols = sizeof(board[0]) / sizeof(board[0][0]);
// ...which we can now use here as well...
for (size_t row = 0; row < nRows; row ) {
for (size_t col = 0; col < nCols; col )
printf("%c", board[row][col]);
printf("n");
}
printf("Player1's turnn ");
fflush(stdout);
scanf("%i", amp;turn);
// ... and here, along with passing board and base.
updateBoard(board, nRows, nCols, base, turn);
}
void updateBoard(char board[5][9], size_t nRows, size_t nCols, int base, int a){
switch (a) {
// ... code omitted for brevity ...
}
// Use the passed dimension values here
for (size_t row = 0; row < nRows; row ) {
for (size_t col = 0; col < nCols; col )
printf("%c", board[row][col]);
printf("n");
}
base = 1;
}
При передаче переменных, подобных этой, существует важное различие между передачей переменных по ссылке и передачей их по значению. Возможно, это хорошая следующая тема для изучения в вашем путешествии на C, наряду с static
«строковым литералом»/»терминатором null».