C :: 컴퓨터와 가위바위보를 하자. – 코딩편

지난 설계편에 이어서… 우선, 헤더파일을 작성하겠습니다. 헤더파일의 이름은 간단히 play.h 로 합니다.


ComSelect() 함수에서 난수를 이용하기로 설계시 정했기 때문에 stdlib.h 와 time.h 를 포함시켜야 합니다. stdlib.h 에는 rand() 함수와 srand() 함수가 있죠. rand() 함수는 난수를 발생시키고, srand() 함수는 시드값을 줄 수 있습니다. 시드값을 주지 않으면 난수가 항상 같은 값으로 나옵니다. 그리고 시드값은 time.h 에 있는 time(NULL) 함수를 참조합니다.


/***************************************************************
 *  프로젝트 이름 : PlayGmae                                    *
 *  소스파일 이름 : play.h                                      *
 ***************************************************************/

#ifndef PLAY_H_INCLUDED
#define PLAY_H_INCLUDED

// 입출력을 위한 헤더파일
#include <stdio.h>
// rand(), srand() 함수를 위한 헤더파일
#include <stdlib.h>
// time(NULL) 함수를 위한 헤더파일
#include <time.h>

int UserSelect(int);
int ComSelect(int);
void Battle(int, int);

#endif // PLAY_H_INCLUDED


그리고 각 함수의 원형을 play.h 안에 선언했죠. 인자로 int 형을 넣어놨는데 이건 사용자나 컴퓨터의 선택값을 받기 위해서입니다.


다음으로, 프로그램의 전체적인 흐름을 통제할 main() 함수를 작성해야겠네요. 당연히 소스파일 이름은 main.c 입니다.


설계에서 이미 다 정해놨기 때문에 그대로 코딩만 하면 됩니다. 설계 내용을 다시 보자면 이렇습니다.


  • 안내문 출력.
  • 사용자의 선택
  • 컴퓨터의 선택 (난수 이용)
  • 승부 결정.
  • 결과 출력.

여기서 조금 수정을 했습니다. 마지막의 결과 출력을 승부 결정에 포함시켰습니다. 즉, Battle() 함수에 넣었은거죠. 이게 더 깔끔하더라구요. 그리고 선택값에 대한 변수 이름은 사용자는 selectUser, 컴퓨터는 selectCom 으로 했습니다.


/***************************************************************
 *  프로젝트 이름 : PlayGmae                                    *
 *  프로젝트 목적 : 컴퓨터와 가위바위보를 하자.                    *
 *  소스파일 이름 : main.c                                      *
 ***************************************************************/

// play.c 와 연결되어 있다.
#include "play.h"

int main()
{
    // 사용자의 선택
    int selectUser = 0;
    // 컴퓨터의 선택
    int selectCom = 0;

    printf("컴퓨터와 가위바위보를 해보자. \n");

    // 사용자가 가위, 바위, 보 중에서 하나를 선택한다.
    selectUser = UserSelect(selectUser);
    // 컴퓨터가 난수를 이용하여 가위, 바위, 보 중에서 하나를 선택한다.
    selectCom = ComSelect(selectCom);

    printf("\n");
    // 사용자와 컴퓨터의 선택을 비교하여 승부를 결정한다.
    Battle(selectUser, selectCom);

    return 0;
}


아, 물론 play.h 를 참조하도록 넣어야겠죠?


끝으로, 각 함수를 정의할 play.c 파일을 작성합니다. 먼저 play.h 를 참조하도록 합니다.


/***************************************************************
 *  프로젝트 이름 : PlayGmae                                    *
 *  소스파일 목적 : 가위바위보 게임을 구현한다.                    *
 *  소스파일 이름 : play.c                                      *
 ***************************************************************/

// main.c 와 연결되어 있다.
#include "play.h"


그리고 첫 번째 함수, UserSelect() 를 작성합니다. 선택사항에 대한 안내를 하고 선택값을 입력하라고 해야겠죠. 단, 입력받은 값이 잘못된 값일 경우를 예상하여 정해진 값이 아니면 다시 입력하라고 안내해야 합니다. 아니면 프로그램 망칩니다. ㅋ


// 사용자가 가위, 바위, 보 중에서 하나를 선택한다.
int UserSelect(int select)
{
    printf("가위(1), 바위(2), 보(3) 중에서 하나 선택해라. >> ");

    while(scanf("%d", &select))
    {
        if((select == 1) || (select == 2) || (select == 3))
        {
            break;
        }
        else
        {
            printf("멍청아, 잘못 입력했잖아. 다시 선택해라. >> ");
        }
    }

    printf("\n넌 %s를 선택했다. \n", (select == 1) ? "가위" : ((select == 2) ? "바위" : "보"));

    return select;
}


가위는 1을, 바위는 2를, 보는 3을 입력하라고 안내했습니다. while 문과 if 문을 이용해서 올바른 값을 입력하도록 유도합니다. if 문을 다룰 때는 꼭 else 문을 같이 넣어줘야 합니다. 안 넣어줘도 프로그램 실행에는 문제 없지만 언제 어디서 오류를 일으킬지 모르거든요. 적어도 else 문으로 오류코드가 출력되도록 하면 어디서 오류가 생겼는지 금방 알 수 있습니다.


이제 두 번째 함수, ComSelect() 입니다. 필요한 건 stdlib.h 에 다 정의되어 있기 때문에 라이브러리 함수만 이용하면 특별히 지정해줄 게 없습니다.


// 컴퓨터가 가위, 바위, 보 중에서 하나를 선택한다.
int ComSelect(int select)
{
    // time 변수를 이용하여 난수를 생성 후, 3가지 선택사항으로 컴퓨터에게 주어진다.
    srand(time(NULL));
    select = rand() % 3 + 1;

    printf("컴퓨터는 %s를 선택했다. \n", (select == 1) ? "가위" : ((select == 2) ? "바위" : "보"));

    return select;
}


난수에 대해 조금 부연설명을 하자면, rand() 함수로 생긴 수많은 경우의 수를 3으로 나눈 나머지 값인 0, 1, 2의 3가지 경우의 수로 분류합니다. 그리고 우리가 원하는 선택값인 1, 2, 3으로 만들기 위해 1을 더하는 거죠.


세 번째 Battle() 함수입니다. 설계에서 어떻게 승부를 결정할 지 못 정했으니 이제 정해야 합니다. 두 함수에서 선택값으로 1, 2, 3을 받도록 되어 있습니다. 이 숫자들을 이용합니다. 여러 방법이 있겠지만, 서로 곱하는 게 가장 깔끔해 보입니다.


// 사용자와 컴퓨터가 선택한 것으로 승부를 결정한다.
void Battle(int user, int com)
{
    switch(user * com)
    {
        // 선택: 가위(1)와 바위(2)
        case 2 :
            printf("%s가 이겼다. \n", (user > com) ? "너" : "컴퓨터");
            break;
        // 선택: 가위(1)와 보(3)
        case 3 :
            printf("%s가 이겼다. \n", (user < com) ? "너" : "컴퓨터");
            break;
        // 선택: 바위(1)와 보(3)
        case 6 :
            printf("%s가 이겼다. \n", (user > com) ? "너" : "컴퓨터");
            break;
        // 선택: 가위(1)와 가위(1), 바위(2)와 바위(2), 보(3)와 보(3)
        default :
            printf("너와 컴퓨터는 비겼다. \n");
            break;
    }
}


곱하는 게 아니더라도 XOR 연산을 이용해도 됩니다. XOR 연산을 이용하면 비기는 경우 모두가 0으로 반환되죠.


마지막 함수까지 코딩을 끝마쳤으니 이제 컴파일 해보겠습니다.


사용자 삽입 이미지

큭, 컴퓨터에게 졌네요. 이런이런… 아무튼 간단한 가위바위보 게임을 만들었습니다. 여기에 GUI를 붙이면 더 멋질 것 같은데… GUI는 지금 공부중입니다. 언젠가 한 번 해보죠.


참, 코딩을 할 때 꼭 주석을 붙여주십시오. 간혹 몇몇 프로그램을 참조할 때 주석이 전혀 없어서 해석하기가 무척 난해했습니다. 서로 돕고 도와야죠. 응? 꼭 그런 게 아니더라도 주석을 달아야 나중에 수정을 하더라도 더 쉽게 할 수 있지 않을까요?


관련글

C :: 컴퓨터와 가위바위보를 하자. – 설계편 :: /?p=752

C :: 컴퓨터와 가위바위보를 하자. – 코딩편 :: /?p=753

Similar Posts

  • .htaccess, UTF-8을 지원하지 않는 서버에서

    이 블로그는 태터툴즈로 운영하는 블로그다. 태터툴즈는 http://www.tattertools.com에서 다운로드 받을 수 있는 설치형 블로그다. 네이버, 이글루스 같은 서비스형 블로그와 달리 자신의 계정에 설치한다. 그래서 백업은 물론이고 DB 관리도 자신이 직접 할 수 있다. 용량도 적어서 어떠한 계정에라도 트래픽만 허용된다면 부담없이 운영할 수 있다. 이런 설치형 블로그에는 워드프레스와 태터툴즈가 대중적이다. 워드프레스는 태터툴즈에 비해 크기가 작고 기능도 더…

  • 뜻을 모르겠으면 Vim에서 사전 검색을 하자.

    코딩을 하거나 다른 사람의 소스를 볼 때 난감할 때가 간혹 있지 않으세요? 바로 변수의 이름을 어떻게 정할까 혹은 이 변수 이름의 뜻이 뭘까하는 것 말이죠. 제가 그렇거든요. 그래서 이리저리 방법을 찾다가 noth 님의 dic 스크립트를 알게 되어 문제를 해결했습니다. dic은 리눅스의 터미널용 야후/네이버 국어/영어사전 프로그램인데요. 스크립트 파일로 되어 있고 용량도 아주 작은 게 장점이죠. 그리고…

  • C :: typedef으로 함수 포인터를…

    Dll Injection으로 Brute Force를 하려고 공부하던 차에 함수 포인터를 활용하는 방법을 알게 되었습니다. 일반적으로 C 언어는 절차 지향 언어, 함수 지향 언어라고 알려져 있어서 C++의 클래스 구현이 안 된다고 배웁니다만, 이 함수 포인터를 이용하면 충분히 클래스를 구현할 수 있을 것 같습니다. 실제로 커널 등의 여러 소프트웨어에서 이 방법을 쓰는 것 같구요. 함수 포인터를 선언하려면 우선…

  • imagEmail, changelog 2009. 2. 28 ~ 3. 15

    2009-03-15———-– ‘gdk_draw_line’는 gtk_example의 chapter5 참조. 2009-03-11———-– *builder, *windowMain, *dialogSave, *textInputID 전역으로 정의.– buttonSave_clicked_cb: *emailID에 *testInputID의 문자열을 저장. 2009-03-09———-– v0.9.0 개발 시작.– windowMain, dialogSave GUI 구현.– GtkBuilder을 사용하면 libglade가 필요없음.– ‘gtk-builder-convert’로 xml 파일을 생성하여 GtkBuilder로 적용.– buttonSave_clicked_cb: dialogSave를 띄움. 2009-03-02———-– 간략한 설계 구성. imagEmail_design_20090302.odg 참조. 2009-02-28———-+ imagEmail 기획.  + 기능    – email 주소를 이미지로 만든다. …

  • Ubuntu 에서 Mac OS X 로… 테마 변경

    http://sourceforge.net/projects/mac4lin/ 위 저장소에서 테마 패키지를 내려받아 압축을 푸신 후, “모양새 -> 테마” 에서 하나하나 설치하시면 됩니다. 이 패키지는 테마를 한번에 훅 설치해주는 게 아니라서 각 부분별로 개별적으로 설치해야 합니다. 그리고 적용하는 것도 “모양새 -> 테마 -> 사용자설정” 에서 따로따로 해야합니다. (처음에 설치해도 변경되는 게 없고 테마 목록에 새로 뜨는 것도 없어서 당황했던… ^^;) 터미널로 압축을…

  • C :: [열혈강의 C 프로그래밍] p.115 char_add.c

    tothefelix 님의 블로그에서 아래의 코드를 가져왔습니다. 언뜻 보면 정상적인 코드인 것 같으나, 유심히 보면 자료형이 잘못된 것을 알 수 있습니다. 1바이트의 char 형 변수에 4바이트의 int 형 값을 넣는 오류입니다. 명백히 코드 상의 오류지요. 정말 열혈강의에 저런 코드가 예문으로 나와 있다면 무척 실망입니다. 역시 국내 C 레퍼런스로는 김상형 님의 “혼자 연구하는 C/C++“가 최고의 레퍼런스가 아닌가…

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다