PGR21.com
이전 질문 게시판은 새 글 쓰기를 막았습니다. [질문 게시판]을 이용바랍니다.
Date 2009/05/19 23:37:08
Name Galdae
Subject 객체지향프로그래밍(c++)에 대한 질문이요!!^^
안녕하세요
저는 컴퓨터과학과 학생인데요.

이번 프로젝트로 blackjack을 코딩하는 것이 나왔습니다.
허접한 실력으로 한다고 열심히 했는데 오류가 뜨더라고요 ㅠㅠ
오류없이 돌아가려면 어디 고쳐야하는지좀 알려주세요^^

막상올리고 보니 너무기네요, 죄송하지만 부탁드립니다,,,,,,,,,,,,,,

#include <iostream>
#include <string>
#include <time.h>
#include <stdlib.h>

using namespace std;

class CARD{ // 카드를 나타내는 클래스
public:
        CARD():pip(0), suit(' '){}

        int pip; // 카드의 숫자를 저장한다
        char suit; // 카드의 모양을 저장한다
        CARD *next, *prev; // 카드를 linked list로 관리하기 위한 포인터
};

CARD *deck;  // 게임에 사용될 카드의 묶음
int index=0;  // 게임에 사용될 카드의 총 수

class PLAYER{ // human, meek, random 클래스의 base 클래스
public:
        PLAYER(){  // 초기화
                name = "";
                point = 0;
                head = new CARD;
                tail = new CARD;
                head->next = tail;
                tail->prev = head;
        }

        // 플레이어가 가지고 있는 카드를 모두 삭제하는 함수
        // 이 함수는 게임 한판이 끝나고 이어서 진행할때 쓰인다.
        void clear(){  
                CARD *temp = head->next;
                while(temp->next !=tail){
                        temp = temp->next;
                        delete temp->prev;
                }
                if(temp->next !=tail)delete temp;
                head->next = tail;
                tail->prev = head;
        }

        int b(){ return bet;} // 플레이어가 배팅한 금액 반환

        void ini(){ // 게임 시작시 플레이어에게 카드 2장 배분
                get_in();
                get_in();
        }
        
        void burst(){ cout << name << " is bursted!!";} // 21점 초과시 파산

        void print_money(){  // 플레이어가 가지고 있는 돈 출력
                cout.width(7);
                cout << left << name;
                cout << "$" << money << endl;
        }

        int conc(int p){  // 플레이어가 게임에서 승리 또는 패배했는지 결정하고 그 결과 출력
                if( point < 22) {
                        if(p<point || p>21) {
                                cout << "Yowzah! " << name << " wins " ;
                                money = money + bet;
                                cout << "$" << money <<  endl;
                                return 1;
                        }
                }
                cout << "Ouch! " << name << " loses " ;
                money = money - bet;
                cout << "$" << money <<  endl;
                return 0;
        }

        // 플레이어가 가지고 있는 카드들을 모두 출력하고
        // 또한 플레이어의 점수를 출력하는 함수이다.
        // 함수의 parameter인 sw가 1일 경우에는 이 함수를
        // 플레이어의 초기 상태를 출력할때 사용한다는 뜻이다
        // 즉 [??][xx]식으로 출력할 때 sw=1로 한다.
        int print_cards(int sw=0){
                CARD *temp = head;
                int total=0;

                cout << endl << name << "'s current hand: ";
                while(temp->next != tail) { // 플레이어가 가진 카드를 모두 검색한다.
                        temp = temp->next;
                        if(sw!=1){
                                cout << "[" << temp->pip << temp->suit << "]";
                                if(temp->pip>10) total +=10;  // 11이상의 카드들은 10포인트를 가진다.
                                else if(temp->pip==1) total +=11; // 1 카드는 기본적으로 11포인트를 가진다.
                                         else total += temp->pip;
                        }
                        else {
                                cout << "[??]";
                                sw=2;
                        }

                }
                point = total;

                if(point > 21){      // 플레이어가 파산할 위기에 몰렸을 경우 플레이어가 가진 카드를 검색하여
                        CARD *temp=head; // 1 카드가 있으면 그 카드의 포인트를 1로 바꿔 파산을 막는다.
                        while(temp->next!=tail && point >21){
                                temp=temp->next;
                                if(temp->pip==1) point=point-10;
                        }
                }
                if(sw==0) cout << " (" << point << " points)" << endl;

                return point;
        }

protected:
        void get_in(){  // 플레이어에게 카드를 주는 함수
                if(index>0) {  // deck에 카드가 남아있으면
                        index--;
                        CARD *in;
                        in = new CARD;
                        *in = deck[index];  // deck 에 저장되어 있는 카드를 플레이어에게 준다.

                        head->next->prev = in;
                        in->next = head->next;
                        in->prev = head;
                        head->next = in;
                }
        }

        string name; // 플레이어의 이름 저장
        int bet;  // 플레이어가 베팅한 금액 저장
        int point;  // 플레이어의 점수 저장
        int money;  // 플레이어가 가진 자금 저장
        CARD *head, *tail;  // 같은 성향의 플레이어들을 묶어서 관리하기 위한 포인터
};

class HUMAN : public PLAYER{
public:
        HUMAN(){  // 휴먼 플레이어의 이름과 소유 자금을 입력받는다.
                cout << endl << "Enter a Human player's name : ";
                cin >> name;
                cout << "Enter a money "<< name << " haven : ";
                cin >> money;
        }
        
        ~HUMAN(){ // 파괴자
                delete head;
                delete tail;
        }
        
        void betting(){  // 휴먼의 베팅액을 입력받는다.
                cout << endl << name << ", how much would you like bet? ";
                cin >> bet;
                cout << name << " bets $" << bet;
        }

        void turn(){  // 휴먼의 게임 플레이
                char in;
                cout << endl<< endl<< name << "'s turn:" << endl;
                cout << "------------------";
        
                while(1){
                        if(print_cards()>21) {  // 포인트가 21을 초과했는가?
                                burst();
                                return;
                        }
                        cout << "Would you like to draw another card? (y or n):";
                        cin >> in;
        
                        if(in=='n' || in=='N') break;  // 카드를 계속 뽑을 것인가?
                        else {
                                cout << name << " choose to draw";
                                get_in(); // deck에서 카드를 뽑는다
                        }
                }
                cout << name << " choose to stay";
        }
};

class MEEK : public PLAYER{
public:
        MEEK(){  // 믹 플레이어의 이름과 소유 자금을 입력받는다.
                cout << endl <<endl<<  "Enter a Meek player's name : ";
                cin >> name;
                cout << "Enter a money "<< name << " haven : ";
                cin >> money;
                bet = 1;
        }

        ~MEEK(){  // 파괴자
                delete head;
                delete tail;
        }        
        
        void betting(){ bet=bet*2; // 믹의 베팅 금액을 결정한다.
                cout << endl<< name << " bets $" << bet;
        }

        void turn(){  //믹의 게임 플레이
                cout << endl <<endl<< name << "'s turn:" << endl;
                cout << "------------------";

                while(1){
                        int temp = print_cards();
                        if(temp>21) {  // 믹의 파산여부 확인
                                MEEK::burst();
                                return;
                        }        
                        if(temp%2 == 1) if(ser_seven() == 0) break;  // 믹은 짝수 점수나, 7-club카드를 가지면 카드를 뽑는다

                        cout << name << " choose to draw";
                        get_in();  // deck에서 카드를 뽑는다.
                }
                cout << name << " choose to stay";
        }

private:
        void burst(){ // 믹은 파산할 경우 베팅 할 금액을 초기화한다.
                cout << name << " is bursted!!";
                money-=bet;
                money++;
                bet = 1;
        }


        int ser_seven(){ // 믹이 7-club카드를 가지고 있는지 확인한다.
                CARD *temp = head->next;
                while(temp->next!=tail){
                        if(temp->suit=='c' && temp->pip==7) return 1;
                        temp = temp->next;
                }
                return 0;
        }

};

class RANDOM : public PLAYER{
public:
        RANDOM(){  // 랜덤 플레이어의 이름과 초기 자본 설정
                cout << endl <<endl<<  "Enter a Random player's name : ";
                cin >> name;
                cout << "Enter a money "<< name << " haven : ";
                cin >> money;
        }

        ~RANDOM(){ // 파괴자
                delete head;
                delete tail;
        }

        void betting(){  // 랜덤의 베팅액 결정
                float random = static_cast<float>(rand())/static_cast<float>(RAND_MAX);
                bet = random * money / 2;
                if(bet < 1) bet = 1;
                cout << endl<< name << " bets $" << bet;
        }

