무작정 배우는 C언어 숫자 야구 게임 만들기 게임스랩

예제 소스 : numberBaseball.zip

 

이번 포스팅에는 추억의 숫자야구 게임을 만들어보겠습니다. 숫자야구 게임에 대해 생소한 분들도 있고 잘 아시는 분들도 있으리라 생각됩니다. 제가 학창시절에 쉬는 시간에 간단하게 즐길 수 있었던 게임이었던 이 숫자야구 게임을 종이와 연필이 없어도 컴퓨터로 즐길 수 있도록 만들어 보겠습니다.

 

난이도 측면에서는 전에 했던 머드 게임보다는 훨씬 쉬울 것입니다. 머드 게임의 경우는 각자의 기획내용에 따라 다양한 결과물이 나왔겠지만 이번 숫자야구게임은 명확한 룰과 결과가 있기에 만들 때 기획을 해야 되는 번거로움(?)이 많이 줄어들 것입니다.

 

만들기에 앞서 숫자야구게임을 모르시는 분들을 위해 우선 숫자야구게임의 규칙을 설명 드리고 넘어가겠습니다.

1.     수비를 하는 사람은 0~9까지의 숫자 중 중복되지 않게 4자리 숫자를 만듭니다. 물론 이 4자리 숫자는 상대방에게 공개하지 않습니다.

2.     공격을 하는 사람은 이제 수비수의 숫자를 얼마나 빠른 시간(기회) 안에 맞추느냐가 관건입니다.

3.     공격을 하는 사람은 임의의 4자리 숫자를 말합니다. 이 때 역시 중복되지 않는 4자리 숫자를 말해야 합니다.

4.     공격자가 말하는 수와 수비자의 수를 비교합니다.

5.     예를 들어 수비자는 8021 라고 했고 공격자가 8294라고 했을 경우 수비자는 공격자에게 1스트라이크 1볼 이라고 얘기해줍니다.

6.     스트라이크는 자리수와 숫자가 일치할 경우이고 볼은 숫자만 일치했을 경우입니다.

7.     한번 더 예를 들면 공격자가 1280 이라고 했다면 4볼이 되겠지요?

8.     이런식으로 공격자가 계속해서 임의의 수를 말해 수비자의 수를 제한된 횟수 또는 맞출 때까지 진행을 합니다.

9.     게임의 난이도를 위해 보통 10번안에 맞추기 등, 공격자가 임의의 수를 말할 수 있는 기회를 제한하기도 합니다.

 

우리는 이제 위의 규칙대로 숫자야구 게임을 만들도록 하겠습니다. 그렇다면 구현 해야 될 기본적인 요구사항에 대한 항목들을 한번 나열해 보겠습니다.우선은 컴퓨터와 내가 게임을 하는 것이니까 컴퓨터가 수비자가 되고 내가 공격자가 되는 것이 아무래도 게임을 하는 재미가 있겠지요내가 수비자가 되어 봤자 컴퓨터랑 하는 입장에선 그다지 재미가 있지 않을 테니까요. 아래 1번이 우리가 해야 할 첫 번째 구현 목록입니다. 

 

1.     컴퓨터(수비자)가 0~9 까지의 숫자 중 중복되지 않게 임의의4자리 숫자를 생성한다.

 

그 다음은 무엇을 해야 할까요?  공격자가 공격을 해야 할 차례입니다. 컴퓨터로 게임을 즐기니까 숫자를 말하는 대신 숫자를 입력할 필요가 있겠군요.

 

2.     사용자(공격자)가 0~9까지의 숫자 중 중복되지 않게 임의의 4자리 숫자를 입력한다.

 

자, 이제 입력이 끝났으니 결과를 공격자에게 통보해 주어야겠습니다.

 

3.     사용자(공격자)의 숫자와 컴퓨터(수비자)의 숫자를 비교한다.

4.     자릿수와 숫자의 일치성을 검사한다.

5.     검사한 결과를 화면에 출력한다.

 

이렇게 5번까지 로직이 완성되면 사용자(공격자)는 1번의 기회를 사용한 것입니다. 이것을 이제 맞출 때까지 무한반복을 하든 횟수의 제한을 가지던 여러분이 정하기 나름이겠죠.

 

