当前位置: 首页 > 工具软件 > uno-game > 使用案例 >

某同学的期末大作业 UNO的简单实现

澹台正真
2023-12-01

这破玩意儿写了好久,代码又长又丑。

实在是拿不出手的东西。。。。而且估计还是有很多bug,从老哥结婚准备那天开始零零散散地写到现在,果然写代码战线拖太长不行啊。。。。

姑且写了很长, 在这里放出来

首先这是他们老师放出来的.h,代码之所以很乱也有原因是要实现他们老师要求的function!!!(其实是自己菜吧)

一个是对game的限制:

// The game of Final Card-Down. v1.1.2
//
// !!! DO NOT CHANGE THIS FILE !!!


#include "Card.h"

#ifndef GAME_H
#define GAME_H

#define NUM_PLAYERS 4

#define NOT_FINISHED -1
#define NO_WINNER 4

#define FALSE 0
#define TRUE (!FALSE)

typedef struct _game *Game;

typedef enum {
    // Clockwise is 0 -> 1 -> 2 -> 3 -> 0 ...
    CLOCKWISE,
    // Anticlockwise is 0 -> 3 -> 2 -> 1 -> 0 ...
    ANTICLOCKWISE
} direction;

typedef enum {
    // Draw a single card from the deck.
    DRAW_CARD,
    // Play a single card onto the discard pile.
    PLAY_CARD,
    // Say the word "UNO".
    SAY_UNO,
    // Say the word "DUO".
    SAY_DUO,
    // Say the word "TRIO".
    SAY_TRIO,
    // End the player's turn.
    END_TURN
} action;

typedef struct _playerMove {
    // Which action to play.
    action action;
    // Declare which color must be played on the next turn.
    // This is only used when playing a DECLARE.
    color nextColor;
    // Which card to play (only valid for PLAY_CARD).
    Card card;
} playerMove;

// Create a new game engine.
//
// This creates a game with a deck of the given size
// and the value, color, and suit of each card to be taken from
// each of the arrays in order.
//
// Your game will always have 4 players. Each player starts with a hand
// of 7 cards. The first card from the deck is given to player 0, the
// second to player 1, the third to player 2, the fourth to player 3,
// the fifth to player 0, and so on until each player has 7 cards.
Game newGame(int deckSize, value values[], color colors[], suit suits[]);


// Destroy an existing game.
//
// This should free all existing memory used in the game including
// allocations for players and cards.
void destroyGame(Game game);

// The following functions can be used by players to discover
// information about the state of the game.

// Get the number of cards that were in the initial deck.
int numCards(Game game);

// Get the number of cards in the initial deck of a particular
// suit.
int numOfSuit(Game game, suit suit);

// Get the number of cards in the initial deck of a particular color.
int numOfColor(Game game, color color);

// Get the number of cards in the initial deck of a particular value.
int numOfValue(Game game, value value);

// Get the number of the player whose turn it is.
int currentPlayer(Game game);

// Get the current turn number.
//
// The turn number increases after a player ends their turn.
// The turn number should start at 0 once the game has started.
int currentTurn(Game game);

// Get the number of points for a given player.
// Player should be between 0 and 3.
//
// This should _not_ be called by a player.
int playerPoints(Game game, int player);

// Get the current direction of play.
direction playDirection(Game game);

// This function returns the number of turns that have occurred in the
// game so far including the current turn.
// When using either the turnMoves or pastMove function,
// the turn number should be less than the number of moves that this
// function returns.
// (i.e. on turn 0 of the game, this should return 1, as there has been
// 1 turn so far including the current turn; if you called pastMove you
// would need to call it on turn 0, as this is the only possible value
// less than 1.)
int numTurns(Game game);

// Get the number of moves that happened on a turn.
//
// A turn may consist of multiple moves such as drawing cards,
// playing cards, and ending the turn.
int turnMoves(Game game, int turn);

