Я сейчас строю набор структур, которые будут хранить состояние игры uno.Игра хранится в структуре, которая содержит следующие данные.Я представляю колоду карт структурой под названием Deck, которая будет работать как стек, определенный следующим образом:
typedef struct _card *Card;
typedef struct _deck *Deck;
typedef struct _listCard *ListCard;
typedef struct _player *Player;
struct _card {
value value;
color color;
suit suit;
};
struct _listCard {
Card card;
ListCard next;
};
struct _player {
// Integer between 0 and 3.
int player_id;
// Player has a hand (a deck of cards)
Deck hand;
};
// A deck is an ADT for a linked lis of ListCards.
struct _deck {
// Keep track of the deck.
int num_cards;
// Stack of cards in the deck.
// Keep track of the top of the deck
ListCard top;
};
struct _gamestate {
int curr_player;
int turn_number;
Card curr_card;
};
struct _game {
Deck draw_pile;
Deck discard_pile;
Player players;
GameState game_state;
int turnNumber;
int deckSize;
};
Я реализовал несколько функций и сейчас пытаюсь написать функцию, которая удалитколода.
static void freeDeck(Deck deck) {
ListCard curr = deck->top;
if (curr == NULL) {
free(deck);
return;
}
while (curr != NULL) {
ListCard temp = curr;
destroyCard(temp->card);
curr = curr->next;
free(temp);
}
free(deck);
}
void destroyCard(Card card) {
free(card);
}
Теперь у меня проблема с реализацией поп-функции и использованием возвращенного значения этой функции для перемещения карты из одной колоды в другую (например, взятие верхней карты колоды ипоместив его в стопку сброса).
static Card popCard(Deck deck) {
// sanity check
if (deck == NULL) {
return NULL;
// Can't pop from an empty stack.
} else if (deck->top == NULL) {
return NULL;
// Only one card in the deck.
} else if (deck->top->next == NULL) {
Card temp = deck->top->card;
free(deck->top);
deck->top = NULL;
return temp;
}
// Otherwise: at least two cards in the deck:
Card val = deck->top->card;
ListCard temp = deck->top->next;
free(deck->top);
deck->top = temp;
return val;
}
Это моя функция для добавления, и это моя функция для добавления:
static void addToDeck(Deck deck, Card card) {
if (deck->top == NULL) {
deck->top = newListCard(card);
} else {
addCard(deck, card);
}
deck->num_cards++;
}
static ListCard newListCard(Card card) {
ListCard newCard = malloc(sizeof(struct _listCard));
newCard->next = NULL;
newCard->card = card;
return newCard;
}
static void addCard(Deck deck, Card card) {
assert(deck != NULL);
ListCard newCard = newListCard(card);
newCard->next = deck->top;
deck->top = newCard;
}
Я вызываю функцию для выполнения вышеуказанной операциивот так:
addToDeck(newgame->discard_pile, popCard(newgame->draw_pile));
Однако это приводит к ошибке неверного указателя в gdb, когда я пытаюсь освободить колоду с помощью
freeDeck(newgame->discard_pile)
Я новичок в управлении памятью C и считаю, чтопроблема связана с попыткой освободить память, которая больше не указывает на начало точки, где она была malloc'd.
РЕДАКТИРОВАТЬ:
Сама игра инициализируется так:
Game newGame(int deckSize, value values[], color colors[], suit suits[]) {
// malloc a new game.
Game newgame = malloc(sizeof(game));
if (newgame == NULL) {
fprintf(stderr, "Out of memory");
return NULL;
}
// Otherwise there will be no cards to put into the draw pile.
if (deckSize <= NUM_PLAYERS*DEFAULT_HAND) {
return NULL;
}
newgame->deckSize = deckSize;
// malloc the players in the game.
Player players = malloc(NUM_PLAYERS*sizeof(struct _player));
if (players == NULL) {
fprintf(stderr, "Out of memory");
return NULL;
}
// Instatiate each player object
int i = 0;
while (i < NUM_PLAYERS) {
players[i].player_id = i;
players[i].hand = newDeck();
i++;
}
// Assign the players to the game.
newgame->players = players;
// Create decks of discard pile and draw_pile
newgame->draw_pile = newDeck();
newgame->discard_pile = newDeck();
// loop through each of the values, colours and suits and create the necessary objects to star the game.
i = 0;
while (i < deckSize) {
// Create a card from the array of values, colours and suits.
Card card = newCard(values[i], colors[i], suits[i]);
// Give each player 7 cards.
if (i < DEFAULT_HAND*NUM_PLAYERS) {
addToDeck(newgame->players[i % 4].hand, card);
// After we have given each player seven cards fill the draw pile.
} else {
addToDeck(newgame->draw_pile, card);
}
i++;
}
// Push the first card onto the stack of the discard_pile.
addToDeck(newgame->discard_pile, popCard(newgame->draw_pile));
//Create the initial game state.
GameState init = malloc(sizeof(struct _gamestate));
init->curr_card = newgame->discard_pile->top->card;
init->curr_player = 0;
init->turn_number = 1;
newgame->game_state = init;
printGame(newgame);
return newgame;
}
static Deck newDeck(void) {
Deck deck = malloc(sizeof(struct _deck));
if (deck == NULL) {
fprintf(stderr, "Out of memory");
return NULL;
}
deck->num_cards = 0;
deck->top = NULL;
return deck;
}
Игра освобождается с помощью этой функции:
void destroyGame(Game game) {
GameState state = game->game_state;
destroyCard(state->curr_card);
free(state);
Player players = game->players;
int i = 0;
while (i < NUM_PLAYERS) {
freeDeck(players[i].hand);
i++;
}
free(game->players);
freeDeck(game->draw_pile);
freeDeck(game->discard_pile);
free(game);
}
Бесплатная функция работает, как и ожидалось, до тех пор, пока я не вызову freeDeck (game-> discard_pile), с помощью которого я получаю недопустимый указатель на элементчто я выскочил из колоды draw_pile.Еще одно тестирование показало, что это происходит каждый раз, когда я вытаскиваю карту из колоды.
Основная функция в данный момент просто вызывает следующее:
int main(void) {
int decksize = 50;
value values[decksize];
color colors[decksize];
suit suits[decksize];
for (int i = 0; i < decksize; i++) {
values[i] = rand() % 16;
colors[i] = rand() % 16;
suits[i] = rand() % 16;
}
Game cardgame = newGame(50, values, colors, suits);
destroyGame(cardgame);
}
Где именно моя ошибка икак я могу это исправить?