6.     2~5 까지의 행동을 무한 또는 n번의 반복을 제어한다.

7.     최종 결과를 화면에 출력한다.0

 

이렇게 해서 최종적으로 컴퓨터(수비자)의 숫자를 맞췄는지 못 맞췄는지를 화면에 출력해 주면 전체적인 게임이 끝나게 되겠습니다. 그럼 이제 코드를 보도록 하겠습니다.

 

1-    #include <stdio.h>

2-    #include <conio.h>

3-    #include <stdlib.h>

4-    #include <time.h>

5-     

6-    #define OFFENSECHANCE 10 //도전횟수

7-     

8-    void main()

9-    {

10-  system("title 숫자야구게임");

11-  srand ( ( unsigned ) time ( NULL ) );

12-   

13-  printf("┌─────────────────────────────────────┐\n");

14-  printf("│                                                                         │\n");

15-  printf("│                   숫자야구게임                                       │\n");               

16-  printf("│                                     created by Jang hyun-il on 2012.8.29│\n");

17-  printf("└─────────────────────────────────────┘\n");

18-  //

19-  int defense[4] = {-1,-1,-1,-1};                                     //수비자의임의의수4개를저장

20-  int offense[4];                                                                                      //입력받은공격자의임의의수4개를저장

21-  int numAssignCount = 0;

22-  int strikeCount = 0;

23-  int ballCount = 0;

24-  int offenseHistory[OFFENSECHANCE][4];        //[횟수][4자리수]

25-  int countHistory[OFFENSECHANCE][2];                       //[횟수][카운트]

26-   

27-  printf("꼬부기의숫자야구게임입니다.\n");

28-  printf("%d번의기회안에상대방의숫자를맞추면승리합니다.\n",OFFENSECHANCE);

29-  printf("행운을빕니다.\n\n");

30-   

31-  while(1)

32-  {

33-                printf("게임을시작하시려면아무키나눌러주세요.\n\n");

34-                getch();

35-                             system("cls");

36-   

37-                printf("컴퓨터가수를정했습니다.\n\n");

38-                //컴퓨터(수비자)의임의의수발생    

39-                while(1)

40-                {

41-                             int num = rand()%10;

42-   

43-                             if(defense[0] != num && defense[1] != num && defense[2] != num &&defense[3] != num)

44-                             {

45-                                          defense[numAssignCount] = num;

46-                                          numAssignCount++;

47-                             }

48-   

49-                             if(numAssignCount >= 4)

50-                             {                                     

51-                                          break;

52-                             }

53-                }

54-   

55-                //게임시작

56-                int offenseChanceCount = OFFENSECHANCE;

57-                for(int k=0; k<OFFENSECHANCEk++)

58-                {

59-                             //아스키값48~57 = 0~9

60-                             printf("첫째자리수입력:");

61-                                          offense[0] = getch();

62-                             offense[0] -= 48;

63-                             printf("%d\n"offense[0]);              

64-   

65-                             while(1)

66-                             {

67-                                          printf("둘째자리수입력:");

68-                                          offense[1] = getch();

69-                                          offense[1] -= 48;

70-                                          if(offense[0] != offense[1])

71-                                          {

72-                                                        printf("%d\n"offense[1]);

73-                                                        break;

74-                                          }

75-                                          else

76-                                          {

77-                                                        printf("중복된숫자입니다다시입력해주세요.\n");

78-                                          }

79-                             }

80-   

81-                             while(1)

82-                             {

83-                                          printf("셋째자리수입력:");

84-                                          offense[2] = getch();

85-                                          offense[2] -= 48;

86-                                          if(offense[0] != offense[1] && offense[0] != offense[2] && offense[1] !=offense[2])

87-                                          {

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

88-                                                        printf("%d\n"offense[2]);

89-                                                        break;

90-                                          }

91-                                          else

92-                                          {

93-                                                        printf("중복된숫자입니다다시입력해주세요.\n");

94-                                          }

95-                             }           

96-   

97-                             while(1)

98-                             {                        

99-                                          printf("넷째자리수입력:");

100-                                        offense[3] = getch();

101-                                        offense[3] -= 48;

102-                                        if(offense[0] != offense[1] && offense[0] != offense[2] && offense[0] !=offense[3] && offense[1] != offense[2] && offense[1] != offense[3] && offense[2] !=offense[3])

103-                                        {

104-                                                      printf("%d\n"offense[3]);

105-                                                      break;

106-                                        }

107-                                        else

108-                                        {

109-                                                      printf("중복된숫자입니다다시입력해주세요.\n");

110-                                        }

111-                           }           

112- 

113-                           //결과비교

114-                           for(int i=0; i<4; i++)

115-                           {

116-                                        for(int j=0; j<4; j++)

117-                                        {

118-                                                      if(offense[i] == defense[j])

119-                                                      {

120-                                                                   if(i == j)

121-                                                                                strikeCount++;

122-                                                                   else

123-                                                                                ballCount++;

124-                                                      }

125-                                        }

126-                           }

127- 

128-                           //히스토리처리

129-                           for(int i=0; i<4; i++)

130-                                        offenseHistory[OFFENSECHANCE -offenseChanceCount][i] = offense[i];

131- 

132-                           countHistory[OFFENSECHANCE -offenseChanceCount][0] = strikeCount;

133-                           countHistory[OFFENSECHANCE -offenseChanceCount][1] = ballCount;

134- 

135-                           //기회감소

136-                           offenseChanceCount--;

137- 

138-                           //결과

139-                           if(strikeCount == 4) //게임승리

140-                           {                                                                             

141-                                        break;

142-                           }

143-                           else

144-                           {

145-                                        printf("\n%d스트라이크%d\n",strikeCountballCount);

146-                                        printf("------------------------\n");

147-                                        printf("%d번의기회가남았습니다.\n",offenseChanceCount);

148-                                        printf("------------------------\n\n");

149-                           }

150- 

151-                           printf("------당신의기록------\n");

152-                           //히스토리출력

153-                           for(int i=0; i<(OFFENSECHANCE - offenseChanceCount) ;i++)

154-                           {

155-                                        printf("%d%d%d%d %d스트라이크%d\n",offenseHistory[i][0],offenseHistory[i][1], offenseHistory[i][2], offenseHistory[i][3],

156-                                                      countHistory[i][0], countHistory[i][1]);

157-                           }

158-                           printf("\n");

159- 

160-                           //변수초기화

161-                           for(int i=0; i<4; i++)

162-                                        offense[i] = -1;

163- 

164-                           strikeCount = 0;

165-                           ballCount = 0;

166-              }

167- 

168-              //게임끝

169-              printf("\n컴퓨터의숫자%d%d%d%d\n",defense[0],defense[1],defense[2],defense[3]);

170- 

171-              if(strikeCount == 4)

172-                           printf("\n축하합니다승리하셨습니다.\n\n");

173-              else                    

174-                           printf("\n패배하였습니다머리가좀...\n\n");

175- }

176-}

 

