0

I made a simple command line application based on Kaiji Ep. 16 that mimics the game Emperor Card (for our midterms in basic programming). I got stuck on what I think is a simple problem, but I can't seem to solve it on my own. I have this function "winChecker(List *root, Node *head)," that checks what cards are drawn and who wins over who.

And it seems that it returns a wrong return value whenever I draw Citizen and the opponent draws Citizen as well. It should just loop, since Citizen vs Citizen is draw, according to my code.

Can you help me understand what I'm doing wrong here. Also if you see some other mistakes, feel free to point them out. I'm open to learn.

PS: I only used struct for Node and List since we aren't allowed to use Class for our midterms yet. I got 1 header file for each of those.

Source.cpp

    #include "Node.h"
#include "List.h"
#include <iostream>
#include <string>
#include <ctime>

using namespace std;

Node *createKaijiDeck(int round);
Node *selectKaijiCard(Node *head, int index);
Node *deleteSelectedKaijiCard(Node *head, int index);
List* createTonegawaDeck(int round);
List *selectTonegawaCard(List *root, int indexT);
List *deleteSelectedTonegawaCard(List *root, int indexT);
bool betCheck(int betLength, int remainingLength);
int prizeCheck(int betLength, int round);
void printDeck(Node * head);
int winCheck(List *root, Node *head, int cardIndex, int randTonegawa);
void gameOver(int cash, int round, int input, int remaining);

int main() {

    // Seed the RNG
    srand((unsigned int)time(0));

    // Initilizing variables
    int input, cardIndex, randTonegawa, countTonegawa = 0, cash = 0, remaining = 30;

    // Round loop
    for (int round = 1; round < 12; round++) {

        cout << "===============================================" << endl;
        cout << "                ROUND " << round << endl;
        cout << "===============================================" << endl;
        cout << "How much would you like to bet, in milimeters?" << endl;
        cout << "(You still have " << remaining << " milimeters left.)" << endl;
        cin >> input;
        betCheck(input, remaining);

        // Match loop
        if (betCheck(input, remaining) == true) {

            cout << "You can win " << prizeCheck(input, round) << " Yen." << endl << endl;
            cout << "Cash currently at hand: " << cash << endl;
            Node* head = createKaijiDeck(round);
            List* root = createTonegawaDeck(round);
            do {
                printDeck(head);

                cout << "Select a card to play [1 - 5]: ";
                cin >> cardIndex;
                randTonegawa = (rand() % (5 - countTonegawa));
                Node* selectKaijiCardAtIndex = selectKaijiCard(head, cardIndex);
                cout << "You chose the card: " << selectKaijiCardAtIndex->cards << endl;
                List* selectTonegawaCardAtIndex = selectTonegawaCard(root, randTonegawa);
                cout << "Tonegawa chose the card: " << selectTonegawaCardAtIndex->card << endl;
                cout << endl;
                countTonegawa++;
            } while (winCheck(root, head, cardIndex, randTonegawa) == 0);

            // Match up checker (Emperor > Citizen > Slave > Emperor)
            if (winCheck(root, head, cardIndex, randTonegawa) == 1) {

                cash = cash + prizeCheck(input, round);
                cout << "Round " << round << " winner is Kaiji." << endl;
                cout << "You won " << prizeCheck(input, round) << " Yen!" << endl;
            }
            else if (winCheck(root, head, cardIndex, randTonegawa) == 2) {

                remaining = remaining - input;
                cout << "Round " << round << " winner is Tonegawa." << endl;
                cout << "The pin moved by " << input << " milimeters!" << endl;
            }

        }
        else if (betCheck(input, remaining) == false)
        {
            cout << "You lose! You already lost your ear!" << endl;
            system("pause");
            exit(0);
        }
    }
    return 0;
}

Node *createKaijiDeck(int round) {

    Node* head = NULL;
    Node* curr = NULL;
    Node* prev = NULL;

    if (round == 1 || round == 2 || round == 3 || round == 7 || round == 8 || round == 9) {
        curr = new Node;
        curr->cards = "Emperor";
        prev = curr;
        head = curr;

        for (int i = 0; i < 3; i++) {

            curr = new Node;
            curr->cards = "Citizen";
            prev->next = curr;
            prev = curr;
        }

        curr = new Node;
        curr->cards = "Citizen";
        prev->next = curr;

    }

    if (round == 4 || round == 5 || round == 6 || round == 10 || round == 11 || round == 12) {
        curr = new Node;
        curr->cards = "Slave";
        prev = curr;
        head = curr;

        for (int i = 0; i < 3; i++) {

            curr = new Node;
            curr->cards = "Citizen";
            prev->next = curr;
            prev = curr;
        }

        curr = new Node;
        curr->cards = "Citizen";
        prev->next = curr;

    }

    return head;

}
Node *selectKaijiCard(Node *head, int indexK) {

    for (int i = 0; i < indexK - 1; i++) {

        head = head->next;
    }

    return head;
}
Node *deleteSelectedKaijiCard(Node *head, int indexK) {

    Node *curr = NULL;
    if (indexK == 1)
    {
        curr = head;
        head = head->next;
        delete curr;
        return head;
    }

    Node *deleteCard = head;

    for (int i = 0; i < indexK - 1; i++) {

        curr = deleteCard;
        deleteCard = deleteCard->next;
    }
    curr->next = deleteCard->next;
    delete deleteCard;
    return head;
}
List *createTonegawaDeck(int round) {

    List *root = NULL;
    List *front = NULL;
    List *tail = NULL;

    if (round == 1 || round == 2 || round == 3 || round == 7 || round == 8 || round == 9) {
        front = new List;
        front->card = "Slave";
        tail = front;
        root = front;

        for (int i = 0; i < 3; i++) {

            front = new List;
            front->card = "Citizen";
            tail->next = front;
            tail = front;
        }

        front = new List;
        front->card = "Citizen";
        tail->next = front;
    }

    if (round == 4 || round == 5 || round == 6 || round == 10 || round == 11 || round == 12) {
        front = new List;
        front->card = "Emperor";
        tail = front;
        root = front;

        for (int i = 0; i < 3; i++) {

            front = new List;
            front->card = "Citizen";
            tail->next = front;
            tail = front;
        }

        front = new List;
        front->card = "Citizen";
        tail->next = front;
        front->next = root;
    }

    return root;
}
List *selectTonegawaCard(List *root, int indexT) {
    for (int i = 0; i < indexT; i++) {

        root = root->next;
    }

    return root;

}
List *deleteSelectedTonegawaCard(List *root, int indexT) {

    List *front = NULL;
    if (indexT == 0)
    {
        front = root;
        root = root->next;
        delete front;
        return root;
    }

    List *deleteTonegawaCard = root;

    for (int i = 0; i < indexT; i++) {

        front = deleteTonegawaCard;
        deleteTonegawaCard = deleteTonegawaCard->next;
    }
    front->next = deleteTonegawaCard->next;
    delete deleteTonegawaCard;
    return root;
}
bool betCheck(int betLength, int remainingLength) {

    bool flag;
    if (betLength <= remainingLength) {
        flag = true;
    }
    else if (betLength > remainingLength) {
        flag = false;
    }
    return flag;
}
int prizeCheck(int betLength, int round) {

    int yen;
    if (round == 1 || round == 2 || round == 3 || round == 7 || round == 8 || round == 9) {

        yen = betLength * 100000;
    }
    if (round == 4 || round == 5 || round == 6 || round == 10 || round == 11 || round == 12) {

        yen = betLength * 500000;
    }
    return yen;
}
void printDeck(Node * head) {

    int count = 1;
    cout << "===============" << endl;
    cout << "Kaiji's cards" << endl;
    cout << "===============" << endl << endl;
    while (head != NULL) {
        cout << count << ". " << head->cards << endl;
        head = head->next;
        count++;
    }
    cout << endl;
}
int winCheck(List *root, Node *head, int cardIndex, int randTonegawa) {

    int result = 0;

    if ((head->cards == "Citizen") && (root->card == "Citizen")) {

        result = 0;
    }
    else if ((head->cards == "Emperor") && (root->card == "Citizen") || (head->cards == "Slave") && (root->card == "Emeperor") || (head->cards == "Citizen") && (root->card == "Slave")) {

        result = 1;
    }
    else if ((root->card == "Emperor") && (head->cards == "Citizen") || root->card == "Slave" && head->cards == "Emperor" || root->card == "Citizen" && head->cards == "Slave") {

        result = 2;
    }
    head = deleteSelectedKaijiCard(head, cardIndex);
    root = deleteSelectedTonegawaCard(root, randTonegawa);
    return result;
}
void gameOver(int cash, int round, int input, int remaining) {

    if (round <= 12 && cash == 20000000 && betCheck(input, remaining) == true) {
        cout << "You did not entirely win! You only got " << cash << " Yen in 12 rounds!" << endl;
        system("pause");
        exit(0);
    }
    else if (round == 12 && cash < 20000000 && betCheck(input, remaining) == false) {

        cout << "You won! You got" << cash << " Yen at Round " << round << endl;
    }

}