        void turn(){  // 랜덤의 게임 플레이
                cout << endl<<endl<<name << "'s turn:" << endl;
                cout << "------------------";

                while(1){
                        int point = print_cards();
                        if(point>21) {  // 파산여부 확인
                                burst();
                                return;
                        }
                        float random = static_cast<int>(rand())/static_cast<int>(RAND_MAX);
                        if(point > 9) {  // 카드를 뽑을 것인지 결정
                                if(point > 12) {
                                        if(point > 15) {
                                                if(point > 18) break;
                                                else if(random > 0.5) break;
                                        }
                                        else if(random > 0.7) break;
                                }
                                else if(random > 0.8) break;
                        }

                        cout << name << " choose to draw";
                        get_in();  // deck에서 카드를 뽑는다
                }
                cout << name << " choose to stay";
        }

};

class DEALER : public PLAYER{
public:
        DEALER(){  // 딜러의 이름과 자금 설정
                name = "Dealer";
                money = 10000;
        }

        ~DEALER(){  // 파괴자
                delete head;
                delete tail;
        }

        int p() { return point;}  // 딜러의 점수 반환

        void concl(int p){  // 딜러의 자금 재설정
                money+=p;
        }

        void turn(){  // 딜러의 게임 플레이
                cout << endl<<endl<<name << "'s turn:" << endl;
                cout << "------------------";

                while(1){
                        int point = print_cards();
                        if(point>21) {  // 파산여부 확인
                                burst();
                                return;
                        }
                        if(point > 16) break;  //딜러는 16포인트 이하에서만 카드를 뽑는다
                        cout << name << " choose to draw" << endl;
                        get_in();  // deck에서 카드를 뽑는다.
                }
                cout << name << " choose to stay" << endl;
        }
};

// 게임 전체를 통괄하는 클래스이다.
class GAME{
public:
        GAME(int h, int m, int r){  // 게임을 하기위한 기초를 다진다.
                human = new HUMAN[h];  // 휴먼을 h명생성한다.
                meek = new MEEK[m];  // 믹을 m명 생성한다.
                random = new RANDOM[r]; // 랜덤을 r명 생성한다/
                num_h = h;  // 자료 백업
                num_m = m;
                num_r = r;
                pack = (num_h + num_m + num_r + 2)/3;  // 몇 그룹이 게임을 하는지 확인
                index = pack * 52;  // 현재 가지고 잇는 카드의 수 설정
                cards();  // 카드를 생성하여 deck에 집어 넣는다.
        }

        ~GAME(){ // 파괴자
                delete [] deck;
        }

        void check(){  // 게임을 진행하기에 앞서 deck에 카드가 충분한가 살펴본다
                if(index < (num_h+num_m+num_r+1)*5){
                        index = pack *52;
                        cards();
                }
        }

        void show_ini(){  // 각 플레이어들이 처음에 가진 카드를 설정하고, 또 보여준다.
                cout << endl <<endl<< "The Initial starting cards are:" << endl;
                cout << "-------------------------"<< endl;
                for(int i=0; i<num_h; i++) human[i].ini();  // 카드를 2장씩 준다.
                for(i=0; i<num_m; i++) meek[i].ini();
                for(i=0; i<num_r; i++) random[i].ini();
                dealer.ini();

                for(i=0; i<num_h; i++) human[i].print_cards(1); // 현제 플레이어가 가진 카드를 보여준다.
                for(i=0; i<num_m; i++) meek[i].print_cards(1);
                for(i=0; i<num_r; i++) random[i].print_cards(1);
                dealer.print_cards(1);
        }

        
        void betting(){  // 각 플레이어가 베팅을 하도록 한다.
                cout << endl << "Time for betting!!";
                cout << endl << "-------------------------";
                for(int i=0; i<num_h; i++) human[i].betting(); //베팅
                for(i=0; i<num_m; i++) meek[i].betting();
                for(i=0; i<num_r; i++) random[i].betting();
        }

        void playing(){  // 본격적인 게임을 진행한다.
                for(int i=0; i<num_h; i++) human[i].turn();  // 플레이어마다 게임을 진행한다.
                for(i=0; i<num_m; i++) meek[i].turn();
                for(i=0; i<num_r; i++) random[i].turn();
                dealer.turn();
                // 게임진행 끝
                cout << endl<< endl<< "Let's see how it turned out:" << endl;
                cout << "------------------------" << endl;

                int p=0; // 이 변수는 딜러가 가지게 될 자금이다
                for(i=0; i<num_h; i++)
                        if(human[i].conc(dealer.p())==0) p+=human[i].b();   // 각각의 플레이어들이 승리 또는 패배했는지 확인하고
                        else p-=human[i].b();                                                                // 베팅한 금액을 처리한다.
                for(i=0; i<num_m; i++)
                        if(meek[i].conc(dealer.p())==0) p+=meek[i].b();
                        else p-=meek[i].b();
                for(i=0; i<num_r; i++)
                        if(random[i].conc(dealer.p())==0) p+=random[i].b();
                        else p-=random[i].b();
                dealer.concl(p);
        }
        