위의 코드는 이 게임의 전체 풀 소스입니다. 176라인의 간단한 프로그램이죠. 그럼 코드 설명에 들어가겠습니다.11라인은 머드게임 만들기 때에도 보았던 난수 발생에 필요한 명령어입니다. 이번에도 역시 컴퓨터가 랜덤하게 수를 만들어야 하니 추가를 했습니다.(하지만 사실 이번에는 굳이 선언하지 않아도 상관이 없습니다. ^^; 그냥 rand()만으로도 충분합니다.)

 

19~25라인은 게임에 필요한 변수를 선언했군요. 2차원 배열이 눈에 띕니다. 그런데 OFFENSECHANCE 이 부분이 신경이 쓰이는 군요. 6라인에서 보면 #define 으로 10이라는 상수값으로 선언을 하였습니다. 주석에서 보이듯이 게임의 전체 루프를 관리하기 위해 선언해주었습니다. 바로 57라인의 for문에서의 최대값으로 쓰이게 됩니다. 그외에도 배열의 최대값으로 사용을 하게 됩니다.

 

34라인은 우리가 전에 사용했던 gets와 비슷한 함수입니다. gets가 문자열을 받았다면 getch는 문자 하나를 처리합니다. 리터값으로 아스키코드값을 리턴하게 됩니다. 바로 밑의 함수는 화면을 전체 지우는 명령어입니다. 좀 더 깔끔한 화면을 위해서 사용해봤습니다. 나중에 두고두고 사용하실 일이 있으실 겁니다.(도스 게임을 만들경우..)

 