List.h

#pragma once
#include <string>
using namespace std;

struct List {
    string card;
    List* next = NULL;
};

Node.h

#pragma once
#include <string>
using namespace std;

struct Node {
    string cards;
    Node* next = NULL;
    Node* prev = NULL;  
};
  • Definitions for `Node` and `List`? Also if this is for school, there are a few easy "downmarks" like `int result = NULL;` – John3136 Sep 30 '15 at 23:41
  • When you used the debugger, which statement is causing the issue? – Thomas Matthews Sep 30 '15 at 23:49
  • Your use of `&&` and `||` is potentially ambiguous, remember that `&&` binds before `||` so something like `if (foo && bar || foobar)` is evaluated as `if ((foo && bar) || foobar)` and not `if (foo && (bar || foobar))` – user657267 Oct 01 '15 at 00:05
  • @user657267 I'll try to put my conditions in parenthesis to be like this? `if ((head->cards == "Emperor") && (root->card == "Slave")) || ( // other conditions)` Is that what you mean? – Alfred Intal Oct 01 '15 at 00:12
  • @AlfredIntal It probably won't make a difference in this case but it's something to keep in mind. Your example is incomplete however, there are 6 undefined functions. – user657267 Oct 01 '15 at 00:13
  • @user657267 Okay. I'll edit my question and I will put the remaining functions that I use in the said program. – Alfred Intal Oct 01 '15 at 00:16
  • @ThomasMatthews When I used my debugger, the function winChecker is returning the value 2 even though the conditions aren't met yet, I reproduce the issue by picking Citizen and the opponent draws Citizen as well, the function should return 0 instead it returns 2. – Alfred Intal Oct 01 '15 at 00:22
  • Sounds like you know where the problem is then. Step through winChecker with an eye on the variables, looking for where they deviate from the expected. Once they do, bingo! – user4581301 Oct 01 '15 at 00:30
  • @user4581301 Yeah, I will try again. But when I try F10 (Debugging mode) in VS 2015, I am really puzzled as to why Citizen vs Citizen makes winChecker return 2, instead of 0. Thanks for the boost! – Alfred Intal Oct 01 '15 at 00:39
  • No idea, but at the moment it's not even going to compile because you're missing a couple brackets. Oh, and placing `using namespace std;` in a header will have other programmers cursing your name. [It is a dangerous enough shortcut at the best of times](http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice), but in a header it's silently lethal to others as well as you. Not a good habit to get into. – user4581301 Oct 01 '15 at 00:54
  • Cleaned up the code a bit and gave it a run. When the input should have been citizen and citizen, the winCheck received emperor and slave. Why that would be, I dunno. Didn't check, but in that case a return of 2 is perfectly justified and your error is elsewhere. – user4581301 Oct 01 '15 at 01:02
  • @user4581301 Woah, I didn't know that it was a wrong habit. It was the one that was being taught to us all along. Alright I will try to use it in a local scope or maybe not use it at all. Thanks for pointing out about that maybe my struct has something going on in it. I'll look on it. – Alfred Intal Oct 01 '15 at 01:15

1 Answers1

0

It looks like when you select a card to play, you then delete that card from the deck, then compare the first card of the two decks. That doesn't seem right, surely you want to compare the cards you just selected?

If so, you should be calling winCheck with selectKaijiCardAtIndex and selectTonegawaCardAtIndex. You also want to do this before you delete the cards from the deck as the deleteSelectedKaijiCard function actually deletes the card so you can't use it after that.

This probably mean rearranging your code a bit and not call wincheck in so many places.

The Dark
  • 8,453
  • 1
  • 16
  • 19
  • Hello! Thanks for contributing. I just re-checked my work and I got a lot of function naming wrong. And also you point one of my biggest mistakes, I deleted the values before I call the checker making it just point at the head and giving same results all over again. – Alfred Intal Oct 01 '15 at 02:13