        int conc(){  // 게임이 다 끝나면 마무리를 한다
                char temp;


                cout << endl << endl << "The standing so for:" << endl;
                cout << "-------------------" << endl;

                for(int i=0; i<num_h; i++) human[i].print_money();  // 현재 플레이어들이 가진 자금을 표시한다.
                for(i=0; i<num_m; i++) meek[i].print_money();
                for(i=0; i<num_r; i++) random[i].print_money();
                dealer.print_money();

                cout << endl << "Another round?(y/n) ";
                cin >> temp;

                for(i=0; i<num_h; i++) human[i].clear();  // 플레이어 들이 가지고 있는 카드를 모두 제거한다.
                for(i=0; i<num_m; i++) meek[i].clear();
                for(i=0; i<num_r; i++) random[i].clear();
                dealer.clear();

                if(temp == 'y' || temp == 'Y') return 1;  // 계속 진행할 것인가?
                return 0;
        }

private:
        void cards(){   // 카드를 생성한 후 섞어서 deck에 담는다.
                deck = new CARD[index];
                for(int i=0; i<pack; i++){
                        for(int j=0;j<52;j++){   // 카드를 생성하는 부분
                                if(j<13) {
                                        deck[j+i*52].pip=j+1;
                                        deck[j+i*52].suit='c';
                                } else if(j<26) {
                                        deck[j+i*52].pip=j-12;
                                        deck[j+i*52].suit='d';
                                } else if(j<39) {
                                        deck[j+i*52].pip=j-25;
                                        deck[j+i*52].suit='h';
                                } else if(j<52) {
                                        deck[j+i*52].pip=j-38;
                                        deck[j+i*52].suit='s';
                                }
                        }
                }
                shuffle();
        }

        void shuffle() {  // 카드를 섞는 함수이다.
                CARD temp;
                int i,j;

                rand();
                for(i=0;i<index;i++) {
                        j=rand() % 52;
                        temp = deck[i];
                        deck[i] = deck[j];
                        deck[j] = temp;
                }
        }

        HUMAN *human;  // 휴먼 플레이어를 관리하는 포인터
        MEEK *meek;  // 믹 플레이어를 관리하는 포인터
        RANDOM *random;  // 랜덤 플레이어를 관리하는 포인터
        DEALER dealer;  // 딜러를 관리하는 변수

        int pack;  // 몇묶음의 카드가 필요한지 저장하는 변수
        int num_h, num_m, num_r;  // 성향별로 몇명의 플레이어가 있는지 저장하는 변수
};

int main(){

        srand(time(0));
        int h, m, r;
        cout << "Blackjack!!" << endl << endl;
        cout << "Game initialization" << endl << "-----------------------" << endl;
        cout << "Input the # of Human player : ";
        cin >> h;
        cout << "Input the # of Meek player : ";
        cin >> m;
        cout << "Input the # of Random player : ";
        cin >> r;

        GAME game(h, m, r);  // 게임 초기화
        do{
                game.check();  // 게임하는데 있어 deck에 잇는 카드가 충분한가?
                game.betting();  // 플레이어들이 베팅하도록 한다
                game.show_ini();  // 플레이어들의 초기 상태를 표시한다.
                game.playing();  // 본격적으로 게임을 한다
        } while(game.conc());  // 게임의 마무리를 짓는다.

        return 0;
}

통합규정 1.3 이용안내 인용

"Pgr은 '명문화된 삭제규정'이 반드시 필요하지 않은 분을 환영합니다.
법 없이도 사는 사람, 남에게 상처를 주지 않으면서 같이 이야기 나눌 수 있는 분이면 좋겠습니다."
MoreThanAir
09/05/19 23:44
수정 아이콘
이런 긴 코드를 복사해서 올리시다니 용자시군요...흐흐

일단 변수 i의 사용이 잘못되었습니다. 각 함수 내에서 for블락 안에서 i가 declare되었는데 그 다음 for에서 그대로 i를 쓰려고 하니 out of scope가 되는거지요. 각 함수의 앞부분에 int i; 를 선언하고 각 for 루프에서는 for(i=0;...) 이런 식으로 사용하세요.
그 부분을 고치면 일단 제대로 돌아가는데 예외 처리가 안되어있어 프로그램이 많이 취약해 보입니다. 가진 돈을 입력하라고 할 때 숫자 대신에 영문을 입력하면 프로그램이 바로 깨지는군요. 유닉스 표준함수인 isdigit isalpha등을 사용해서 타입을 체크해주는 것이 좋겠네요. <ctype.h> 헤더안에 있는 함수들입니다.
09/05/19 23:58
수정 아이콘
MoreThanAir님/// 엄청나게 빠른답변 진짜 감사드려요^^
엄청 고민했는데 i하나때문에 이런거였다니 허탈하네요,,,,,,,,,,,,,크크크
그부분 고치고 코딩을 했는데요,,,,,,,, 플레이어한명이 파산하면 프로그램이 끝나야하는데 안끝나서요ㅠㅠㅠ
어떻게하면될까요???????? 한번만더도와주세요 흐흙흙흙
MoreThanAir
09/05/20 00:09
수정 아이콘
파산을 하면 끝나는 코드를 넣으셔야죠. 지금 상태에서 봤을 때는 while문으로 돌면서 다시 게임하겠냐는 질문에 y나 Y를 입력하지 않는 경우에만 끝내도록 되어있는 것 같은데요?

Trace를 하면서 프로그램 흐름을 하나하나 따라가보세요.
MoreThanAir
09/05/20 00:10
수정 아이콘
playing 함수 내에서 각 플레이어의 잔액을 체크하고 파산했다면 끝내도록 코딩을 하면 되겠네요.
09/05/20 00:56
수정 아이콘
MoreThanAir님// 답변 정말 감사합니다^^
목록 삭게로! 맨위로
번호 제목 이름 날짜 조회
55963 나눈 파티션을 다시 합치려면.. [3] 달려라투신아~2060 09/05/20 2060
55962 외국어로 하나둘셋 어떻게 하죠? [19] 오월4981 09/05/20 4981
55960 인간의 행동과 관련하여 잘못 만들어 졌다고 생각되는 것들이 무엇이 있을까요 [5] 紅純1577 09/05/20 1577
55959 뮤짤의 역사라고 해야하나요.. 여하튼 뮤짤에 관한 질문입니다. [18] GASSANG3050 09/05/20 3050
55958 커세어와 드랍쉽에 관한 질문 [2] ipa1654 09/05/20 1654
55956 근력. 체력운동 추천좀 부탁드립니다. [2] 달려라투신아~2122 09/05/20 2122
55955 마라도나에 대해서... [1] Dis-v2139 09/05/20 2139
55954 비행기 여행시 1회 경유할때 그곳에서 [2] [秋] AKi2213 09/05/20 2213
55953 보컬 동아리나 동호회 아시는분 있나요? [2] 멜로2105 09/05/20 2105
55952 동영상보다가 가만이 있으면 소리가 안나네요 가치파괴자2115 09/05/20 2115
55951 트랜스포머 블루레이... [2] 본호라이즌1878 09/05/20 1878
55949 혹시 전화영어 해보신분 계신가요? [4] Valueinvester2135 09/05/20 2135
55948 혹시 pgr에 드럼치시는분 계신가요? 질문좀.. [6] 호랑이잡자1797 09/05/20 1797
55947 도와주세요 ㅠㅠ 동영상 재생후에 창을 닫으면 모든창에 '응답없음'이 뜹니다. llVioletll1678 09/05/20 1678
55945 지겨우시겠지만, mp3 추천좀 부탁드릴께요. [6] 도시의미학2275 09/05/20 2275
55944 드래곤 볼을 보며 궁금했던점 [4] 애플보요2127 09/05/20 2127
55943 마른사람은 헬스어떻게 해야돼나요? 살도 찌고싶습니다~!! [2] Mint2093 09/05/20 2093
55942 MISSONI와 M-MISSONI와의 관계? [1] 스타카토2060 09/05/20 2060
55941 온도가 높을 때 운동하는게 확실히 칼로리 소모가 높나요? [10] 라울4372 09/05/19 4372
55940 토익.. 최소한 몇점 이상 나와야 그래도 여기저기 내밀순 있나요? [16] 창이3993 09/05/19 3993
55939 객체지향프로그래밍(c++)에 대한 질문이요!!^^ [5] Galdae1618 09/05/19 1618
55938 유성 볼펜, 필기구 중 볼펜똥 적고 괜찮은 걸로 추천해 주세요. [11] Hi there4773 09/05/19 4773
55937 폰이 꺼져있다면 찾기는 불가능인가요? [6] 개그맨2169 09/05/19 2169
목록 이전 다음
댓글

+ : 최근 6시간내에 달린 댓글
+ : 최근 12시간내에 달린 댓글
맨 위로