39~53라인까지는 컴퓨터가 중복되지 않는 4자리 숫자를 발생하는 부분입니다. numAssignCount 변수를 이용해 무한루프에서 중복이 안될때까지 수를 발생시키고 defense[] 변수에 값을 넣고 수가 완성되면 break를 통해 빠져나오게 됩니다.

 

56~111라인까지는 사용자가 4자리 수를 입력하는 부분입니다. 각 자리수마다 중복여부를 체크하는 로직이 들어갑니다. 코드 중간에 한가지 특이한 점이 눈에 띄실겁니다. 바로 offense[0] = getch(); offense[0] -= 48; 이런 패턴의 부분들말입니다. 앞서 설명했다시피 getch()함수는 입력된 문자에 대한 리턴값으로 아스키코드값을 리턴합니다. -48을 한 이유는 바로 숫자 0~9의 아스키코드값이 48~57사이라는 점입니다. 

 

0 48, 1 49…..9 57 인것이죠이러다 보니 실제 유저가 입력한 값을 바로 숫자로 가져오기 위해서 -48을 해서0 = 48-48 , 1 = 49 – 48….의 식으로 정수값을 취하게 된것입니다. 0~9 이외의 키보드 입력이 들어올 경우도 예외처리를 하셔야 더 완변한 게임이 될것입니다위의 코드는 이 부분이 빠져 있습니다.

여러분이 한번 if 등의 제어문을 통해 완성해 보길 바랍니다.

 

113~126 라인은 입력한 수를 컴퓨터가 발생한 수와 비교하여 스트라이크와 볼의 여부를 판단하는 곳입니다. 이중for 문을 사용한 점이 눈에 띄실겁니다. 안의 로직은 천천히 살펴보시면 금방 이해하실겁니다.

 

128~133 라인은 게임을 만들다 보니 원래 요구사항에 없던 항목을 추가한 경우입니다. 위에서 우리는 이런 요구사항을 생각하지 못했습니다.(정확히는 제가 생각하지 못한것이지요.ㅡ.ㅡ;) 게임을 만들면서 보니까 중간에 이런 부분이 있어야 게임을 좀더 사용자가 편하게 할 수 있겠다는 생각이 들었거든요. 이렇듯 요구사항이 정확하지 않으면 중간에 필요한 사항들을 넣게 되는 경우가 발생합니다. 그럼 원래 의도한 시간보다 오래 걸리겠지요?

 

이러한 부분들이 바로 개인 스케쥴, 나아가 프로젝트의 전체적인 스케쥴을 변동시키게 되는 주요 요인입니다. 나중에 게임회사에 들어가실 분들은 이런점들을 잘 파악하시면 좋겠습니다.

 

그리고 128-133 라인은 내가 그동안 입력한 내용에 대한 결과들의 히스토리입니다. 야구게임을 하신분들이 이 부분이 얼마나 중요한지 아실겁니다. 이후의 코드들은 굳이 설명하지 않아도 간단하게 남긴 주석만으로도 충분히 이해하리라 믿습니다. 생각보다 간단하게 게임이 완성되었군요.

 

<게임 실행 화면>

 

질 경우 컴퓨터에게 굴욕적인 말을 들을수도.... 이 후 결과에 대한 연출 부분은 개인 입맛대로 작성하시면 될거 같습니다이상 간단하게 숫자야구 게임을 만들어 보았습니다

 

위 글의 내용에서 보신바와 같이 기본적인 요구사항들을 나열해보고 그에 따른 상세한 기능을 추가로 넣는다면 보다 견고하고 완성도 높은 게임을 만들수 있습니다제목은 무작정일지라도 게임을 만들기전에 어떤 게임을 만들지 준비를 해놓는다면 프로그래밍하기 수월하다는 것을 이번 글을 통해 여러분에게 잘 전달되었길 바라며 이만 마치도록 하겠습니다.

 

[출처] https://gameslab.tistory.com/m/99?category=486131

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED