From b94ea8797a91db8e1420898a54f14956f523e583 Mon Sep 17 00:00:00 2001 From: Murilo Pereira Date: Sun, 29 May 2011 15:19:00 -0300 Subject: [PATCH] Make stack#pop return a card and don't duplicate stuff on push/pop. --- lib/display.c | 2 - lib/frame.c | 7 +- lib/game.c | 87 ++++++----------- lib/stack.c | 38 ++++---- lib/stack.h | 2 +- test/game_test.c | 240 ++++++++++++++++++++++++++-------------------- test/stack_test.c | 27 +++--- 7 files changed, 196 insertions(+), 207 deletions(-) diff --git a/lib/display.c b/lib/display.c index c8b4784..8852d36 100644 --- a/lib/display.c +++ b/lib/display.c @@ -107,7 +107,6 @@ void draw_back(struct card *card) { } void draw_card(struct card *card) { - mvwin(card->frame->window, card->frame->begin_y, card->frame->begin_x); if (card->face == EXPOSED) { draw_front(card); } else { @@ -124,7 +123,6 @@ void draw_stack(struct stack *stack) { } else { if (maneuvre_stack(stack)) { struct stack *reversed_stack = reverse(stack); - for (struct stack *i = reversed_stack; i; i = i->next) { draw_card(i->card); } diff --git a/lib/frame.c b/lib/frame.c index ed27116..957813e 100644 --- a/lib/frame.c +++ b/lib/frame.c @@ -11,10 +11,10 @@ void allocate_frame(struct frame **frame) { fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__)); exit(errno); } + (*frame)->window = newwin(FRAME_HEIGHT, FRAME_WIDTH, 0, 0); } void initialize_frame(struct frame *frame) { - frame->window = NULL; frame->begin_y = 0; frame->begin_x = 0; } @@ -38,8 +38,5 @@ void free_frame(struct frame *frame) { void set_frame(struct frame *frame, int begin_y, int begin_x) { frame->begin_y = begin_y; frame->begin_x = begin_x; - frame->window = newwin(FRAME_HEIGHT, - FRAME_WIDTH, - frame->begin_y, - frame->begin_x); + mvwin(frame->window, begin_y, begin_x); } diff --git a/lib/game.c b/lib/game.c index fafe1ac..e8f35f8 100644 --- a/lib/game.c +++ b/lib/game.c @@ -73,60 +73,32 @@ bool valid_move(struct stack *origin, struct stack *destination) { } void move_card(struct stack **origin, struct stack **destination) { - struct stack *stack; - - if (!empty(*origin)) { - (*origin)->card->frame->begin_x = (*destination)->card->frame->begin_x; - (*origin)->card->frame->begin_y = (*destination)->card->frame->begin_y; - } - if (!empty(*destination) && maneuvre_stack(*destination)) { - (*origin)->card->frame->begin_y++; - } - if ((stack = pop(origin))) { - push(destination, stack->card); + struct card *tmp; + if ((tmp = pop(origin))) { + int destination_y = (*destination)->card->frame->begin_y; + int destination_x = (*destination)->card->frame->begin_x; + if (!empty(*destination) && maneuvre_stack(*destination)) { + destination_y++; + } + push(destination, tmp); + set_frame((*destination)->card->frame, destination_y, destination_x); } } static void set_stacks_initial_coordinates(struct deck *deck) { - set_frame(deck->stock->card->frame, - STOCK_BEGIN_Y, - STOCK_BEGIN_X); - set_frame(deck->waste_pile->card->frame, - WASTE_PILE_BEGIN_Y, - WASTE_PILE_BEGIN_X); - set_frame(deck->foundation_0->card->frame, - FOUNDATION_BEGIN_Y, - FOUNDATION_0_BEGIN_X); - set_frame(deck->foundation_1->card->frame, - FOUNDATION_BEGIN_Y, - FOUNDATION_1_BEGIN_X); - set_frame(deck->foundation_2->card->frame, - FOUNDATION_BEGIN_Y, - FOUNDATION_2_BEGIN_X); - set_frame(deck->foundation_3->card->frame, - FOUNDATION_BEGIN_Y, - FOUNDATION_3_BEGIN_X); - set_frame(deck->maneuvre_0->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_0_BEGIN_X); - set_frame(deck->maneuvre_1->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_1_BEGIN_X); - set_frame(deck->maneuvre_2->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_2_BEGIN_X); - set_frame(deck->maneuvre_3->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_3_BEGIN_X); - set_frame(deck->maneuvre_4->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_4_BEGIN_X); - set_frame(deck->maneuvre_5->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_5_BEGIN_X); - set_frame(deck->maneuvre_6->card->frame, - MANEUVRE_BEGIN_Y, - MANEUVRE_6_BEGIN_X); + set_frame(deck->stock->card->frame, STOCK_BEGIN_Y, STOCK_BEGIN_X); + set_frame(deck->waste_pile->card->frame, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X); + set_frame(deck->foundation_0->card->frame, FOUNDATION_BEGIN_Y, FOUNDATION_0_BEGIN_X); + set_frame(deck->foundation_1->card->frame, FOUNDATION_BEGIN_Y, FOUNDATION_1_BEGIN_X); + set_frame(deck->foundation_2->card->frame, FOUNDATION_BEGIN_Y, FOUNDATION_2_BEGIN_X); + set_frame(deck->foundation_3->card->frame, FOUNDATION_BEGIN_Y, FOUNDATION_3_BEGIN_X); + set_frame(deck->maneuvre_0->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X); + set_frame(deck->maneuvre_1->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X); + set_frame(deck->maneuvre_2->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X); + set_frame(deck->maneuvre_3->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X); + set_frame(deck->maneuvre_4->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X); + set_frame(deck->maneuvre_5->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X); + set_frame(deck->maneuvre_6->card->frame, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X); } static void fill_deck(struct deck *deck) { @@ -194,30 +166,29 @@ static void fill_deck(struct deck *deck) { } static void shuffle_deck(struct deck *deck) { - struct stack **stack = NULL; - struct stack tmp; + struct card **card, tmp; int random; - if (!(stack = malloc(NUMBER_OF_CARDS * sizeof(*stack)))) { + if (!(card = malloc(NUMBER_OF_CARDS * sizeof(*card)))) { fprintf(stderr, tty_solitaire_error_message(errno, __FILE__, __LINE__)); exit(errno); } for (int i = 0; i < NUMBER_OF_CARDS; i++) { - stack[i] = pop(&(deck->stock)); + card[i] = pop(&(deck->stock)); } srand(time(NULL)); for (int i = 0; i < NUMBER_OF_CARDS - 1; i++) { random = i + (rand() % (NUMBER_OF_CARDS) - i); - tmp = (*stack[i]); - (*stack[i]) = (*stack[random]); - (*stack[random]) = tmp; + tmp = *card[i]; + *card[i] = (*card[random]); + *card[random] = tmp; } for (int i = 0; i < NUMBER_OF_CARDS; i++) { - push(&(deck->stock), stack[i]->card); + push(&(deck->stock), card[i]); } } diff --git a/lib/stack.c b/lib/stack.c index 5ba657e..450e8b6 100644 --- a/lib/stack.c +++ b/lib/stack.c @@ -33,7 +33,7 @@ struct stack *duplicate_stack(struct stack *stack) { push(&tmp_stack, duplicate_card(iterator->card)); } while (!empty(tmp_stack)) { - push(&new_stack, (pop(&tmp_stack))->card); + push(&new_stack, (pop(&tmp_stack))); } free_stack(tmp_stack); @@ -69,44 +69,40 @@ int length(struct stack *stack) { } void push(struct stack **stack, struct card *card) { - struct stack *new_stack; - if (card) { if (empty(*stack)) { - (*stack)->card = duplicate_card(card); + (*stack)->card = card; } else { + struct stack *new_stack; allocate_stack(&new_stack); - new_stack->card = duplicate_card(card); + new_stack->card = card; new_stack->next = (*stack); *stack = new_stack; } } } -struct stack *pop(struct stack **stack) { - struct stack *popped_entry = NULL; - - if(!empty(*stack)) { - allocate_stack(&popped_entry); - initialize_stack(popped_entry); - popped_entry->card = duplicate_card((*stack)->card); - popped_entry->next = NULL; +struct card *pop(struct stack **stack) { + if(empty(*stack)) { + return(NULL); + } else { + struct card *popped_card = (*stack)->card; if (length(*stack) == 1) { + /* Remembering the stack position before clearing it. */ + int begin_y = (*stack)->card->frame->begin_y; + int begin_x = (*stack)->card->frame->begin_x; + allocate_card(&((*stack)->card)); /* An empty stack is a stack with a blank top card * and with stack->next == NULL. */ - set_card((*stack)->card, - NO_VALUE, - NO_SUIT, - NO_FACE, - (*stack)->card->frame->begin_y, - (*stack)->card->frame->begin_x); + set_card((*stack)->card, NO_VALUE, NO_SUIT, NO_FACE, begin_y, begin_x); (*stack)->next = NULL; } else { + struct stack *tmp = *stack; *stack = (*stack)->next; + free(tmp); } + return(popped_card); } - - return(popped_entry); } struct stack *reverse(struct stack *stack) { diff --git a/lib/stack.h b/lib/stack.h index 1a3efec..395b3ee 100644 --- a/lib/stack.h +++ b/lib/stack.h @@ -15,7 +15,7 @@ void free_stack(struct stack *); bool empty(struct stack *); int length(struct stack *); void push(struct stack **, struct card *); -struct stack *pop(struct stack **); +struct card *pop(struct stack **); struct stack *reverse(struct stack *); #endif diff --git a/test/game_test.c b/test/game_test.c index 61a991c..22b0e6a 100644 --- a/test/game_test.c +++ b/test/game_test.c @@ -3,111 +3,6 @@ #include "../lib/game.h" #include "test_helper.h" -void test_move_card_from_empty_stack_to_empty_stack() { - struct stack *origin, *destination, - *new_origin, *new_destination, - *origin_duplicate, *destination_duplicate; - - allocate_stack(&origin); - allocate_stack(&destination); - initialize_stack(origin); - initialize_stack(destination); - new_origin = origin; - new_destination = destination; - origin_duplicate = duplicate_stack(origin); - destination_duplicate = duplicate_stack(destination); - move_card(&new_origin, &new_destination); - - assert(origin == new_origin); - assert(stacks_equal(origin, origin_duplicate)); - assert(destination == new_destination); - assert(stacks_equal(destination, destination_duplicate)); - - free_stack(origin); - free_stack(destination); -} - -void test_move_card_from_empty_stack_to_non_empty_stack() { - struct stack *origin, *destination, - *new_origin, *new_destination, - *origin_duplicate, *destination_duplicate; - struct card *card; - - allocate_card(&card); - initialize_card(card); - set_card(card, ACE, SPADES, EXPOSED, 0, 0); - - allocate_stack(&origin); - allocate_stack(&destination); - initialize_stack(origin); - initialize_stack(destination); - new_origin = origin; - new_destination = destination; - push(&new_destination, card); - origin_duplicate = duplicate_stack(origin); - destination_duplicate = duplicate_stack(destination); - move_card(&new_origin, &new_destination); - - assert(origin == new_origin); - assert(stacks_equal(origin, origin_duplicate)); - assert(destination == new_destination); - assert(stacks_equal(destination, destination_duplicate)); - - free_stack(origin); - free_stack(destination); -} - -void test_move_card_from_non_empty_stack_to_empty_stack() { - struct stack *origin, *destination; - struct card *card; - - allocate_card(&card); - initialize_card(card); - set_card(card, ACE, SPADES, EXPOSED, 0, 0); - - allocate_stack(&origin); - allocate_stack(&destination); - initialize_stack(origin); - initialize_stack(destination); - push(&origin, card); - move_card(&origin, &destination); - - assert(empty(origin)); - assert(length(destination) == 1); - assert(cards_equal(destination->card, card)); - - free_stack(origin); - free_stack(destination); -} - -void test_move_card_from_non_empty_stack_to_non_empty_stack() { - struct stack *origin, *destination; - struct card *card[2]; - - allocate_card(&card[0]); - allocate_card(&card[1]); - initialize_card(card[0]); - initialize_card(card[1]); - set_card(card[0], ACE, SPADES, EXPOSED, 99, 99); - set_card(card[1], KING, HEARTS, EXPOSED, 99, 99); - - allocate_stack(&origin); - allocate_stack(&destination); - initialize_stack(origin); - initialize_stack(destination); - push(&origin, card[0]); - push(&destination, card[1]); - move_card(&origin, &destination); - - assert(empty(origin)); - assert(length(destination) == 2); - assert(cards_equal(destination->card, card[0])); - assert(cards_equal(destination->next->card, card[1])); - - free_stack(origin); - free_stack(destination); -} - void test_valid_move_from_stock_to_stock() { struct stack *stock_0, *stock_1; @@ -491,6 +386,140 @@ void test_valid_move_from_maneuvre_stack_to_maneuvre_stacks() { } } +void test_move_card_from_empty_stack_to_empty_stack() { + struct stack *origin, *destination, + *new_origin, *new_destination, + *origin_duplicate, *destination_duplicate; + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + new_origin = origin; + new_destination = destination; + origin_duplicate = duplicate_stack(origin); + destination_duplicate = duplicate_stack(destination); + move_card(&new_origin, &new_destination); + + assert(origin == new_origin); + assert(stacks_equal(origin, origin_duplicate)); + assert(destination == new_destination); + assert(stacks_equal(destination, destination_duplicate)); + + free_stack(origin); + free_stack(destination); +} + +void test_move_card_from_empty_stack_to_non_empty_stack() { + struct stack *origin, *destination, + *new_origin, *new_destination, + *origin_duplicate, *destination_duplicate; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + new_origin = origin; + new_destination = destination; + push(&new_destination, card); + origin_duplicate = duplicate_stack(origin); + destination_duplicate = duplicate_stack(destination); + move_card(&new_origin, &new_destination); + + assert(origin == new_origin); + assert(stacks_equal(origin, origin_duplicate)); + assert(destination == new_destination); + assert(stacks_equal(destination, destination_duplicate)); + + free_stack(origin); + free_stack(destination); +} + +void test_move_card_from_non_empty_stack_to_empty_stack() { + struct stack *origin, *destination; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, TWO, DIAMONDS, EXPOSED, 0, 0); + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + push(&origin, card); + move_card(&origin, &destination); + + assert(empty(origin)); + assert(length(destination) == 1); + assert(cards_equal(destination->card, card)); + + free_stack(origin); + free_stack(destination); +} + +void test_move_card_from_non_empty_stack_to_non_empty_stack() { + struct stack *origin, *destination; + struct card *card[6]; + + for (int i = 0; i < 6; i++) { + allocate_card(&card[i]); + initialize_card(card[i]); + set_card(card[i], TWO + i, i % 5, i % 2, 99, 99); + } + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + for (int i = 0; i < 3; i++) { + push(&origin, card[i]); + } + for (int i = 3; i < 6; i++) { + push(&destination, card[i]); + } + move_card(&origin, &destination); + + assert(length(origin) == 2); + assert(length(destination) == 4); + assert(cards_equal(destination->card, card[2])); + assert(cards_equal(destination->next->card, card[5])); + + free_stack(origin); + free_stack(destination); +} + +void test_move_card_should_not_change_empty_stack_coordinates() { + struct stack *origin, *destination; + struct card *card[2]; + + allocate_card(&card[0]); + allocate_card(&card[1]); + initialize_card(card[0]); + initialize_card(card[1]); + set_card(card[0], ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X); + set_card(card[1], KING, HEARTS, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X); + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + push(&origin, card[0]); + push(&destination, card[1]); + move_card(&origin, &destination); + + assert(origin->card->frame->begin_y == MANEUVRE_BEGIN_Y); + assert(origin->card->frame->begin_x == MANEUVRE_0_BEGIN_X); + + free_stack(origin); + free_stack(destination); +} + void test_game() { test_valid_move_from_stock_to_stock(); test_valid_move_from_stock_to_waste_pile(); @@ -513,4 +542,5 @@ void test_game() { test_move_card_from_empty_stack_to_non_empty_stack(); test_move_card_from_non_empty_stack_to_empty_stack(); test_move_card_from_non_empty_stack_to_non_empty_stack(); + test_move_card_should_not_change_empty_stack_coordinates(); } diff --git a/test/stack_test.c b/test/stack_test.c index 1839a50..2552f89 100644 --- a/test/stack_test.c +++ b/test/stack_test.c @@ -156,22 +156,21 @@ void test_push_null_on_non_empty_stack() { void test_pop_on_empty_stack() { struct stack *stack; - struct stack *popped_entry; + struct card *popped_card; allocate_stack(&stack); - allocate_stack(&popped_entry); initialize_stack(stack); - popped_entry = pop(&stack); + popped_card = pop(&stack); assert(empty(stack)); - assert(!popped_entry); + assert(!popped_card); free_stack(stack); } void test_pop_on_stack_with_one_element() { - struct stack *stack, *popped_entry; - struct card *card; + struct stack *stack; + struct card *card, *popped_card; allocate_card(&card); initialize_card(card); @@ -180,18 +179,17 @@ void test_pop_on_stack_with_one_element() { allocate_stack(&stack); initialize_stack(stack); push(&stack, card); - popped_entry = pop(&stack); + popped_card = pop(&stack); assert(empty(stack)); - assert(cards_equal(popped_entry->card, card)); - assert(!popped_entry->next); + assert(popped_card == card); free_stack(stack); } void test_pop_on_stack_with_more_than_one_element() { - struct stack *stack, *old_stack_next, *popped_entry; - struct card *card[3]; + struct stack *stack, *old_stack_next; + struct card *card[3], *popped_card; allocate_stack(&stack); initialize_stack(stack); @@ -202,12 +200,11 @@ void test_pop_on_stack_with_more_than_one_element() { push(&stack, card[i]); } old_stack_next = stack->next; - popped_entry = pop(&stack); + popped_card = pop(&stack); assert(length(stack) == 2); assert(stack == old_stack_next); - assert(cards_equal(popped_entry->card, card[2])); - assert(!popped_entry->next); + assert(popped_card == card[2]); free_stack(stack); } @@ -262,7 +259,7 @@ void test_reverse_on_stack_with_more_than_one_element() { allocate_stack(&unreversed_stack); initialize_stack(unreversed_stack); for (int i = 0; i < 3; i++) { - push(&unreversed_stack, pop(&reversed_stack)->card); + push(&unreversed_stack, pop(&reversed_stack)); } assert(stacks_equal(unreversed_stack, old_stack));