Make stack#pop return a card and don't duplicate stuff on push/pop.

This commit is contained in:
Murilo Pereira 2011-05-29 15:19:00 -03:00
parent 6282cf8ee2
commit b94ea8797a
7 changed files with 196 additions and 207 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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]);
}
}

View File

@ -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) {

View File

@ -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

View File

@ -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();
}

View File

@ -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));