From 1169992d50ce930143efe2851d02e7dfa0304e29 Mon Sep 17 00:00:00 2001 From: Ian C Date: Fri, 21 Dec 2018 11:27:26 +0000 Subject: Split code up into separate objects. --- csol.c | 833 +---------------------------------------------------------------- 1 file changed, 4 insertions(+), 829 deletions(-) (limited to 'csol.c') diff --git a/csol.c b/csol.c index f07e755..1abfcc9 100644 --- a/csol.c +++ b/csol.c @@ -23,840 +23,15 @@ */ #include -#include #include -#include -#include #include #include -typedef enum -{ - NoSuit = 0, - Heart = 'H', - Diamond = 'D', - Club = 'C', - Spade = 'S' -} Suit; - -typedef struct -{ - int value; - Suit suit; -} Card; - -typedef Card Deck[52]; - -typedef struct -{ - int no; - Card *card; -} Pile; - -static void Fatal(const char *p) -{ - endwin(); - fprintf(stderr, "%s\n", p); - exit(EXIT_FAILURE); -} - -static void Init(Deck deck) -{ - int i = 0; - int f; - - for(f=1; f < 14; f++) - { - deck[i].suit = Heart; - deck[i++].value = f; - - deck[i].suit = Diamond; - deck[i++].value = f; - - deck[i].suit = Club; - deck[i++].value = f; - - deck[i].suit = Spade; - deck[i++].value = f; - } -} - -static void Shuffle(Deck deck) -{ - int f; - - for(f = 0; f < 1000; f++) - { - int c1 = rand() % 52; - int c2 = rand() % 52; - Card c; - - c = deck[c1]; - deck[c1] = deck[c2]; - deck[c2] = c; - } -} - -static void AddToPile(Pile *pile, Card card) -{ - pile->no++; - - pile->card = realloc(pile->card, sizeof *pile->card * pile->no); - - if (!pile->card) - { - Fatal("Failed to reallocate memory"); - } - else - { - pile->card[pile->no - 1] = card; - } -} - -static void InsertBottomOfPile(Pile *pile, Card card) -{ - pile->no++; - - pile->card = realloc(pile->card, sizeof *pile->card * pile->no); - - if (!pile->card) - { - Fatal("Failed to reallocate memory"); - } - else - { - int f; - - for(f = pile->no - 1; f > 0; f--) - { - pile->card[f] = pile->card[f - 1]; - } - - pile->card[0] = card; - } -} - -static Card PopPile(Pile *pile) -{ - Card c = {0}; - - if (pile->no) - { - c = pile->card[pile->no - 1]; - - pile->no--; - - if (pile->no) - { - pile->card = realloc(pile->card, sizeof *pile->card * pile->no); - - if (!pile->card) - { - Fatal("Failed to reallocate memory"); - } - } - else - { - free(pile->card); - pile->card = NULL; - } - } - else - { - free(pile->card); - pile->card = NULL; - } - - return c; -} - -static Card TopOfPile(Pile *pile) -{ - Card c = {0}; - - if (pile->no) - { - c = pile->card[pile->no - 1]; - } - - return c; -} - -static void MoveTopCard(Pile *from, Pile *to) -{ - Card c; - - if (from->no) - { - c = PopPile(from); - AddToPile(to, c); - } -} - -static void SwapPile(Pile *a, Pile *b) -{ - Pile t; - - t = *a; - *a = *b; - *b = t; -} - -static void FreePile(Pile *p) -{ - if (p->card) - { - free(p->card); - p->card = NULL; - } -} - -static void Centre(int y, const char *p) -{ - size_t l = strlen(p); - - mvaddstr(y, COLS / 2 - l / 2, p); -} - -static const char *CardName(Card c) -{ - static char buff[32]; - static const char *num[]= - { - "ERR", - " A", - " 2", - " 3", - " 4", - " 5", - " 6", - " 7", - " 8", - " 9", - "10", - " J", - " Q", - " K" - }; - - sprintf(buff, "%s%c", num[c.value], c.suit); - - return buff; -} - -static void DrawCard(int y, int x, int face_down, Card c) -{ - if (c.suit == NoSuit) - { - mvaddstr(y, x, " "); - } - else - { - if (face_down) - { - mvaddstr(y, x, "###"); - } - else - { - if (c.suit == Spade || c.suit == Club) - { - attron(A_REVERSE); - } - - mvaddstr(y, x, CardName(c)); - - if (c.suit == Spade || c.suit == Club) - { - attroff(A_REVERSE); - } - } - } -} - -static double DRand() -{ - return (double)(rand() % 1000) / 1000.0; -} - -static void WinScreen() -{ - static const char *text[] = - { - "# # ## # # # # ## # #", - " # # # # # # # # # # ## #", - " # # # # # # # # # # # ##", - " # # # # # ## ## # # # #", - " # ## ## # # ## # #", - NULL, - }; - - static const int NO_STAR = 100; - - typedef struct - { - double x,y,yi; - } Star; - - Star *star; - - int f; - - star = malloc(sizeof *star * NO_STAR); - - if (!star) - { - Fatal("Memory allocation failed"); - } - - for(f = 0; f < NO_STAR; f++) - { - star[f].x = rand() % COLS; - star[f].y = rand() % LINES; - - do - { - star[f].yi = DRand() * 2; - } while(star[f].yi == 0); - } - - halfdelay(1); - - erase(); - - while(getch() != ' ') - { - for(f = 0; f < NO_STAR; f++) - { - mvaddch(star[f].y, star[f].x, ' '); - - star[f].y -= star[f].yi; - - if (star[f].y < 0) - { - star[f].x = rand() % COLS; - star[f].y = LINES - 1; - - do - { - star[f].yi = DRand() * 2; - } while(star[f].yi == 0); - } - } - - for(f = 0; f < NO_STAR; f++) - { - mvaddch(star[f].y, star[f].x, '.'); - } - - for(f = 0 ; text[f]; f++) - { - int x = COLS / 2 - strlen(text[f]) / 2; - int i; - - for(i = 0; text[f][i]; i++) - { - if (text[f][i] != ' ') - { - mvaddch(f + 4, x++, text[f][i]); - } - else - { - x++; - } - } - } - - Centre(f + 7, "PRESS SPACE"); - - refresh(); - } - - nocbreak(); - cbreak(); - erase(); - - free(star); -} - -static int CanCardSitOnTop(Card card, Card on) -{ - int ret = FALSE; - - if (card.suit != NoSuit && on.suit != NoSuit) - { - if (card.value == on.value - 1) - { - switch(card.suit) - { - case Spade: - case Club: - ret = (on.suit == Heart || on.suit == Diamond); - break; - - case Heart: - case Diamond: - ret = (on.suit == Spade || on.suit == Club); - break; - - case NoSuit: - break; - } - } - } - - return ret; -} - -static int PutCardOnSuitPile(Pile *from, Pile *hearts, Pile *diamonds, - Pile *spades, Pile *clubs) -{ - Card c; - Pile *p; - int move = FALSE; - - c = TopOfPile(from); - - if (c.suit != NoSuit) - { - switch(c.suit) - { - case Heart: - p = hearts; - break; - case Diamond: - p = diamonds; - break; - case Spade: - p = spades; - break; - case Club: - p = clubs; - break; - default: - p = NULL; - break; - } - - if (p->no) - { - if (c.value == TopOfPile(p).value + 1) - { - move = TRUE; - } - } - else - { - if (c.value == 1 ) - { - move = TRUE; - } - } - - if (move) - { - MoveTopCard(from, p); - } - } - - return move; -} - -static void RevealCard(Pile *column_down, Pile *column_up) -{ - if (column_up->no == 0) - { - if (column_down->no) - { - InsertBottomOfPile(column_up, PopPile(column_down)); - } - } -} - -static void KlondikeHelp(void) -{ - static const char *text[] = - { - "Use the cursor keys to move the cursor around.", - "", - "Press RETURN to select a bunch of cards to move.", - "Press RETURN again when you are where you want to move the cards.", - "", - "Use space to draw the next set of cards.", - "", - "Use 'S' to move a card from the drawn cards to the current column.", - "", - "Use 'P' to put the current card on the suits piles.", - "If invalid it will attempt to move the card from the drawn pile.", - "", - "Press '1', '2', '3' or '4' to move the top card from the hearts, ", - "diamonds, spades or clubs suit pile respectively back onto the board.", - "", - "Press 'Q' to quit. You'll be asked if you want to see the cards.", - "", - "", - "Press SPACE to continue.", - NULL - }; - - int y = 2; - int f; - - erase(); - - for(f = 0; text[f]; f++) - { - Centre(y++, text[f]); - } - - refresh(); - - while(getch() != ' '); -} - -static void Klondike(int draw) -{ - Deck deck; - Pile pile = {0}; - Pile turned = {0}; - Pile hearts = {0}; - Pile diamonds = {0}; - Pile clubs = {0}; - Pile spades = {0}; - Pile column_down[7] = {{0}}; - Pile column_up[7] = {{0}}; - int f; - int n; - int i; - int won = FALSE; - int quit = FALSE; - int show = FALSE; - int pos_x = 0; - int pos_y = 0; - int move_pos_x = -1; - int move_pos_y = -1; - - Init(deck); - Shuffle(deck); - - i = 0; - - for(f = 0; f < 7; f++) - { - for(n = 0; n < f; n++) - { - AddToPile(&column_down[f], deck[i++]); - } - - AddToPile(&column_up[f], deck[i++]); - } - - while(i < 52) - { - AddToPile(&pile, deck[i++]); - } - - while(!quit && !won) - { - Card c = {0}; - int key = 0; - - erase(); - - DrawCard(0, 0, TRUE, TopOfPile(&pile)); - DrawCard(0, 4, FALSE, TopOfPile(&turned)); - - DrawCard(0, 10, FALSE, TopOfPile(&hearts)); - DrawCard(0, 15, FALSE, TopOfPile(&diamonds)); - DrawCard(0, 20, FALSE, TopOfPile(&spades)); - DrawCard(0, 25, FALSE, TopOfPile(&clubs)); - - for(f = 0; f < 7; f++) - { - for(n = 0; n < column_down[f].no; n++) - { - DrawCard(2 + n, 1 + f * 5, TRUE, column_down[f].card[n]); - } - - for(n = 0; n < column_up[f].no; n++) - { - DrawCard(2 + column_down[f].no + n, 1 + f * 5, - FALSE, column_up[f].card[n]); - } - } - - if (move_pos_x != -1) - { - mvaddch(2 + column_down[move_pos_x].no + move_pos_y, - move_pos_x * 5, '*'); - mvaddch(2 + column_down[move_pos_x].no + move_pos_y, - move_pos_x * 5 + 4, '*'); - } - - if (!column_up[pos_x].no && !column_down[pos_x].no) - { - mvaddch(2, pos_x * 5, '>'); - mvaddch(2, pos_x * 5 + 4, '<'); - } - else - { - mvaddch(2 + column_down[pos_x].no + pos_y, pos_x * 5, '>'); - mvaddch(2 + column_down[pos_x].no + pos_y, pos_x * 5 + 4, '<'); - } - - if (hearts.no == 13 && diamonds.no == 13 && - spades.no == 13 && clubs.no == 13) - { - won = TRUE; - } - - refresh(); - - if (!won) - { - key = getch(); - } - - switch(key) - { - case ' ': - if (pile.no) - { - for(f = 0; f < draw; f++) - { - MoveTopCard(&pile, &turned); - } - } - else - { - SwapPile(&pile, &turned); - } - break; - - case 'S': - case 's': - c = TopOfPile(&turned); - - if (c.value == 13 && column_up[pos_x].no == 0 && - column_down[pos_x].no == 0) - { - MoveTopCard(&turned, &column_up[pos_x]); - } - else - { - if (CanCardSitOnTop(c, TopOfPile(&column_up[pos_x]))) - { - MoveTopCard(&turned, &column_up[pos_x]); - pos_y++; - } - } - break; - - case 'P': - case 'p': - if (PutCardOnSuitPile(&column_up[pos_x], - &hearts, &diamonds, &spades, &clubs)) - { - RevealCard(&column_down[pos_x], &column_up[pos_x]); - - pos_y--; - - if (pos_y < 0) - { - pos_y = 0; - } - } - else - { - PutCardOnSuitPile(&turned, &hearts, &diamonds, - &spades, &clubs); - } - break; - - case 'Q': - case 'q': - { - int k; - - quit = TRUE; - Centre(LINES-1, "Show cards?"); - refresh(); - k = getch(); - show = (k == 'y' || k == 'Y'); - break; - } - - case 10: - if (move_pos_x == -1) - { - move_pos_x = pos_x; - move_pos_y = pos_y; - } - else - { - int can_move = FALSE; - - if (column_up[move_pos_x].no && - column_up[move_pos_x].card[move_pos_y].value == 13 && - column_up[pos_x].no == 0 && column_down[pos_x].no == 0) - { - can_move = TRUE; - } - else - { - if (column_up[move_pos_x].no && - CanCardSitOnTop - (column_up[move_pos_x].card[move_pos_y], - TopOfPile(&column_up[pos_x]))) - { - can_move = TRUE; - } - } - - if (can_move) - { - Pile temp = {0}; - - while(column_up[move_pos_x].no > move_pos_y) - { - MoveTopCard(&column_up[move_pos_x], - &temp); - } - - while(temp.no) - { - MoveTopCard(&temp, - &column_up[pos_x]); - } - - RevealCard(&column_down[move_pos_x], - &column_up[move_pos_x]); - } - - move_pos_x = -1; - move_pos_y = -1; - } - break; - - case '1': - if (CanCardSitOnTop(TopOfPile(&hearts), - TopOfPile(&column_up[pos_x]))) - { - MoveTopCard(&hearts, &column_up[pos_x]); - } - break; - - case '2': - if (CanCardSitOnTop(TopOfPile(&diamonds), - TopOfPile(&column_up[pos_x]))) - { - MoveTopCard(&diamonds, &column_up[pos_x]); - } - break; - - case '3': - if (CanCardSitOnTop(TopOfPile(&spades), - TopOfPile(&column_up[pos_x]))) - { - MoveTopCard(&spades, &column_up[pos_x]); - } - break; - - case '4': - if (CanCardSitOnTop(TopOfPile(&clubs), - TopOfPile(&column_up[pos_x]))) - { - MoveTopCard(&clubs, &column_up[pos_x]); - } - break; - - case KEY_LEFT: - if (pos_x) - { - pos_x--; - pos_y = column_up[pos_x].no - 1; - - if (pos_y < 0) - { - pos_y = 0; - } - } - break; - - case KEY_RIGHT: - if (pos_x < 6) - { - pos_x++; - pos_y = column_up[pos_x].no - 1; - - if (pos_y < 0) - { - pos_y = 0; - } - } - break; - - case KEY_UP: - if (pos_y) - { - pos_y--; - } - break; - - case KEY_DOWN: - if (pos_y < column_up[pos_x].no - 1) - { - pos_y++; - } - break; - - case '?': - KlondikeHelp(); - break; - - default: - break; - } - } - - if (show) - { - for(f = 0; f < 7; f++) - { - for(n = 0; n < column_down[f].no; n++) - { - DrawCard(2 + n, 1 + f * 5, FALSE, column_down[f].card[n]); - } - - for(n = 0; n < column_up[f].no; n++) - { - DrawCard(2 + column_down[f].no + n, 1 + f * 5, - FALSE, column_up[f].card[n]); - } - } - - Centre(LINES - 1, "Press any key"); - refresh(); - getch(); - } - - if (won) - { - WinScreen(); - } - - FreePile(&pile); - FreePile(&turned); - FreePile(&hearts); - FreePile(&diamonds); - FreePile(&clubs); - FreePile(&spades); - for(f = 0; f < 7; f++) - { - FreePile(&column_down[f]); - FreePile(&column_up[f]); - } -} +#include "deck.h" +#include "pile.h" +#include "util.h" +#include "klondike.h" int main(int argc, char *argv[]) { -- cgit v1.2.3