// Look at a previous move from a specified turn.
playerMove pastMove(Game game, int turn, int move);

// Get the number of cards in a given player's hand.
int playerCardCount(Game game, int player);

// Get the number of cards in the current player's hand.
int handCardCount(Game game);

// View a card from the current player's own hand.
//
// The player should not need to free() this card,
// so you should not allocate or clone an existing card
// but give a reference to an existing card.
Card handCard(Game game, int card);

// Check if a given move is valid.
//
// If the last player played a 2 (DRAW_TWO),
// the next player must either play a 2
// or draw 2 cards.
// Otherwise, the player must play a card that is either a ZERO
// or that has the same color, value, or suit as the card on the top
// of the discard pile.
//
// If the player plays an ADVANCE, the next player's turn is skipped.
// If the player plays a BACKWARDS, the direction of play is reversed.
// If the player plays a CONTINUE, they may play another card.
// If the player plays a DECLARE, they must also state which color
// the next player's discarded card should be.
//
// A player can only play cards from their hand.
// A player may choose to draw a card instead of discarding a card.
// A player must draw a card if they are unable to discard a card.
//
// This check should verify that:
// * The card being played is in the player's hand
// * The player has played at least one card before finishing their turn,
//   unless a draw-two was played, in which case the player may not
//   play a card, and instead must draw the appropriate number of cards.
int isValidMove(Game game, playerMove move);

// Play the given action for the current player
//
// If the player makes the END_TURN move, their turn ends,
// and it becomes the turn of the next player.
//
// This should _not_ be called by the player AI.
void playMove(Game game, playerMove move);

// Check the game winner.
//
// Returns NOT_FINISHED if the game has not yet finished,
// 0-3, representing which player has won the game, or
// NO_WINNER if the game has ended but there was no winner.
int gameWinner(Game game);

#endif // GAME_H

一个是对card的一些限制:

// The playing card interface. v1.1.0
//
// !!! DO NOT CHANGE THIS FILE !!!
//
// This interface represents a single playing card
// in the game of Final Card-Down.

#ifndef CARD_H
#define CARD_H

typedef struct _card *Card;

// The various colors that a card can have.
typedef enum {
    RED,
    BLUE,
    GREEN,
    YELLOW,
    PURPLE
} color;

// The various suits that a card can have.
typedef enum {
    HEARTS,
    DIAMONDS,
    CLUBS,
    SPADES,
    QUESTIONS
} suit;

// The various values that a card can have.
typedef enum {
    ZERO,
    ONE,
    DRAW_TWO,
    THREE,
    FOUR,
    FIVE,
    SIX,
    SEVEN,
    EIGHT,
    NINE,
    ADVANCE,
    BACKWARDS,
    CONTINUE,
    DECLARE,
    E,
    F
} value;


// Create a new card.
// These values can only be set at creation time.
// The number should be between 0x0 and 0xF.
Card newCard(value value, color color, suit suit);

// Destroy an existing card.
void destroyCard(Card card);

// Get the card's suit (HEARTS, DIAMONDS, etc).
suit cardSuit(Card card);

// Get the card's number (0x0 through 0xF).
value cardValue(Card card);

// Get the card's color (RED, BLUE, etc).
color cardColor(Card card);

#endif // CARD_H

然后是我的破代码。。。。本来还需要写测试的,不过我就不写了哈哈哈!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include "Game.h"
#include "Card.h"
using namespace std;
#define MAX_DECK_SIZE 100
#define MAX_TURNS 100
#define MAX_MOVE 15
struct cardPile{
    int card[MAX_DECK_SIZE];
    int num;
};

struct _game{
    int deckSize;
    int numPlayers;
    int moveInTurn[MAX_TURNS];
    int nowPlayer;
    int lastPlayer;
    int isFirstTurn;
    int twoValue;
    int haveDraw;
    int havePlay;
    int haveSayUno;
    int haveSayDuo;
    int haveSayTrio;
    int lastForgetO;
    int noWinner;
    int points;
    int playerPoints[NUM_PLAYERS];
    int turns;
    playerMove *lastMove;
    playerMove *pastMoveRec[MAX_TURNS][MAX_MOVE];
    cardPile player[NUM_PLAYERS];
    cardPile disPile;
    direction nowDirection;
    color *colors;
    suit *suits;
    value *values;
};

struct _card{
    value value;
    color color;
    suit suit;
};

Card newCard(value value, color color, suit suit){
    Card card = (_card*)calloc(1, sizeof(_card));
    card->value = value;
    card->color = color;
    card->suit = suit;
    return card;
}

playerMove *newPlayerMove(){
    playerMove *p = (playerMove*)calloc(1, sizeof(playerMove));
    p->card = newCard(ZERO, RED, HEARTS);
    return p;
}

void destroyPlayerMove(playerMove *p){
    destroyCard(p->card);
    free(p);
}

Game newGame(int deckSize, value values[], color colors[], suit suits[]){
    Game nowGame = (_game*)calloc(1, sizeof(_game));
    nowGame->deckSize = deckSize;
    nowGame->disPile.num = 0;
    for(int i=0;i<NUM_PLAYERS;i++){
        nowGame->player[i].num = 0;
    }
    nowGame->turns = 0;
    nowGame->nowDirection = CLOCKWISE;
    nowGame->twoValue = 0;
    nowGame->nowPlayer = 0;
    nowGame->haveDraw = FALSE;
    nowGame->havePlay = FALSE;
    nowGame->haveSayUno = FALSE;
    nowGame->haveSayDuo = FALSE;
    nowGame->haveSayTrio = FALSE;
    nowGame->noWinner = FALSE;
    nowGame->points = 0;
    nowGame->lastMove = newPlayerMove();
    for(int i = 0; i<MAX_TURNS; i++){
        for(int j = 0; j<MAX_MOVE; j++){
            nowGame->pastMoveRec[i][j] = newPlayerMove();
        }
    }
    nowGame->values = values;
    nowGame->colors = colors;
    nowGame->suits = suits;
    return nowGame;
};

int isOver(Game game){
    if(game->noWinner == TRUE) return TRUE;
    int sum = 0;
    for(int i=0;i<NUM_PLAYERS;i++){
        sum += game->player[i].num;
    }
    if(sum==0) return TRUE;
    else return FALSE;
}
void dealCard(Game game){
    int i,j,k;
    k = 0, j = 0;
    int p = game->deckSize;
    for(i=0;i<28;i++){
        j = i%NUM_PLAYERS;
        game->player[j].card[k] = --p;
        ++game->player[j].num;
        if(j==3){
            ++k;
        }
    }
    game->deckSize -= 28;
    
}
void systemVoice(Game game){
    printf("Player %d's turn\n",game->nowPlayer);
    printf("you have %d cards,there are:\n",game->player[game->nowPlayer].num);
    printf("index: ");
    for(int i = 0;i<game->player[game->nowPlayer].num;i++){
        printf("%d ",game->player[game->nowPlayer].card[i]);
    }
    printf("\n");
    printf("value: ");
    for(int i = 0;i<game->player[game->nowPlayer].num;i++){
        printf("%d ",game->values[game->player[game->nowPlayer].card[i]]);
    }
    printf("\n");
    printf("color: ");
    for(int i = 0;i<game->player[game->nowPlayer].num;i++){
        printf("%d ",game->colors[game->player[game->nowPlayer].card[i]]);
    }
    printf("\n");
    printf("suit:  ");
    for(int i = 0;i<game->player[game->nowPlayer].num;i++){
        printf("%d ",game->suits[game->player[game->nowPlayer].card[i]]);
    }
    printf("\n");
    printf("Please select your action: \n");
    printf("0: DRAW_CARD\n1:PLAY_CARD\n2:SAY_UNO\n3:SAY_DUO\n4:SAY_TRIO\n5:END_TURN\n");
}

int drawACard(Game game, int playerIndex){
    int numOfMyCards = game->player[playerIndex].num;
    if(game->deckSize > 0){
        game->player[playerIndex].card[numOfMyCards++] = game->deckSize - 1;
        game->deckSize -= 1;
        game->player[playerIndex].num = numOfMyCards;
        return TRUE;
    }else if(game->disPile.num > 0){
        game->player[playerIndex].card[numOfMyCards++] = game->disPile.card[game->disPile.num - 1];
        game->disPile.num -= 1;
        game->player[playerIndex].num = numOfMyCards;
        return TRUE;
    }else{
        return FALSE;
    }
}

void discard(Game game, int playerIndex, int cardIndex){
    int numOfDispile = game->disPile.num;
    int numOfCardsOnHand = game->player[playerIndex].num;
    game->disPile.card[numOfDispile++] = cardIndex;
    for(int i = 0; i<numOfCardsOnHand; i++){
        if(game->player[playerIndex].card[i] == cardIndex){
            for(int j = i+1; j < numOfCardsOnHand; j++){
                game->player[playerIndex].card[j-1] = game->player[playerIndex].card[j];
            }
        }
    }
    game->disPile.num = numOfDispile;
    game->player[playerIndex].num = numOfCardsOnHand - 1;
}

void copyLastMove(Game game, playerMove &move){
    game->lastMove->action = PLAY_CARD;
    game->lastMove->card->value = move.card->value;
    game->lastMove->card->color = move.card->color;
    game->lastMove->card->suit = move.card->suit;
}


int isValidMove(Game game, playerMove move){
    if(game->lastMove->card->value == ADVANCE){
        if(move.action == END_TURN){
            game->isFirstTurn = TRUE;
            return TRUE;
        }
        printf("This turn you are been skipped ...invalid action!\n");
        return FALSE;
    }
    if(move.action == PLAY_CARD){
        if(game->havePlay != FALSE){
            printf("You have no change to play.... invalid action\n");
            return FALSE;
        }
        if(game->haveDraw == TRUE){
            printf("You can't played now.... invalid action\n");
            return FALSE;
        }
        
        if(game->lastMove->card->value == DRAW_TWO){
            if(move.card->value != DRAW_TWO){
                printf("You can only play card whose value is 2, or draw %d cards\n", game->twoValue);
                return FALSE;
            }else{
                game->twoValue += 2;
                game->havePlay = TRUE;
                copyLastMove(game, move);
                return TRUE;
            }
        }else if(game->lastMove->card->value == DECLARE){
            if(move.card->color != game->lastMove->nextColor){
                printf("You can't play this color\n");
                return FALSE;
            }else{
                copyLastMove(game, move);
                game->havePlay = TRUE;
                return TRUE;
            }
        }
        
        if(game->lastMove->card->value == move.card->value || game->lastMove->card->color == move.card->suit || game->lastMove->card->suit == move.card->suit || game->isFirstTurn || move.card->value == ZERO){
            copyLastMove(game, move);
            if(game->isFirstTurn == TRUE){
                game->isFirstTurn = FALSE;
            }
            if(move.card->value == DRAW_TWO){
                game->havePlay = TRUE;
                game->twoValue += 2;
                return TRUE;
            }else if(move.card->value == ADVANCE){
                game->havePlay = TRUE;
                return TRUE;
            }else if(move.card->value == BACKWARDS){
                game->nowDirection = (direction)(!game->nowDirection);
                game->havePlay = TRUE;
                return TRUE;
            }else if(move.card->value == CONTINUE){
                game->haveDraw = -1; //fuck up... For the Draw action
                game->isFirstTurn = TRUE;
                return TRUE;
            }else if(move.card->value == DECLARE){
                copyLastMove(game, move);
                game->havePlay = TRUE;
                return TRUE;
            }else{
                game->havePlay = TRUE;
                return TRUE;
            }
        }else{
            printf("What are you thinking? Invalid card\n");
            return FALSE;
        }
    }else if(move.action == DRAW_CARD){
        if(game->haveDraw == TRUE && game->twoValue == 0){
            printf("You have drawed... invalid action\n");
            return FALSE;
        }
        if(game->haveDraw == -1 || game->havePlay == TRUE){
            printf("You have chosen to play card... invalid action\n");
            return FALSE;
        }
        game->haveDraw = TRUE;
        if(drawACard(game, game->nowPlayer)){
            if(game->twoValue>0){
                -- game->twoValue;
            }
            return TRUE;
        }else{
            printf("No cards left....No winner\n");
            return -1; //No winner;
        }
            
        
    }else if(move.action == SAY_UNO){
        game->haveSayUno = TRUE;
        if(game->lastForgetO == 1){
            for(int i = 1; i<=2;i++){
                drawACard(game, game->lastPlayer);
            }
        }
        printf("UNO!!\n");
        return TRUE;
    }else if(move.action == SAY_DUO){
        game->haveSayDuo = TRUE;
        if(game->lastForgetO == 2){
            for(int i=1; i<=2; i++){
                drawACard(game, game->lastPlayer);
            }
        }
        printf("DUO!!\n");
        return TRUE;
    }else if(move.action == SAY_TRIO){
        game->haveSayTrio = TRUE;
        if(game->lastForgetO == 3){
            for(int i=1; i<=2; i++){
                drawACard(game, game->lastPlayer);
            }
        }
    }else{
        if(game->havePlay==FALSE && game->haveDraw == FALSE){
            printf("Nothong has been done\n");
            return FALSE;
        }
        return 2;
    }
    
    printf("wtf?!\n");
    return FALSE;
}

void initBeforeMove(Game game){
    game->haveDraw = FALSE;
    game->havePlay = FALSE;
    game->haveSayUno = FALSE;
    game->haveSayDuo = FALSE;
    game->haveSayTrio = FALSE;
}

void playMove(Game game, playerMove move){
    //emmmmmmmmmmmmm
}

void copyMove(playerMove *a, playerMove *b){
    a->action = b->action;
    a->nextColor = b->nextColor;
    a->card = b->card;
}

void makeMove(Game game){
    int isOver = FALSE;
    playerMove *nowMove = newPlayerMove();
    int num, flag, cardIndex;
    initBeforeMove(game);
    while (isOver == FALSE) {
        if(game->player[game->nowPlayer].num == 0){
            printf("No cards! Congarduations\n");
            game->playerPoints[game->nowPlayer] = game->points++;
            break;
        }
        systemVoice(game);
        scanf("%d",&nowMove->action);
        if(nowMove->action==PLAY_CARD){
            printf("pelase input the index of the card\n");
            scanf("%d",&num);
            cardIndex = num;
            nowMove->card->color = game->colors[num];
            nowMove->card->suit = game->suits[num];
            nowMove->card->value = game->values[num];
            nowMove->action = PLAY_CARD;
            if(game->values[num] == DECLARE){
                printf("Please select the color which the next player need to play\n");
                printf("0:RED, 1:BLUE, 2:GREEN, 3:YELLOW, 4:PURPLE\n");
                while(scanf("%d", &num)&&(num<0||num>4)){
                    printf("invalid color!\n");
                }
                nowMove->nextColor = (color)num;
            }
            flag = isValidMove(game, *nowMove);
            if(flag == TRUE){
                discard(game, game->nowPlayer, cardIndex);
            }
        }else{
            flag = isValidMove(game, *nowMove);
            if(flag == -1){
                game->noWinner = TRUE;
            }else if(flag == 2){
                isOver = TRUE;
            }
        }
        copyMove(game->pastMoveRec[game->turns][game->moveInTurn[game->turns]], nowMove);
        ++(game->moveInTurn[game->turns]);
    }
    if(game->player[game->nowPlayer].num == 1 && game->haveSayUno == FALSE){
        game->lastForgetO = 1;
    }else if(game->player[game->nowPlayer].num == 2 && game->haveSayDuo == FALSE){
        game->lastForgetO = 2;
    }else if(game->player[game->nowPlayer].num == 3 && game->haveSayTrio == FALSE){
        game->lastForgetO = 3;
    }
    destroyPlayerMove(nowMove);
}
void playGame(Game game){
    dealCard(game);
    printf("Welcome to Uno World, the loser will go die\n");
    game->isFirstTurn = TRUE;
    game->lastMove->card->value = ZERO, game->lastMove->card->color = RED, game->lastMove->card->suit = HEARTS;
    game->twoValue = 0;
    while(!isOver(game)){
        makeMove(game);
        int add;
        if(game->nowDirection == CLOCKWISE) add = 1;
        else add = -1;
        game->nowPlayer = (game->nowPlayer + add + NUM_PLAYERS)%NUM_PLAYERS;
        game->turns++;
    }
    printf("The game is over\n");
}

void destroyCard(Card card){
    free(card);
}

suit cardSuit(Card card){
    return card->suit;
}

value cardValue(Card card){
    return card->value;
}

color cardColor(Card card){
    return card->color;
}

void destroyGame(Game game){
    destroyPlayerMove(game->lastMove);
    for(int i = 0; i<MAX_TURNS; i++){
        for(int j = 0; j<MAX_MOVE; j++){
            destroyPlayerMove(game->pastMoveRec[i][j]);
        }
    }
    free(game);
}

int numCards(Game game){
    return game->deckSize;
}

int numOfSuit(Game game, suit suit){
    int sum = 0;
    for(int i = 0; i<game->deckSize; i++){
        if(game->suits[i] == suit){
            ++sum;
        }
    }
    return sum;
}

int numOfColor(Game game, color color){
    int sum = 0;
    for(int i = 0; i<game->deckSize; i++){
        if(game->colors[i] == color){
            ++sum;
        }
    }
    return sum;
}

int numOfValue(Game game, value value){
    int sum = 0;
    for(int i = 0; i<game->deckSize; i++){
        if(game->values[i] == value){
            ++sum;
        }
    }
    return sum;
}

int currentPlayer(Game game){
    return game->nowPlayer;
}
int currentTurn(Game game){
    return game->turns;
}
int playerPoints(Game game, int player){
    return game->playerPoints[player];
}

direction playDirection(Game game){
    return game->nowDirection;
}

int numTurns(Game game){
    return game->turns + 1;
}

int turnMoves(Game game, int turn){
    return game->moveInTurn[turn];
}

playerMove pastMove(Game game, int turn, int move){
    return *game->pastMoveRec[turn][move];
}

int playerCardCount(Game game, int player){
    return game->player[player].num;
}

int handCardCount(Game game){
    return game->player[game->nowPlayer].num;
}

Card handCard(Game game, int card){
    int index;
    for(int i = 0; i<game->player[game->nowPlayer].num; i++){
        if(i==card){
            index =  game->player[game->nowPlayer].card[i];
        }
    }
    Card ca = newCard(game->values[index], game->colors[index], game->suits[index]);
    return ca;
}

int gameWinner(Game game){
    for(int i = 0; i<NUM_PLAYERS; i++){
        if(game->playerPoints[i] == 0){
            return i;
        }
    }
    return NO_WINNER;
}



int main(){
    value a[50];
    color b[50];
    suit c[50];
    for(int i = 0; i<30; i++){
        scanf("%d",a+i);
    }
    for(int i = 0; i<30; i++){
        scanf("%d",b+i);
    }
    for(int i = 0; i<30; i++){
        scanf("%d",c+i);
    }
    Game killme = newGame(30, a, b, c);
    playGame(killme);
    destroyGame(killme);
    
    return 0;
}






 类似资料: