당신은 주제를 찾고 있습니까 “c 언어 게임 소스 코드 – C 언어 무료 강의 (입문부터 게임 개발까지)“? 다음 카테고리의 웹사이트 https://chewathai27.com/you 에서 귀하의 모든 질문에 답변해 드립니다: https://chewathai27.com/you/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 나도코딩 이(가) 작성한 기사에는 조회수 1,276,084회 및 좋아요 30,995개 개의 좋아요가 있습니다.
c 언어 게임 소스 코드 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 C 언어 무료 강의 (입문부터 게임 개발까지) – c 언어 게임 소스 코드 주제에 대한 세부정보를 참조하세요
9가지 게임을 만들며 누구나 쉽고 재미있게 C 를 배울 수 있습니다.
컴퓨터 전공자, IT 개발자로 진로를 희망하시는 분들에게 C 는 선택이 아닌 필수입니다. 더 이상 포인터에서 좌절하지 마시고, 나도코딩과 함께 C 를 마스터하세요.
인프런 C 분야 최고의 인기 강의, 지금 바로 만나보세요!
(Visual Studio 2019 환경설정 업데이트)
0:03:09 환경설정
게임 #1
0:07:58 경찰서 조서 쓰기
0:10:19 정수형 변수
0:16:11 주석
0:19:02 실수형 변수
0:21:26 상수
0:23:05 printf
0:26:17 scanf
0:32:00 프로젝트
게임 #2
0:37:24 피라미드를 쌓아라
0:38:46 뿔뿔
0:45:44 for
0:48:18 while
0:50:39 do while
0:51:35 이중 반복문 (구구단)
0:56:45 이중 반복문 파헤치기
1:05:40 이중 반복문(거꾸로 별)
1:08:39 프로젝트
게임 #3
1:13:43 Up \u0026 Down
1:16:44 if else
1:25:22 break continue
1:31:33 and or
1:34:56 랜덤
1:40:36 switch case
1:51:44 프로젝트
게임 #4
1:58:31 비밀번호 마스터
2:00:36 계산기
2:06:37 함수의 형태
2:09:11 반환값이 없는 함수
2:10:54 반환값이 있는 함수
2:12:37 전달값이 없는 함수
2:13:43 전달값이 있는 함수
2:15:21 반환값과 전달값이 있는 함수
2:19:29 함수를 이용한 계산기
2:23:44 프로젝트
게임 #5
2:37:41 아빠는 대머리
2:39:08 배열 기초
2:44:08 값 설정
2:49:32 문자 vs 문자열
2:56:48 문자열 심화
3:02:44 아스키 코드
3:08:39 프로젝트
게임 #6
3:23:05 물고기 키우기
3:25:30 친구들의 주소
3:29:26 미션맨(포인터)의 등장
3:35:01 스파이(또다른 포인터)의 등장
3:40:57 배열과 포인터의 관계
3:49:39 Swap
3:56:40 포인터로 배열 값 변경하기
4:00:06 프로젝트(전반전)
4:11:18 프로젝트(후반전)
4:19:45 프로젝트(연장전)
게임 #7
4:27:34 동물 뒤집기
4:29:31 다차원 배열 기본
4:33:13 다차원 배열 접근
4:36:57 다차원 배열 선언
4:41:19 다차원 배열 사용
4:45:55 프로젝트(전반전)
5:02:25 프로젝트(후반전)
5:11:51 프로젝트(연장전)
게임 #8
5:27:17 너, 내 집사가 되어라
5:31:29 구조체 기본
5:34:41 구조체 사용
5:38:23 구조체 배열
5:39:26 구조체 포인터
5:43:25 구조체 안의 구조체
5:45:46 typedef
5:51:28 프로젝트(전반전)
6:00:36 프로젝트(후반전)
게임 #9
6:09:25 비밀 일기
6:12:09 파일 쓰기 fputs
6:19:22 파일 읽기 fgets
6:22:43 또다른 파일 쓰기 fprintf
6:26:39 또다른 파일 읽기 fscanf
6:29:55 프로젝트(전반전)
6:35:43 프로젝트(후반전) [소스코드]강의에 사용된 소스코드는 아래 경로에서 가입 없이 다운로드 가능합니다.
https://cafe.naver.com/nadocoding
(참고 : 현재는 운영되고 있지 않은 카페입니다)
Designed by freepik
: https://www.freepik.com
c 언어 게임 소스 코드 주제에 대한 자세한 내용은 여기를 참조하세요.
[C언어 게임] 구글 공룡 게임 만들기 (충돌처리 추가)
C언어 구글 게임 소스 코드 v1.0 (공룡 움직임, 점프, 나무 움직이기 등 기본 세팅). 4. 공룡 게임 소스코드 v2.0 (충돌, 시간에따른 점수 추가).
Source: blockdmask.tistory.com
Date Published: 7/2/2021
View: 2952
c언어 뱀게임 소스코드 – Kocaine! 의 코딩하는 블로그
c언어 뱀게임 소스코드. Ruminz 2018. 10. 23. 16:10 … 게임이름 : Snake Game 1.2. **************/. #include
Source: kocaine.tistory.com
Date Published: 11/9/2022
View: 1447
[C언어 게임 만들기] 테트리스 게임 (Tetris) – 네이버 블로그
Text Game Maker JS/Games: Tetris – A MEAN Blog … [C언어 게임 만들기] 테트리스 게임 (Tetris) 소스 코드 보기 …
Source: m.blog.naver.com
Date Published: 10/25/2022
View: 1085
무한의 땅굴(게임프로젝트) 소스코드 – 고딩개발자
c언어. 무한의 땅굴(게임프로젝트) 소스코드. 행운의다섯 2017. 7 …
Source: jiminon5.tistory.com
Date Published: 2/20/2021
View: 9619
C언어 공룡게임 만들기 2 – Ro_ll_ing
저번에 올렸던 소스코드에 시작메뉴와 충돌처리, 결과창 등을 추가하여 만들어 보았습니다. #define _CRT_SECURE_NO_WARNINGS #define TreeHigh 19 …
Source: confidence-10211.tistory.com
Date Published: 12/12/2022
View: 634
C언어로 게임 만들기 1. 기초 & 플레이어 움직이기 (1) 기초 함수들
본 강의는 윈도우를 기준으로 하므로, 이후에는 계속 이 버전이 등장할 예정입니다. // ANSI escape code 버전 vo gotoxy(int x, int y) …
Source: blog.moon44432.dev
Date Published: 10/3/2021
View: 5355
[C언어 소스] 3X3 퍼즐 게임 – 언제나 휴일
3X3 배열에 1부터 8까지의 수를 순서대로 나타날 수 있게 방향 키로 이동하는 단순한 콘솔 게임입니다. 3X3 퍼즐 게임. 소스 코드 //3X3 퍼즐 게임 #include …
Source: ehpub.co.kr
Date Published: 2/25/2022
View: 2479
주제와 관련된 이미지 c 언어 게임 소스 코드
주제와 관련된 더 많은 사진을 참조하십시오 C 언어 무료 강의 (입문부터 게임 개발까지). 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 c 언어 게임 소스 코드
- Author: 나도코딩
- Views: 조회수 1,276,084회
- Likes: 좋아요 30,995개
- Date Published: 2020. 9. 15.
- Video Url link: https://www.youtube.com/watch?v=q6fPjQAzll8
[C언어 게임] 구글 공룡 게임 만들기 (충돌처리 추가)
반응형
안녕하세요. BlockDMask 입니다.
C언어나 C++을 책만보고 공부만하면 재미가 없잖아요. 그래서 제가 간단한 게임을 만들어서 소개해보려 합니다.
제가 만든 게임이 게임성이 없는 프로그램 일 수 있습니다. 순전히 예제, 연습용 게임들이니 너그럽게 이해해주시면 감사하겠습니다.
오늘은 “C/C++로 게임을 만들어보자” 그 첫번째 게임인 “구글 공룡 게임”을 만들어 보았습니다.
사실 게임이라고 하기도 좀 그런게, 충돌판정이나 게임오버 점수주기 이런게 아무것도 없이, 캐릭터 움직임, 점프, 장애물 이동하기 이 세개만 만들어 보았습니다.
이영상을 통해서 “아 C/C++을 이용해서 이렇게 간단히 게임을 만들 수 있구나”를 보여드리고 싶었습니다.
<목차> 1. 게임 이름 및 설명 2. 게임영상 3. C언어 구글 게임 소스 코드 v1.0 (공룡 움직임, 점프, 나무 움직이기 등 기본 세팅) 4. 공룡 게임 소스코드 v2.0 (충돌, 시간에따른 점수 추가)
1. 게임이름 및 설명
▶ C/C++로 만든 구글 공룡 게임
▶ 구글 공룡게임 v1.0
1. z를 누르면 점프를 할 수 있습니다.
2. 공룡의 발을 번갈아 가며 출력합니다.
3. 장애물이 생성 됩니다.
2. 게임영상 (v1.0)
영상 바로가기 : https://youtu.be/TXSmQ6tpRQ4
영상 댓글에 공룡 모양을 복사할 수 있도록 댓글에 작성 해 놓았습니다.
3. 소스코드(v1.0)
코드에 주석을 최대한 자세히 달았으니, 주석을 보고도 이해가 가지 않는다면 댓글 달아주시면 답변 드리겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 //[C/C++ game] very simple google dinosaur. //BlockDMask. #include < stdio.h > #include < Windows.h > #include < conio.h > #define DINO_BOTTOM_Y 12 #define TREE_BOTTOM_Y 20 #define TREE_BOTTOM_X 45 //콘솔 창의 크기와 제목을 지정하는 함수 void SetConsoleView() { system( “mode con:cols=100 lines=25” ); system( “title Google Dinosaurs. By BlockDMask” ); } //커서의 위치를 x, y로 이동하는 함수 void GotoXY( int x, int y) { COORD Pos; Pos.X = 2 * x; Pos.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos); } //키보드의 입력을 받고, 입력된 키의 값을 반환하는 함수 int GetKeyDown() { if (_kbhit() ! = 0 ) { return _getch(); } return 0 ; } void DrawDino( int dinoY) { GotoXY( 0 , dinoY); static bool legFlag = true ; printf ( ” $$$$$$$
” ); printf ( ” $$ $$$$$$
” ); printf ( ” $$$$$$$$$
” ); printf ( “$ $$$
” ); printf ( “$$ $$$$$$$
” ); printf ( “$$$ $$$$$
” ); printf ( ” $$ $$$$$$$$$$
” ); printf ( ” $$$$$$$$$$$
” ); printf ( ” $$$$$$$$$$
” ); printf ( ” $$$$$$$$
” ); printf ( ” $$$$$$
” ); if (legFlag) { printf ( ” $ $$$
” ); printf ( ” $$ ” ); legFlag = false ; } else { printf ( ” $$$ $
” ); printf ( ” $$ ” ); legFlag = true ; } } void DrawTree( int treeX) { GotoXY(treeX, TREE_BOTTOM_Y); printf ( “$$$$” ); GotoXY(treeX, TREE_BOTTOM_Y + 1 ); printf ( ” $$ ” ); GotoXY(treeX, TREE_BOTTOM_Y + 2 ); printf ( ” $$ ” ); GotoXY(treeX, TREE_BOTTOM_Y + 3 ); printf ( ” $$ ” ); GotoXY(treeX, TREE_BOTTOM_Y + 4 ); printf ( ” $$ ” ); } int main( void ) { SetConsoleView(); bool isJumping = false ; bool isBottom = true ; const int gravity = 3 ; int dinoY = DINO_BOTTOM_Y; int treeX = TREE_BOTTOM_X; while ( true ) { //z키가 눌렸고, 바닥이 아닐때만 점프가능. if (GetKeyDown() = = ‘z’ & & isBottom) { isJumping = true ; isBottom = false ; } //점프중 = y감소 //점프끝 = y증가 if (isJumping) { dinoY – = gravity; } else { dinoY + = gravity; } //Y가 계속해서 증가하는걸 막기위해 바닥을 지정. //Y가 증가한다는 것은 공룡이 아래로 내려온다는 뜻. if (dinoY > = DINO_BOTTOM_Y) { dinoY = DINO_BOTTOM_Y; isBottom = true ; } //점프의 맨 위를 찍으면 점프가 끝난 상황 if (dinoY < = 3 ) { isJumping = false ; } //나무가 왼쪽으로 가도록 하고(x의 음수방향) //나무의 위치가 왼쪽 끝으로가면 다시 초기 위치로 소환 treeX - = 2 ; if (treeX < = 0 ) { treeX = TREE_BOTTOM_X; } DrawDino(dinoY); //draw dino DrawTree(treeX); //draw tree Sleep( 80 ); system( "cls" ); //clear } system( "pause" ); return 0 ; } Colored by Color Scripter cs 4. 구글 공룡게임 소스코드 충돌처리 및 시간 추가 ▶ 구글 공룡게임 v2 .0 1. 시간에 따라서 점수가 올라가도록 코드 추가하였습니다. 2. 충돌 처리를 넣어달라는 요청이 있어서 간단하게 한번 넣어 보았습니다. ▶ 충돌 처리 간단 설명 간단하게 충돌을 설명해보겠습니다. 제가 직접 그림을 그려보았습니다. 일단 이 게 임에서 x, y는 왼쪽위부터 0,0 이고 오른쪽으로 갈수록 x가 증가 하고 아래쪽으로 갈수록 y가 증가 하는 구조 입니다. 우리가 현재 가지고 있는것은 공룡의 Y축 좌표와 나무의 X좌표 뿐입니다. 따로 좌표를 추가하지않고 우리는 이 두가지 좌표를 통해서 "충돌" 체크를 할 수 있습니다. 말로 한번 설명 드리겠습니다. 나무의 위치X가 공룡몸통에 위치하고 && 공룡의 높이(Y위치)가 적당히 낮을때 충돌이다! 이렇게 판단할 수 있습니다. 그쵸? 그림으로 한번 표현해보겠습니다. 이해가 쑥쑥 가시죠..? 공룡의 머리 기준으로 출력하기 때문에 공룡이 평소에는 y가 12인데 점프를 뛰면 대략 3까지 올라가더군요 그래서 중간 정도인 6정도가 딱 바 에서 나무가 오면 부딪히는걸로 간주하겠다고. 코드를 작성한 것이고 나무의 위치를 보니 공룡쪽으로 오는 X가 4~8 정도가 적당하다고 판단했습니다. 그래서 생겨난 코드가 bool isCollision(const int treeX, const int dinoY) 이 함수입니다. 해당함수 내부를 보면 if (treeX <= 8 && treeX >= 4 && dinoY > 8) 만약에 X(나무)의 위치가 4~8 사이이고 공룡 머머리의 Y가 8보다 높을때(바닥에 가까울때) 충돌했다! 라고 판단하면됩니다.
▶ 구글 공룡게임 v2.0 움짤
공룡이 나무에 부딪히면 게임오버 하는걸 확인할 수 있습니다.
▶ 소스코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 //[C/C++ game] very simple google dinosaur. (by. BlockDMask) //2019.12.03 (v2.0)점수 추가, 충돌처리 추가. #include < stdio.h > #include < windows.h > #include < conio.h > #include < time.h > #define DINO_BOTTOM_Y 12 #define TREE_BOTTOM_Y 20 #define TREE_BOTTOM_X 45 //콘솔 창의 크기와 제목을 지정하는 함수 void SetConsoleView() { system( “mode con:cols=100 lines=25” ); system( “title Google Dinosaurs. By BlockDMask.” ); } //커서의 위치를 x, y로 이동하는 함수 void GotoXY( int x, int y) { COORD Pos; Pos.X = 2 * x; Pos.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos); } //키보드의 입력을 받고, 입력된 키의 값을 반환하는 함수 int GetKeyDown() { if (_kbhit() ! = 0 ) { return _getch(); } return 0 ; } //공룡을 그리는 함수 void DrawDino( int dinoY) { GotoXY( 0 , dinoY); static bool legFlag = true ; printf ( ” $$$$$$$
” ); printf ( ” $$ $$$$$$
” ); printf ( ” $$$$$$$$$
” ); printf ( “$ $$$
” ); printf ( “$$ $$$$$$$
” ); printf ( “$$$ $$$$$
” ); printf ( ” $$ $$$$$$$$$$
” ); printf ( ” $$$$$$$$$$$
” ); printf ( ” $$$$$$$$$$
” ); printf ( ” $$$$$$$$
” ); printf ( ” $$$$$$
” ); if (legFlag) { printf ( ” $ $$$
” ); printf ( ” $$ ” ); legFlag = false ; } else { printf ( ” $$$ $
” ); printf ( ” $$ ” ); legFlag = true ; } } //나무를 그리는 함수 void DrawTree( int treeX) { GotoXY(treeX, TREE_BOTTOM_Y); printf ( “$$$$” ); GotoXY(treeX, TREE_BOTTOM_Y + 1 ); printf ( ” $$ ” ); GotoXY(treeX, TREE_BOTTOM_Y + 2 ); printf ( ” $$ ” ); GotoXY(treeX, TREE_BOTTOM_Y + 3 ); printf ( ” $$ ” ); GotoXY(treeX, TREE_BOTTOM_Y + 4 ); printf ( ” $$ ” ); } //(v2.0) 충돌 했을때 게임오버 그려줌 void DrawGameOver( const int score) { system( “cls” ); int x = 18 ; int y = 8 ; GotoXY(x, y); printf ( “===========================” ); GotoXY(x, y + 1 ); printf ( “======G A M E O V E R======” ); GotoXY(x, y + 2 ); printf ( “===========================” ); GotoXY(x, y + 5 ); printf ( “SCORE : %d” , score); printf ( ”
” ); system( “pause” ); } //(v2.0) 충돌했으면 true, 아니면 false bool isCollision( const int treeX, const int dinoY) { //트리의 X가 공룡의 몸체쪽에 있을때, //공룡의 높이가 충분하지 않다면 충돌로 처리 GotoXY( 0 , 0 ); printf ( “treeX : %d, dinoY : %d” , treeX, dinoY); //이런식으로 적절한 X, Y를 찾습니다. if (treeX < = 8 & & treeX > = 4 & & dinoY > 8 ) { return true ; } return false ; } int main() { SetConsoleView(); while ( true ) //(v2.0) 게임 루프 { //게임 시작시 초기화 bool isJumping = false ; bool isBottom = true ; const int gravity = 3 ; int dinoY = DINO_BOTTOM_Y; int treeX = TREE_BOTTOM_X; int score = 0 ; clock_t start, curr; //점수 변수 초기화 start = clock(); //시작시간 초기화 while ( true ) //한 판에 대한 루프 { //(v2.0) 충돌체크 트리의 x값과 공룡의 y값으로 판단 if (isCollision(treeX, dinoY)) break ; //z키가 눌렸고, 바닥이 아닐때 점프 if (GetKeyDown() = = ‘z’ & & isBottom) { isJumping = true ; isBottom = false ; } //점프중이라면 Y를 감소, 점프가 끝났으면 Y를 증가. if (isJumping) { dinoY – = gravity; } else { dinoY + = gravity; } //Y가 계속해서 증가하는걸 막기위해 바닥을 지정. if (dinoY > = DINO_BOTTOM_Y) { dinoY = DINO_BOTTOM_Y; isBottom = true ; } //나무가 왼쪽으로 (x음수) 가도록하고 //나무의 위치가 왼쪽 끝으로가면 다시 오른쪽 끝으로 소환. treeX – = 2 ; if (treeX < = 0 ) { treeX = TREE_BOTTOM_X; } //점프의 맨위를 찍으면 점프가 끝난 상황. if (dinoY < = 3 ) { isJumping = false ; } DrawDino(dinoY); //draw dino DrawTree(treeX); //draw Tree //(v2.0) curr = clock(); //현재시간 받아오기 if (((curr - start) / CLOCKS_PER_SEC) > = 1 ) // 1초가 넘었을떄 { score + + ; //스코어 UP start = clock(); //시작시간 초기화 } Sleep( 60 ); system( “cls” ); //clear //(v2.0) 점수출력을 1초마다 해주는것이 아니라 항상 출력해주면서, 1초가 지났을때 ++ 해줍니다. GotoXY( 22 , 0 ); //커서를 가운데 위쪽으로 옮긴다. 콘솔창이 cols=100이니까 2*x이므로 22정도 넣어줌 printf ( “Score : %d ” , score); //점수 출력해줌. } //(v2.0) 게임 오버 메뉴 DrawGameOver(score); } return 0 ; } Colored by Color Scripter cs
C언어로 구글 공룡게임 만들기 이상입니다. 질문이 있다면 아래 댓글로 남겨주세요. 간단한 공룡게임 특성상 더이상 확장할것은 없을것 같네요.
소스코드 : https://github.com/BlockDMask/Google_Dino
반응형
c언어 뱀게임 소스코드
/*************
작성일자 : 2018.10.23
작성자 : Kocaine
게임이름 : Snake Game 1.2
**************/
#include < stdio.h >
#include < Windows.h >
#include < conio.h >
#include < stdlib.h >
#include < stdbool.h >
#include < time.h >
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define UP 72
#define MAPWIDTH 20
#define MAPHEIGHT 20
#define SNAKELENGTH 17
typedef struct _body
{
int x;
int y;
}Body;
Body body[ 18 ][ 18 ];
Body Temp[ 18 ][ 18 ];
typedef struct _food
{
int x;
int y;
}Food;
Food food;
int i, j;
typedef struct _logic
{
bool Up;
bool Down;
bool Right;
bool Left;
}Logic;
Logic l;
int snake[ 18 ][ 18 ] =
{
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 }
};
int map[ 20 ][ 20 ] =
{
{ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
{ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 }
};
void Map();
void Init();
void TempToBody();
void MoveCoor();
void BodyToTemp();
void Delete();
void Output();
void Move();
void FoodOutput();
void Eat();
void BodyPlus();
void Score();
void Clear();
void GameOver();
void GameExplain();
void gotoxy( int x, int y);
void CursorView( char show); //커서숨기기
void Map()
{
for (i = 0 ; i < MAPHEIGHT; i + + ) { for (j = 0 ; j < MAPWIDTH; j + + ) { if (map[i][j] = = 1 ) printf ( "■" ); else printf ( " " ); } printf ( " " ); } } void Init() { l.Up = false ; l.Down = false ; l.Right = false ; l.Left = false ; body[ 17 ][ 17 ].x = 14 ; body[ 17 ][ 17 ].y = 14 ; body[ 17 ][ 16 ].x = 12 ; body[ 17 ][ 16 ].y = 14 ; body[ 17 ][ 15 ].x = 10 ; body[ 17 ][ 15 ].y = 14 ; } void TempToBody() { bool ExitOutLoop = false ; for (i = 17 ; i > = 0 ; i – – )
{
for (j = 17 ; j > = 0 ; j – – )
{
if (snake[i][j] = = 1 )
{
Temp[i][j].x = body[i][j].x;
Temp[i][j].y = body[i][j].y;
}
if (snake[i][j] = = 0 )
{
ExitOutLoop = true ;
break ;
}
}
if (ExitOutLoop = = true )
{
ExitOutLoop = false ;
break ;
}
}
}
void MoveCoor()
{
if (l.Up = = true )
{
TempToBody();
body[ 17 ][ 17 ].y – – ;
BodyToTemp();
}
if (l.Down = = true )
{
TempToBody();
body[ 17 ][ 17 ].y + + ;
BodyToTemp();
}
if (l.Right = = true )
{
TempToBody();
body[ 17 ][ 17 ].x + = 2 ;
BodyToTemp();
}
if (l.Left = = true )
{
TempToBody();
body[ 17 ][ 17 ].x – = 2 ;
BodyToTemp();
}
}
void BodyToTemp()
{
bool ExitOutLoop = false ;
for (i = 17 ; i > 0 ; i – – )
{
for (j = 17 ; j > = 0 ; j – – )
{
if (snake[i][j] = = 0 & & j = = 0 )
{
body[i – 1 ][ 17 ].x = Temp[i][j].x;
body[i – 1 ][ 17 ].y = Temp[i][j].y;
ExitOutLoop = true ;
break ;
}
body[i][j – 1 ].x = Temp[i][j].x;
body[i][j – 1 ].y = Temp[i][j].y;
}
if (ExitOutLoop = = true )
{
ExitOutLoop = false ;
break ;
}
}
}
void Delete()
{
bool ExitOutLoop = false ;
for (i = 17 ; i > = 0 ; i – – )
{
for (j = 17 ; j > = 0 ; j – – )
{
if (snake[i][j] = = 1 )
{
gotoxy(body[i][j].x, body[i][j].y);
printf ( ” ” );
}
else
{
ExitOutLoop = true ;
break ;
}
}
if (ExitOutLoop = = true )
{
ExitOutLoop = false ;
break ;
}
}
}
void Output()
{
bool ExitOutLoop = false ;
for (i = 17 ; i > = 0 ; i – – )
{
for (j = 17 ; j > = 0 ; j – – )
{
if (snake[i][j] = = 1 )
{
gotoxy(body[i][j].x, body[i][j].y);
printf ( “■” );
}
else
{
ExitOutLoop = true ;
break ;
}
}
if (ExitOutLoop = = true )
{
ExitOutLoop = false ;
break ;
}
}
}
void Move()
{
int Time = 150 ;
while ( 1 )
{
Sleep(Time);
Delete();
MoveCoor();
Output();
Eat();
GameOver();
if (_kbhit())
break ;
}
}
void FoodOutput()
{
bool ExitOutLoop = false ;
srand(time( NULL ));
food.x = (rand() % 18 + 1 ) * 2 ;
food.y = rand() % 18 + 1 ;
for (i = 17 ; i > = 0 ; i – – )
{
for (j = 17 ; j > = 0 ; j – – )
{
if (body[i][j].x = = food.x & & body[i][j].y = = food.y)
{
food.x = (rand() % 18 + 1 ) * 2 ;
food.y = rand() % 18 + 1 ;
}
}
}
gotoxy(food.x, food.y);
printf ( “★” );
}
void Eat()
{
if (body[ 17 ][ 17 ].x = = food.x & & body[ 17 ][ 17 ].y = = food.y)
{
Score();
BodyPlus();
FoodOutput();
}
}
void BodyPlus()
{
bool ExitOutLoop = false ;
for (i = 17 ; i > = 0 ; i – – )
{
for (j = 17 ; j > = 0 ; j – – )
{
if (snake[i][j] = = 0 )
{
snake[i][j] = 1 ;
ExitOutLoop = true ;
break ;
}
}
if (ExitOutLoop = = true )
{
ExitOutLoop = false ;
break ;
}
}
}
void Score()
{
static int score = 0 ;
score + = 100 ;
gotoxy( 70 , 20 );
printf ( “점수 : %d” , score);
if (score = = 30000 )
Clear();
}
void GameOver()
{
if (body[ 17 ][ 17 ].x > = 38 | | body[ 17 ][ 17 ].x < = 0 ) { system( "cls" ); printf ( "게임 오버" ); exit( 0 ); } if (body[ 17 ][ 17 ].y > = 19 | | body[ 17 ][ 17 ].y < = 0 ) { system( "cls" ); printf ( "게임 오버" ); exit( 0 ); } for (i = 17 ; i > = 0 ; i – – )
{
for (j = 16 ; j > = 0 ; j – – )
{
if (body[ 17 ][ 17 ].x = = body[i][j].x & &
body[ 17 ][ 17 ].y = = body[i][j].y)
{
system( “cls” );
printf ( “게임 오버” );
exit( 0 );
}
}
}
}
void GameExplain()
{
gotoxy( 70 , 10 );
puts( “처음엔 왼쪽키 안됨” );
gotoxy( 70 , 11 );
puts( “방향키 : 이동” );
gotoxy( 70 , 12 );
puts( “머리가 몸이나 벽에 닿을시 게임오버” );
gotoxy( 70 , 13 );
puts( “별을 먹으면 점수 +100” );
gotoxy( 70 , 14 );
puts( “q누르면 게임종료” );
}
void Clear()
{
system( “cls” );
printf ( “클리어” );
exit( 0 );
}
int main()
{
int key;
Map();
CursorView( 0 );
Init();
Output();
FoodOutput();
while ( 1 )
{
GameExplain();
if (_kbhit())
{
key = _getch();
if (key = = ‘q’ )
break ;
switch (key)
{
case UP:
if (l.Down = = true )
l.Up = false ;
else
{
l.Up = true ;
l.Down = false ;
l.Right = false ;
l.Left = false ;
}
Move();
break ;
case DOWN:
if (l.Up = = true )
l.Down = false ;
else
{
l.Down = true ;
l.Up = false ;
l.Right = false ;
l.Left = false ;
}
Move();
break ;
case LEFT:
if (body[ 17 ][ 17 ].x = = 14 & & body[ 17 ][ 17 ].y = = 14 )
l.Left = false ;
else if (l.Right = = true )
l.Left = false ;
else
{
l.Left = true ;
l.Down = false ;
l.Right = false ;
l.Up = false ;
}
Move();
break ;
case RIGHT:
if (l.Left = = true )
l.Right = false ;
else
{
l.Right = true ;
l.Down = false ;
l.Up = false ;
l.Left = false ;
}
Move();
break ;
default :
break ;
}
}
}
return 0 ;
}
void gotoxy( int x, int y)
{
COORD Pos = { x, y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}
void CursorView( char show) //커서숨기기
{
HANDLE hConsole;
CONSOLE_CURSOR_INFO ConsoleCursor;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
ConsoleCursor.bVisible = show;
ConsoleCursor.dwSize = 1 ;
SetConsoleCursorInfo(hConsole, & ConsoleCursor);
}
[C언어 게임 만들기] 테트리스 게임 (Tetris)
#include < stdio.h >
#include < windows.h >
#include < conio.h >
#include < time.h >
#include < stdlib.h >
#define LEFT 75 //좌로 이동 //키보드값들
#define RIGHT 77 //우로 이동
#define UP 72 //회전
#define DOWN 80 //soft drop
#define SPACE 32 //hard drop
#define p 112 //일시정지
#define P 80 //일시정지
#define ESC 27 //게임종료
#define false 0
#define true 1
#define ACTIVE_BLOCK – 2 // 게임판배열에 저장될 블록의 상태들
#define CEILLING – 1 // 블록이 이동할 수 있는 공간은 0 또는 음의 정수료 표현
#define EMPTY 0 // 블록이 이동할 수 없는 공간은 양수로 표현
#define WALL 1
#define INACTIVE_BLOCK 2 // 이동이 완료된 블록값
#define MAIN_X 11 //게임판 가로크기
#define MAIN_Y 23 //게임판 세로크기
#define MAIN_X_ADJ 3 //게임판 위치조정
#define MAIN_Y_ADJ 1 //게임판 위치조정
#define STATUS_X_ADJ MAIN_X_ADJ + MAIN_X + 1 //게임정보표시 위치조정
int STATUS_Y_GOAL; //GOAL 정보표시위치Y 좌표 저장
int STATUS_Y_LEVEL; //LEVEL 정보표시위치Y 좌표 저장
int STATUS_Y_SCORE; //SCORE 정보표시위치Y 좌표 저장
int blocks[ 7 ][ 4 ][ 4 ][ 4 ] = {
{{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 }},
{{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 },{ 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 },{ 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 }},
{{ 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 }},
{{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 }},
{{ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 0 }},
{{ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 }},
{{ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 0 },{ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 }}
}; //블록모양 저장 4*4공간에 블록을 표현 blcoks[b_type][b_rotation][i][j]로 사용
int b_type; //블록 종류를 저장
int b_rotation; //블록 회전값 저장
int b_type_next; //다음 블록값 저장
int main_org[MAIN_Y][MAIN_X]; //게임판의 정보를 저장하는 배열 모니터에 표시후에 main_cpy로 복사됨
int main_cpy[MAIN_Y][MAIN_X]; //즉 maincpy는 게임판이 모니터에 표시되기 전의 정보를 가지고 있음
//main의 전체를 계속 모니터에 표시하지 않고(이렇게 하면 모니터가 깜빡거림)
//main_cpy와 배열을 비교해서 값이 달라진 곳만 모니터에 고침
int bx,by; //이동중인 블록의 게임판상의 x,y좌표를 저장
int key; //키보드로 입력받은 키값을 저장
int speed; //게임진행속도
int level; //현재 level
int level_goal; //다음레벨로 넘어가기 위한 목표점수
int cnt; //현재 레벨에서 제거한 줄 수를 저장
int score; //현재 점수
int last_score = 0 ; //마지막게임점수
int best_score = 0 ; //최고게임점수
int new_block_on = 0 ; //새로운 블럭이 필요함을 알리는 flag
int crush_on = 0 ; //현재 이동중인 블록이 충돌상태인지 알려주는 flag
int level_up_on = 0 ; //다음레벨로 진행(현재 레벨목표가 완료되었음을) 알리는 flag
int space_key_on = 0 ; //hard drop상태임을 알려주는 flag
void title( void ); //게임시작화면
void reset( void ); //게임판 초기화
void reset_main( void ); //메인 게임판(main_org[][]를 초기화)
void reset_main_cpy( void ); //copy 게임판(main_cpy[][]를 초기화)
void draw_map( void ); //게임 전체 인터페이스를 표시
void draw_main( void ); //게임판을 그림
void new_block( void ); //새로운 블록을 하나 만듦
void check_key( void ); //키보드로 키를 입력받음
void drop_block( void ); //블록을 아래로 떨어트림
int check_crush( int bx, int by, int rotation); //bx, by위치에 rotation회전값을 같는 경우 충돌 판단
void move_block( int dir); //dir방향으로 블록을 움직임
void check_line( void ); //줄이 가득찼는지를 판단하고 지움
void check_level_up( void ); //레벨목표가 달성되었는지를 판단하고 levelup시킴
void check_game_over( void ); //게임오버인지 판단하고 게임오버를 진행
void pause( void ); //게임을 일시정지시킴
void gotoxy( int x, int y) { //gotoxy함수
COORD pos = { 2 * x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
typedef enum { NOCURSOR, SOLIDCURSOR, NORMALCURSOR } CURSOR_TYPE; //커서숨기는 함수에 사용되는 열거형
void setcursortype(CURSOR_TYPE c){ //커서숨기는 함수
CONSOLE_CURSOR_INFO CurInfo;
switch (c) {
case NOCURSOR:
CurInfo.dwSize = 1 ;
CurInfo.bVisible = FALSE;
break ;
case SOLIDCURSOR:
CurInfo.dwSize = 100 ;
CurInfo.bVisible = TRUE;
break ;
case NORMALCURSOR:
CurInfo.dwSize = 20 ;
CurInfo.bVisible = TRUE;
break ;
}
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&CurInfo);
}
int main(){
int i;
srand(( unsigned )time(NULL)); //난수표생성
setcursortype(NOCURSOR); //커서 없앰
title(); //메인타이틀 호출
reset(); //게임판 리셋
while ( 1 ){
for (i = 0 ;i < 5 ;i + + ){ //블록이 한칸떨어지는동안 5번 키입력받을 수 있음 check_key(); //키입력확인 draw_main(); //화면을 그림 Sleep(speed); //게임속도조절 if (crush_on&&check_crush(bx,by + 1 , b_rotation) = = false ) Sleep( 100 ); //블록이 충돌중인경우 추가로 이동및 회전할 시간을 갖음 if (space_key_on = = 1 ) { //스페이스바를 누른경우(hard drop) 추가로 이동및 회전할수 없음 break; space_key_on = 0 ; break ; } } drop_block(); // 블록을 한칸 내림 check_level_up(); // 레벨업을 체크 check_game_over(); //게임오버를 체크 if (new_block_on = = 1 ) new_block(); // 뉴 블럭 flag가 있는 경우 새로운 블럭 생성 } } void title( void ){ int x = 5 ; //타이틀화면이 표시되는 x좌표 int y = 4 ; //타이틀화면이 표시되는 y좌표 int cnt; //타이틀 프레임을 세는 변수 gotoxy(x,y + 0 );printf( "■□□□■■■□□■■□□■■" );Sleep( 100 ); gotoxy(x,y + 1 );printf( "■■■□ ■□□ ■■□□■" );Sleep( 100 ); gotoxy(x,y + 2 );printf( "□□□■ □■ ■" );Sleep( 100 ); gotoxy(x,y + 3 );printf( "■■□■■ □ ■ □□■□□" );Sleep( 100 ); gotoxy(x,y + 4 );printf( "■■ ■□□□■■■□■■□□" );Sleep( 100 ); gotoxy(x,y + 5 );printf( " blog.naver.com/azure0777" );Sleep( 100 ); gotoxy(x + 5 ,y + 2 );printf( "T E T R I S" );Sleep( 100 ); gotoxy(x,y + 7 );printf( "Please Enter Any Key to Start.." ); gotoxy(x,y + 9 ); printf( " △ : Shift" ); gotoxy(x,y + 10 ); printf( "◁ ▷ : Left / Right" ); gotoxy(x,y + 11 ); printf( " ▽ : Soft Drop" ); gotoxy(x,y + 12 ); printf( " SPACE : Hard Drop" ); gotoxy(x,y + 13 ); printf( " P : Pause" ); gotoxy(x,y + 14 ); printf( " ESC : Quit" ); gotoxy(x,y + 16 ); printf( "BONUS FOR HARD DROPS / COMBOS" ); for (cnt = 0 ;;cnt + + ){ //cnt를 1씩 증가시키면서 계속 반복 //하나도 안중요한 별 반짝이는 애니메이션효과 if (kbhit()) break ; //키입력이 있으면 무한루프 종료 if (cnt% 200 = = 0 ){gotoxy(x + 4 ,y + 1 );printf( "★" );} //cnt가 200으로 나누어 떨어질때 별을 표시 if ((cnt% 200 - 100 ) = = 0 ){gotoxy(x + 4 ,y + 1 );printf( " " );} //위 카운트에서 100카운트 간격으로 별을 지움 if ((cnt% 350 ) = = 0 ){gotoxy(x + 13 ,y + 2 );printf( "☆" );} //윗별과 같지만 시간차를 뒀음 if ((cnt% 350 - 100 ) = = 0 ){gotoxy(x + 13 ,y + 2 );printf( " " );} Sleep( 10 ); // 00.1초 딜레이 } while (kbhit()) getch(); //버퍼에 기록된 키값을 버림 } void reset( void ){ FILE * file = fopen( "score.dat" , "rt" ); // score.dat파일을 연결 if (file = = 0 ){best_score = 0 ;} //파일이 없으면 걍 최고점수에 0을 넣음 else { fscanf(file, "%d" , &best_score); // 파일이 열리면 최고점수를 불러옴 fclose(file); //파일 닫음 } level = 1 ; //각종변수 초기화 score = 0 ; level_goal = 1000 ; key = 0 ; crush_on = 0 ; cnt = 0 ; speed = 100 ; system( "cls" ); //화면지움 reset_main(); // main_org를 초기화 draw_map(); // 게임화면을 그림 draw_main(); // 게임판을 그림 b_type_next = rand()% 7 ; //다음번에 나올 블록 종류를 랜덤하게 생성 new_block(); //새로운 블록을 하나 만듦 } void reset_main( void ){ //게임판을 초기화 int i,j; for (i = 0 ;i < MAIN_Y;i + + ){ // 게임판을 0으로 초기화 for (j = 0 ;j < MAIN_X;j + + ){ main_org[i][j] = 0 ; main_cpy[i][j] = 100 ; } } for (j = 1 ;j < MAIN_X;j + + ){ //y값이 3인 위치에 천장을 만듦 main_org[ 3 ][j] = CEILLING; } for (i = 1 ;i < MAIN_Y - 1 ;i + + ){ //좌우 벽을 만듦 main_org[i][ 0 ] = WALL; main_org[i][MAIN_X - 1 ] = WALL; } for (j = 0 ;j < MAIN_X;j + + ){ //바닥벽을 만듦 main_org[MAIN_Y - 1 ][j] = WALL; } } void reset_main_cpy( void ){ //main_cpy를 초기화 int i, j; for (i = 0 ;i < MAIN_Y;i + + ){ //게임판에 게임에 사용되지 않는 숫자를 넣음 for (j = 0 ;j < MAIN_X;j + + ){ //이는 main_org와 같은 숫자가 없게 하기 위함 main_cpy[i][j] = 100 ; } } } void draw_map( void ){ //게임 상태 표시를 나타내는 함수 int y = 3 ; // level, goal, score만 게임중에 값이 바뀔수 도 있음 그 y값을 따로 저장해둠 // 그래서 혹시 게임 상태 표시 위치가 바뀌어도 그 함수에서 안바꿔도 되게.. gotoxy(STATUS_X_ADJ, STATUS_Y_LEVEL = y); printf( " LEVEL : %5d" , level); gotoxy(STATUS_X_ADJ, STATUS_Y_GOAL = y + 1 ); printf( " GOAL : %5d" , 10 - cnt); gotoxy(STATUS_X_ADJ, y + 2 ); printf( "+- N E X T -+ " ); gotoxy(STATUS_X_ADJ, y + 3 ); printf( "| | " ); gotoxy(STATUS_X_ADJ, y + 4 ); printf( "| | " ); gotoxy(STATUS_X_ADJ, y + 5 ); printf( "| | " ); gotoxy(STATUS_X_ADJ, y + 6 ); printf( "| | " ); gotoxy(STATUS_X_ADJ, y + 7 ); printf( "+-- - - - --+ " ); gotoxy(STATUS_X_ADJ, y + 8 ); printf( " YOUR SCORE :" ); gotoxy(STATUS_X_ADJ, STATUS_Y_SCORE = y + 9 ); printf( " %6d" , score); gotoxy(STATUS_X_ADJ, y + 10 ); printf( " LAST SCORE :" ); gotoxy(STATUS_X_ADJ, y + 11 ); printf( " %6d" , last_score); gotoxy(STATUS_X_ADJ, y + 12 ); printf( " BEST SCORE :" ); gotoxy(STATUS_X_ADJ, y + 13 ); printf( " %6d" , best_score); gotoxy(STATUS_X_ADJ, y + 15 ); printf( " △ : Shift SPACE : Hard Drop" ); gotoxy(STATUS_X_ADJ, y + 16 ); printf( "◁ ▷ : Left / Right P : Pause" ); gotoxy(STATUS_X_ADJ, y + 17 ); printf( " ▽ : Soft Drop ESC : Quit" ); gotoxy(STATUS_X_ADJ, y + 20 );printf( "blog.naver.com/azure0777" ); } void draw_main( void ){ //게임판 그리는 함수 int i, j; for (j = 1 ;j < MAIN_X - 1 ;j + + ){ //천장은 계속 새로운블럭이 지나가서 지워지면 새로 그려줌 if (main_org[ 3 ][j] = = EMPTY) main_org[ 3 ][j] = CEILLING; } for (i = 0 ;i < MAIN_Y;i + + ){ for (j = 0 ;j < MAIN_X;j + + ){ if (main_cpy[i][j] ! = main_org[i][j]){ //cpy랑 비교해서 값이 달라진 부분만 새로 그려줌. //이게 없으면 게임판전체를 계속 그려서 느려지고 반짝거림 gotoxy(MAIN_X_ADJ + j,MAIN_Y_ADJ + i); switch (main_org[i][j]){ case EMPTY: //빈칸모양 printf( " " ); break ; case CEILLING: //천장모양 printf( ". " ); break ; case WALL: //벽모양 printf( "▩" ); break ; case INACTIVE_BLOCK: //굳은 블럭 모양 printf( "□" ); break ; case ACTIVE_BLOCK: //움직이고있는 블럭 모양 printf( "■" ); break ; } } } } for (i = 0 ;i < MAIN_Y;i + + ){ //게임판을 그린 후 main_cpy에 복사 for (j = 0 ;j < MAIN_X;j + + ){ main_cpy[i][j] = main_org[i][j]; } } } void new_block( void ){ //새로운 블록 생성 int i, j; bx = (MAIN_X / 2 ) - 1 ; //블록 생성 위치x좌표(게임판의 가운데) by = 0 ; //블록 생성위치 y좌표(제일 위) b_type = b_type_next; //다음블럭값을 가져옴 b_type_next = rand()% 7 ; //다음 블럭을 만듦 b_rotation = 0 ; //회전은 0번으로 가져옴 new_block_on = 0 ; //new_block flag를 끔 for (i = 0 ;i < 4 ;i + + ){ //게임판 bx, by위치에 블럭생성 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = ACTIVE_BLOCK; } } for (i = 1 ;i < 3 ;i + + ){ //게임상태표시에 다음에 나올블럭을 그림 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type_next][ 0 ][i][j] = = 1 ) { gotoxy(STATUS_X_ADJ + 2 + j,i + 6 ); printf( "■" ); } else { gotoxy(STATUS_X_ADJ + 2 + j,i + 6 ); printf( " " ); } } } } void check_key( void ){ key = 0 ; //키값 초기화 if (kbhit()){ //키입력이 있는 경우 key = getch(); //키값을 받음 if (key = = 224 ){ //방향키인경우 do {key = getch();} while (key = = 224 ); //방향키지시값을 버림 switch (key){ case LEFT: //왼쪽키 눌렀을때 if (check_crush(bx - 1 ,by,b_rotation) = = true ) move_block(LEFT); break ; //왼쪽으로 갈 수 있는지 체크 후 가능하면 이동 case RIGHT: //오른쪽 방향키 눌렀을때- 위와 동일하게 처리됨 if (check_crush(bx + 1 ,by,b_rotation) = = true ) move_block(RIGHT); break ; case DOWN: //아래쪽 방향키 눌렀을때-위와 동일하게 처리됨 if (check_crush(bx,by + 1 ,b_rotation) = = true ) move_block(DOWN); break ; case UP: //위쪽 방향키 눌렀을때 if (check_crush(bx,by,(b_rotation + 1 )% 4 ) = = true ) move_block(UP); //회전할 수 있는지 체크 후 가능하면 회전 else if (crush_on = = 1&&check_crush(bx,by - 1 ,(b_rotation + 1 )% 4 ) = = true ) move_block( 100 ); } //바닥에 닿은 경우 위쪽으로 한칸띄워서 회전이 가능하면 그렇게 함(특수동작) } else { //방향키가 아닌경우 switch (key){ case SPACE: //스페이스키 눌렀을때 space_key_on = 1 ; //스페이스키 flag를 띄움 while (crush_on = = 0 ){ //바닥에 닿을때까지 이동시킴 drop_block(); score + = level; // hard drop 보너스 gotoxy(STATUS_X_ADJ, STATUS_Y_SCORE); printf( " %6d" , score); //점수 표시 } break ; case P: //P(대문자) 눌렀을때 case p: //p(소문자) 눌렀을때 pause(); //일시정지 break ; case ESC: //ESC눌렀을때 system( "cls" ); //화면을 지우고 exit( 0 ); //게임종료 } } } while (kbhit()) getch(); //키버퍼를 비움 } void drop_block( void ){ int i,j; if (crush_on&&check_crush(bx,by + 1 , b_rotation) = = true ) crush_on = 0 ; //밑이 비어있으면 crush flag 끔 if (crush_on&&check_crush(bx,by + 1 , b_rotation) = = false ){ //밑이 비어있지않고 crush flag가 켜저있으면 for (i = 0 ;i < MAIN_Y;i + + ){ //현재 조작중인 블럭을 굳힘 for (j = 0 ;j < MAIN_X;j + + ){ if (main_org[i][j] = = ACTIVE_BLOCK) main_org[i][j] = INACTIVE_BLOCK; } } crush_on = 0 ; //flag를 끔 check_line(); //라인체크를 함 new_block_on = 1 ; //새로운 블럭생성 flag를 켬 return ; //함수 종료 } if (check_crush(bx,by + 1 , b_rotation) = = true ) move_block(DOWN); //밑이 비어있으면 밑으로 한칸 이동 if (check_crush(bx,by + 1 , b_rotation) = = false ) crush_on + + ; //밑으로 이동이 안되면 crush flag를 켬 } int check_crush( int bx, int by, int b_rotation){ //지정된 좌표와 회전값으로 충돌이 있는지 검사 int i,j; for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ //지정된 위치의 게임판과 블럭모양을 비교해서 겹치면 false를 리턴 if (blocks[b_type][b_rotation][i][j] = = 1&&main_org[by + i][bx + j] > 0 ) return false ;
}
}
return true ; //하나도 안겹치면 true리턴
};
void move_block( int dir){ //블록을 이동시킴
int i,j;
switch (dir){
case LEFT: //왼쪽방향
for (i = 0 ;i < 4 ;i + + ){ //현재좌표의 블럭을 지움 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = EMPTY; } } for (i = 0 ;i < 4 ;i + + ){ //왼쪽으로 한칸가서 active block을 찍음 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j - 1 ] = ACTIVE_BLOCK; } } bx - - ; //좌표값 이동 break ; case RIGHT: //오른쪽 방향. 왼쪽방향이랑 같은 원리로 동작 for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = EMPTY; } } for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j + 1 ] = ACTIVE_BLOCK; } } bx + + ; break ; case DOWN: //아래쪽 방향. 왼쪽방향이랑 같은 원리로 동작 for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = EMPTY; } } for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i + 1 ][bx + j] = ACTIVE_BLOCK; } } by + + ; break ; case UP: //키보드 위쪽 눌렀을때 회전시킴. for (i = 0 ;i < 4 ;i + + ){ //현재좌표의 블럭을 지움 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = EMPTY; } } b_rotation = (b_rotation + 1 )% 4 ; //회전값을 1증가시킴(3에서 4가 되는 경우는 0으로 되돌림) for (i = 0 ;i < 4 ;i + + ){ //회전된 블록을 찍음 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = ACTIVE_BLOCK; } } break ; case 100 : //블록이 바닥, 혹은 다른 블록과 닿은 상태에서 한칸위로 올려 회전이 가능한 경우 //이를 동작시키는 특수동작 for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i][bx + j] = EMPTY; } } b_rotation = (b_rotation + 1 )% 4 ; for (i = 0 ;i < 4 ;i + + ){ for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type][b_rotation][i][j] = = 1 ) main_org[by + i - 1 ][bx + j] = ACTIVE_BLOCK; } } by - - ; break ; } } void check_line( void ){ int i, j, k, l; int block_amount; //한줄의 블록갯수를 저장하는 변수 int combo = 0 ; //콤보갯수 저장하는 변수 지정및 초기화 for (i = MAIN_Y - 2 ;i > 3 ;){ //i=MAIN_Y-2 : 밑쪽벽의 윗칸부터, i>3 : 천장(3)아래까지 검사
block_amount = 0 ; //블록갯수 저장 변수 초기화
for (j = 1 ;j < MAIN_X - 1 ;j + + ){ //벽과 벽사이의 블록갯루를 셈 if (main_org[i][j] > 0 ) block_amount + + ;
}
if (block_amount = = MAIN_X – 2 ){ //블록이 가득 찬 경우
if (level_up_on = = 0 ){ //레벨업상태가 아닌 경우에(레벨업이 되면 자동 줄삭제가 있음)
score + = 100 * level; //점수추가
cnt + + ; //지운 줄 갯수 카운트 증가
combo + + ; //콤보수 증가
}
for (k = i;k > 1 ;k – – ){ //윗줄을 한칸씩 모두 내림(윗줄이 천장이 아닌 경우에만)
for (l = 1 ;l < MAIN_X - 1 ;l + + ){ if (main_org[k - 1 ][l] ! = CEILLING) main_org[k][l] = main_org[k - 1 ][l]; if (main_org[k - 1 ][l] = = CEILLING) main_org[k][l] = EMPTY; //윗줄이 천장인 경우에는 천장을 한칸 내리면 안되니까 빈칸을 넣음 } } } else i - - ; } if (combo){ //줄 삭제가 있는 경우 점수와 레벨 목표를 새로 표시함 if (combo > 1 ){ //2콤보이상인 경우 경우 보너스및 메세지를 게임판에 띄웠다가 지움
gotoxy(MAIN_X_ADJ + (MAIN_X / 2 ) – 1 ,MAIN_Y_ADJ + by – 2 );printf( “%d COMBO!” ,combo);
Sleep( 500 );
score + = (combo * level * 100 );
reset_main_cpy(); //텍스트를 지우기 위해 main_cpy을 초기화.
//(main_cpy와 main_org가 전부 다르므로 다음번 draw()호출시 게임판 전체를 새로 그리게 됨)
}
gotoxy(STATUS_X_ADJ, STATUS_Y_GOAL); printf( ” GOAL : %5d” , (cnt < = 10 )? 10 - cnt: 0 ); gotoxy(STATUS_X_ADJ, STATUS_Y_SCORE); printf( " %6d" , score); } } void check_level_up( void ){ int i, j; if (cnt > = 10 ){ //레벨별로 10줄씩 없애야함. 10줄이상 없앤 경우
draw_main();
level_up_on = 1 ; //레벨업 flag를 띄움
level + = 1 ; //레벨을 1 올림
cnt = 0 ; //지운 줄수 초기화
for (i = 0 ;i < 4 ;i + + ){ gotoxy(MAIN_X_ADJ + (MAIN_X / 2 ) - 3 ,MAIN_Y_ADJ + 4 ); printf( " " ); gotoxy(MAIN_X_ADJ + (MAIN_X / 2 ) - 2 ,MAIN_Y_ADJ + 6 ); printf( " " ); Sleep( 200 ); gotoxy(MAIN_X_ADJ + (MAIN_X / 2 ) - 3 ,MAIN_Y_ADJ + 4 ); printf( "☆LEVEL UP!☆" ); gotoxy(MAIN_X_ADJ + (MAIN_X / 2 ) - 2 ,MAIN_Y_ADJ + 6 ); printf( "☆SPEED UP!☆" ); Sleep( 200 ); } reset_main_cpy(); //텍스트를 지우기 위해 main_cpy을 초기화. //(main_cpy와 main_org가 전부 다르므로 다음번 draw()호출시 게임판 전체를 새로 그리게 됨) for (i = MAIN_Y - 2 ;i > MAIN_Y – 2 – (level – 1 );i – – ){ //레벨업보상으로 각 레벨-1의 수만큼 아랫쪽 줄을 지워줌
for (j = 1 ;j < MAIN_X - 1 ;j + + ){ main_org[i][j] = INACTIVE_BLOCK; // 줄을 블록으로 모두 채우고 gotoxy(MAIN_X_ADJ + j,MAIN_Y_ADJ + i); // 별을 찍어줌.. 이뻐보이게 printf( "★" ); Sleep( 20 ); } } Sleep( 100 ); //별찍은거 보여주기 위해 delay check_line(); //블록으로 모두 채운것 지우기 //.check_line()함수 내부에서 level up flag가 켜져있는 경우 점수는 없음. switch (level){ //레벨별로 속도를 조절해줌. case 2 : speed = 50 ; break ; case 3 : speed = 25 ; break ; case 4 : speed = 10 ; break ; case 5 : speed = 5 ; break ; case 6 : speed = 4 ; break ; case 7 : speed = 3 ; break ; case 8 : speed = 2 ; break ; case 9 : speed = 1 ; break ; case 10 : speed = 0 ; break ; } level_up_on = 0 ; //레벨업 flag꺼줌 gotoxy(STATUS_X_ADJ, STATUS_Y_LEVEL); printf( " LEVEL : %5d" , level); //레벨표시 gotoxy(STATUS_X_ADJ, STATUS_Y_GOAL); printf( " GOAL : %5d" , 10 - cnt); // 레벨목표 표시 } } void check_game_over( void ){ int i; int x = 5 ; int y = 5 ; for (i = 1 ;i < MAIN_X - 2 ;i + + ){ if (main_org[ 3 ][i] > 0 ){ //천장(위에서 세번째 줄)에 inactive가 생성되면 게임 오버
gotoxy(x,y + 0 ); printf( “▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤” ); //게임오버 메세지
gotoxy(x,y + 1 ); printf( “▤ ▤” );
gotoxy(x,y + 2 ); printf( “▤ +———————–+ ▤” );
gotoxy(x,y + 3 ); printf( “▤ | G A M E O V E R.. | ▤” );
gotoxy(x,y + 4 ); printf( “▤ +———————–+ ▤” );
gotoxy(x,y + 5 ); printf( “▤ YOUR SCORE: %6d ▤” ,score);
gotoxy(x,y + 6 ); printf( “▤ ▤” );
gotoxy(x,y + 7 ); printf( “▤ Press any key to restart.. ▤” );
gotoxy(x,y + 8 ); printf( “▤ ▤” );
gotoxy(x,y + 9 ); printf( “▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤” );
last_score = score; //게임점수를 옮김
if (score > best_score){ //최고기록 갱신시
FILE * file = fopen( “score.dat” , “wt” ); //score.dat에 점수 저장
gotoxy(x,y + 6 ); printf( “▤ ★★★ BEST SCORE! ★★★ ▤ ” );
if (file = = 0 ){ //파일 에러메세지
gotoxy( 0 , 0 );
printf( “FILE ERROR: SYSTEM CANNOT WRITE BEST SCORE ON \”SCORE.DAT\”” );
}
else {
fprintf(file, “%d” , score);
fclose(file);
}
}
Sleep( 1000 );
while (kbhit()) getch();
key = getch();
reset();
}
}
}
void pause( void ){ //게임 일시정지 함수
int i,j;
int x = 5 ;
int y = 5 ;
for (i = 1 ;i < MAIN_X - 2 ;i + + ){ //게임 일시정지 메세지 gotoxy(x,y + 0 ); printf( "▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤" ); gotoxy(x,y + 1 ); printf( "▤ ▤" ); gotoxy(x,y + 2 ); printf( "▤ +-----------------------+ ▤" ); gotoxy(x,y + 3 ); printf( "▤ | P A U S E | ▤" ); gotoxy(x,y + 4 ); printf( "▤ +-----------------------+ ▤" ); gotoxy(x,y + 5 ); printf( "▤ Press any key to resume.. ▤" ); gotoxy(x,y + 6 ); printf( "▤ ▤" ); gotoxy(x,y + 7 ); printf( "▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤▤" ); } getch(); //키입력시까지 대기 system( "cls" ); //화면 지우고 새로 그림 reset_main_cpy(); draw_main(); draw_map(); for (i = 1 ;i < 3 ;i + + ){ // 다음블록 그림 for (j = 0 ;j < 4 ;j + + ){ if (blocks[b_type_next][ 0 ][i][j] = = 1 ) { gotoxy(MAIN_X + MAIN_X_ADJ + 3 + j,i + 6 ); printf( "■" ); } else { gotoxy(MAIN_X + MAIN_X_ADJ + 3 + j,i + 6 ); printf( " " ); } } }
무한의 땅굴(게임프로젝트) 소스코드
#include
#include #include #include #include #define ESC 27 #define LEFT 75 #define RIGHT 77 #define DOWN 80 #define ENTER 13 int current_score = 0;//현재 점수 int best_score = 0;//최고 점수 int coin = 0;//동전 갯수 void gotoxy(int x, int y) { COORD pos = { x – 1, y – 1 }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); }//입력한 좌표로 커서를 이동시켜 주는 함수 void SetColor(int color) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color); } enum { BLACK, DARK_BLUE, DARK_GREEN, DARK_SKYBLUE, DARK_RED, DARK_VIOLET, DARK_YELLOW, GRAY, DARK_GRAY, BLUE, GREEN, SKYBLUE, RED, VIOLET, YELLOW, WHITE, };//색깔 설정 함수 정의 typedef enum { NOCURSOR, SOLIDCURSOR, NORMALCURSOR } CURSOR_TYPE; void setcursortype(CURSOR_TYPE c) { CONSOLE_CURSOR_INFO CurInfo; switch (c) { case NOCURSOR: CurInfo.dwSize = 1; CurInfo.bVisible = FALSE; break; case SOLIDCURSOR: CurInfo.dwSize = 100; CurInfo.bVisible = TRUE; break; case NORMALCURSOR: CurInfo.dwSize = 20; CurInfo.bVisible = TRUE; break; } SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CurInfo); }//커서 숨기는 함수 정의 void main_screen() { system(“mode con cols=80 lines=25”); int x = 23, y = 17; gotoxy(x, y); printf(“+——————————–+”); gotoxy(x, y + 1); printf(“| 무한의 땅굴 |”); gotoxy(x, y + 2); printf(“+——————————–+”);//게임 제목 for (int i = 1; i <= 25; ++i) { SetColor(GRAY); gotoxy(1, i); printf("▼"); Sleep(20); }//왼쪽 화살표 내려옴 for (int i = 25; i >= 1; –i) { SetColor(GRAY); gotoxy(78, i); printf(“▲”); Sleep(20); }//오른쪽 화살표 올라옴 SetColor(DARK_YELLOW); int a = 30, b = 7; gotoxy(a, b + 9); printf(” ■■”); Sleep(50); gotoxy(a, b + 8); printf(” ■■”); Sleep(50); gotoxy(a, b + 7); printf(” ■■”); Sleep(50); gotoxy(a, b + 6); printf(” ■■”); Sleep(50); gotoxy(a, b + 5); printf(” ■■”); Sleep(50); gotoxy(a, b + 4); printf(“■ ■■ ■”); Sleep(50); gotoxy(a, b + 3); printf(” ■■ ■■ ■■”); Sleep(50); gotoxy(a, b + 2); printf(” ■■■■■■■”); Sleep(50); gotoxy(a, b + 1); printf(” ■■■■■”); Sleep(50); gotoxy(a, b); printf(” ■■■”); Sleep(50); //도끼 그리기 for (int i = 25; i >= 1; –i) { SetColor(BLACK); gotoxy(78, i); printf(“▲”); Sleep(10); }//오른쪽 화살표 지움 for (int i = 1; i <= 25; ++i) { SetColor(BLACK); gotoxy(1, i); printf("▼"); Sleep(10); }//왼쪽 화살표 지움 for (int i = 1; i <= 8; ++i) { if (i == i) { SetColor(BLACK); gotoxy(x, y + 3); printf("■■■■■■■■■■■■■■■■■■■■■"); } Sleep(60); SetColor(RED); gotoxy(x, y + 3); printf(" “); Sleep(60); }//게임시작법 안내 getch(); } int tutorial() { system(“cls”);//화면 초기화 해줌 system(“mode con cols=94 lines=23”);//콘솔창 크기 조절 int x = 4, y = 3; gotoxy(x, y); printf(“■■■■■ ■ ■ ■■■■■ ■■■■■ ■■■■ ■■■■■ ■ ■”); gotoxy(x, y + 1); printf(” ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■ “); gotoxy(x, y + 2); printf(” ■ ■ ■ ■ ■ ■ ■■■■ ■ ■ ■ ■”); gotoxy(x, y + 3); printf(” ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■■ ■”); gotoxy(x, y + 4); printf(” ■ ■■■■■ ■ ■■■■■ ■ ■■ ■ ■ ■ ■■■■■”); y = 5; SetColor(VIOLET); gotoxy(x, y + 7); printf(“How to play?”); SetColor(WHITE); gotoxy(x + 20, y + 7); printf(“Follow the stairs!!”); gotoxy(x + 20, y + 9); printf(“Press ‘→’ key to move right”); gotoxy(x + 20, y + 11); printf(“Press ‘←’ key to move left”); gotoxy(x + 20, y + 13); printf(“Press ‘↓’ key to move down”); Sleep(700); gotoxy(x + 70, y + 7); printf(“옷”); gotoxy(x + 70, y + 8); printf(“〓”); Sleep(300); gotoxy(x + 72, y + 9); printf(“〓”); gotoxy(x + 70, y + 7); printf(” “); gotoxy(x + 72, y + 8); printf(“옷”); Sleep(300); gotoxy(x + 70, y + 10); printf(“〓”); gotoxy(x + 72, y + 8); printf(” “); gotoxy(x + 70, y + 9); printf(“옷”); Sleep(300); gotoxy(x + 68, y + 11); printf(“〓”); gotoxy(x + 70, y + 9); printf(” “); gotoxy(x + 68, y + 10); printf(“옷”); Sleep(300); gotoxy(x + 68, y + 13); printf(“〓”); gotoxy(x + 68, y + 10); printf(” “); gotoxy(x + 68, y + 12); printf(“옷”); Sleep(300); gotoxy(x + 66, y + 14); printf(“〓”); gotoxy(x + 68, y + 12); printf(” “); gotoxy(x + 66, y + 13); printf(“옷”); Sleep(300);//게임 플레이 장면 예시 보여주기 getch(); return 0; } int px = 18, py = 1;//플레이어의 좌표 void player() { SetColor(GRAY); gotoxy(px, py); printf(“옷”); }//플레이어 찍어주는 함수 void erase_player() { SetColor(BLACK); gotoxy(px, py); printf(“■”); }//이동한 플레이어 지워주는 함수 void player_move() { int ch = getch(); if (0 == ch || 224 == ch)//방향키를 누르면 한번에 두개의 값이 들어오기 때문에 이 조건을 걸어주지 않으면 루프가 두번 돌게된다 ch = getch();//방향키를 받는다 switch (ch) { case LEFT: if (px >= 3 && px <= 37 && py >= 1 && py <= 34) { erase_player(); px -= 2; py++; } break;//플레이어 왼쪽으로 이동 case RIGHT: if (px >= 1 && px <= 35 && py >= 1 && py <= 34) { erase_player(); px += 2; py++; } break;//플레이어 오른쪽으로 이동 case DOWN: if (px >= 1 && px <= 37 && py >= 1 && py <= 33) { erase_player(); py += 2; } break;//플레이어 아래로 이동 default: player(); break;//아무키도 입력되지 않았을 때 } player(); }//결과적으로 플레이어를 움직이는 함수 void line() { for (int i = 1; i <= 35; ++i) { SetColor(WHITE); gotoxy(38, i); printf("│"); Sleep(10); } }//화면 칸 나누기 int score() { SetColor(WHITE); gotoxy(42, 5); printf("MY SCORE : %d", current_score); gotoxy(42, 10); printf("BEST SCORE : %d", best_score); gotoxy(42, 15); printf("COIN : %d", coin); return 0; }//현재점수와 최고기록 표시 int end_screen() { system("cls"); SetColor(WHITE); for (int i = 6; i <= 53; i += 2) { gotoxy(i, 6); printf("─"); gotoxy(i, 29); printf("─"); } gotoxy(6, 6); printf("┌"); gotoxy(54, 6); printf("┐"); for (int i = 7; i <= 28; ++i) { gotoxy(6, i); printf("│"); gotoxy(54, i); printf("│"); } gotoxy(6, 29); printf("└"); gotoxy(54, 29); printf("┘"); gotoxy(10, 10); printf("■■■■■ ■ ■ ■■■■■ ■■■■"); gotoxy(10, 11); printf("■ ■ ■ ■ ■ ■ ■"); gotoxy(10, 12); printf("■ ■ ■ ■ ■■■■■ ■■■■"); gotoxy(10, 13); printf("■ ■ ■■ ■ ■ ■"); gotoxy(10, 14); printf("■■■■■ ■ ■■■■■ ■ ■■"); if (current_score > best_score) { best_score = current_score; } gotoxy(34, 18); printf(“SCORE : %d”, current_score);//현재점수 출력 gotoxy(34, 21); printf(“BEST SCORE : %d”, best_score);//최고 점수 출력 if (current_score >= best_score) { SetColor(RED); gotoxy(36, 19); printf(“RECORD BREAKING!!!”); }//점수 갱신되었을때 출력하는 안내 메세지 if (0 == 0) { SetColor(RED); gotoxy(9, 27); printf(“ “); } return 0; } int sx = 18, sy = 4; int check_x, check_y; int stair() { int i, num; SetColor(WHITE); check_x = sx; check_y = sy; gotoxy(sx, sy); printf(“〓”);//계단 출력 num = rand() % 3;//0,1,2중 한개의 변수 받기 if (num == 0 && sx >= 3) { sx -= 2; sy++; }//왼쪽으로 계단 이동 else if (num == 1 && sx <= 35) { sx += 2; sy++; }//오른쪽으로 계단 이동 else { sy += 2; } return 0; }//땅굴 생성하는 함수 int cx, cy, check_c1 = 0, check_c2 = 0; int coin_score() { SetColor(YELLOW); int num; cx = check_x; cy = check_y - 1;//동전 갯수를 세기 위해서 계속 변하는 값인 cx와 cy의 값 대신 조건을 비교 할 변수를 선언함 num = rand() % 1000; if (num % 3 == 0) { gotoxy(cx, cy); printf("○"); check_c2 = check_c1; check_c1++;//만약 동전이 출력되면 동전갯수도 올려주어야함 } else { check_c2 = check_c1; check_c1--;//이 값을 줄여주지 않으면 계속 동전 점수가 늘어나기 때문에 줄여줌 } return 0; }//동전 출력하는 함수 int screen_reset() { if (sy == 35 || sy == 34) { for (int i = 1; i <= 35; ++i) { for (int j = 1; j <= 37; ++j) { gotoxy(j, i); printf(" "); } } gotoxy(18, 1); printf("옷"); px = 18; py = 1; sx = 18; sy = 4; } return 0; }//화면 넘어갔을 때 초기화 시키는 함수 int store() { system("mode con cols=80 lines=17");//콘솔창 초기화 시키기 int i, x = 1, y = 4; SetColor(RED); gotoxy(x + 1, y - 2); printf("Store"); SetColor(DARK_GRAY); gotoxy(x + 65, y - 2); printf("Your Coin : %d", coin); SetColor(WHITE); for (i = 1; i <= 80; i += 2) { gotoxy(x + i - 1, y); printf("─"); Sleep(10); }//현재 보유 코인과 store표시 하기 gotoxy(x + 5, y + 2); printf("You need "); SetColor(RED); printf("30"); SetColor(WHITE); printf("coins"); gotoxy(x + 7, y + 3); printf("to buy this!!"); gotoxy(x + 11, y + 6); printf("못"); gotoxy(x + 6, y + 9); printf("If you want to"); gotoxy(x + 8, y + 10); printf("buy this,"); gotoxy(x + 3, y + 11); printf("Please Press "); SetColor(RED); printf("'→' "); SetColor(WHITE); printf("key"); gotoxy(x + 31, y + 2); printf("You need "); SetColor(RED); printf("35"); SetColor(WHITE); printf("coins"); gotoxy(x + 33, y + 3); printf("to buy this!!"); gotoxy(x + 37, y + 6); printf("촛"); gotoxy(x + 31, y + 9); printf("If you want to"); gotoxy(x + 33, y + 10); printf("buy this,"); gotoxy(x + 28, y + 11); printf("Please Press "); SetColor(RED); printf("'←' "); SetColor(WHITE); printf("key"); gotoxy(x + 57, y + 2); printf("You need "); SetColor(RED); printf("50"); SetColor(WHITE); printf("coins"); gotoxy(x + 59, y + 3); printf("to buy this!!"); gotoxy(x + 63, y + 6); printf("홋"); gotoxy(x + 57, y + 9); printf("If you want to"); gotoxy(x + 59, y + 10); printf("buy this,"); gotoxy(x + 54, y + 11); printf("Please Press "); SetColor(RED); printf("'↓' "); SetColor(WHITE); printf("key"); //////////////////////////////////////캐릭터 바꿔주는 것은 아직 구현하지 못함 /*int get = getch(); if (0 == get || 224 == get)//방향키를 누르면 한번에 두개의 값이 들어오기 때문에 이 조건을 걸어주지 않으면 루프가 두번 돌게된다 get = getch();//방향키를 받는다 switch (get) { case RIGHT: skin = 1; break; case LEFT: skin = 2; break; case DOWN: skin = 3; break; } */ getch(); return 0; } int start_time = 0, end_time, gap = 0;//타이머 기능을 쓰기위해 필요한 변수 int main() { //랜덤함수 값이 다양한 값이 나오도록 함 srand(time(NULL)); setcursortype(NOCURSOR); //게임 첫 화면 main_screen(); //게임 설명 tutorial(); //게임 다시 시작하기 replay: //시스템 화면 초기화 system("cls"); //게임 화면 크기 조정 system("mode con cols=60 lines=35"); //게임 화면 만들기 line(); //점수 화면 찍기 score(); //시작 플레이어 찍기 player(); SetColor(WHITE); //시작 계단 gotoxy(18, 2); printf("〓"); //게임 플레이 화면 for (;;) { int temp = py; stair();//계단 먼저 찍기 start_time = clock(); coin_score();//동전 출력하기 player_move();//플레이어 움직이기 end_time = clock(); gap = (int)(end_time - start_time); if (gap >= 700) { goto game_over; }//일정 시간동안 키 입력하지 않으면 게임종료 if (py>temp) { current_score++; }//현재 점수 올려주기 if (px != check_x) { goto game_over; }//게임 종료하는 조건 screen_reset();//화면 초기화 if (check_c1 > check_c2) { coin++; }//동전 갯수 올리기 score(); } //게임 종료 됐을때 game_over: store(); system(“mode con cols=60 lines=35”);//콘솔창 크기 초기화 //게임 종료 end_screen(); //게임종료시 enter키로 게임을 다시 시작함 if (getch() == ENTER) { px = 18, py = 1; sx = 18, sy = 4; current_score = 0;//게임이 종료 됬으므로 전 게임의 정보를 초기화 해준다 goto replay; } //커서 숨기는 것 getch(); return 0; } 실행 파일 :
무한의 땅굴.exe
C언어 공룡게임 만들기 2
저번에 올렸던 소스코드에 시작메뉴와 충돌처리, 결과창 등을 추가하여
만들어 보았습니다.
#define _CRT_SECURE_NO_WARNINGS #define TreeHigh 19 #define DinoY 11 #define TreeDistance 80 #define CRT_SECURE_NO_WARNINGS #define CLS system(“cls”) #include
#include #include void SetConsoleView(); // 콘솔창 크기 조정하기 void gotoXY(int x, int y); // X좌표와 Y좌표 조정하기 void DinoSour(int Dinoleg); // 공룡그림 그리기 void Tree1(int TreePosition); // 첫번째 나무 모양 그리기 void Tree2(int TreePostin1); // 두번째 나무 모양 그리기 char KeyInput(); // 문자를 받는 함수 int DinolegsSwing = true; // 공룡의 다리 초깃값을 true로 놓고 함수에 대입 int main(void) { int TreeX2_Flag = 0; // 두번째 트리가 나오는 주기 설정 int DinosourHigh = DinoY; // 공룡의 높이를 11로 지정 int TreeX1 = TreeDistance; //첫번째 나무의 거리를 80으로 지정 int TreeX2 = TreeDistance; // 두번째 나무의 거리를 80으로 지정 int Jumping = false; // 처음 점프의 값을 false를 두고 시작 int Bottom = true; // 공룡이 바닥에 있어야만 점프를 뛸 수 있음 int JumpingLevel = false; // 점프의 최댓값에 다했다면 내려가기 위한 변수 int StartOrder = 0; int UsersOrder = 0; int Score = 0; int End = 0; SetConsoleView(); // 게임 메뉴 화면 if (StartOrder == 0) { printf(” ============================================================================ “); printf(” | |
“); printf(” | ==== ========== || \ || ========== |
“); printf(” | || \ | | || \ || / \ |
“); printf(” | || \ | | || \ || / \ |
“); printf(” | || | | | || \ || | | |
“); printf(” | || | | | || \ || | | |
“); printf(” | || / | | || \ || \ / |
“); printf(” | || / | | || \ || \ / |
“); printf(” | ==== ========== || \ || ========= |
“); printf(” | |
“); printf(” | ======= =========== ===== ===== ====== |
“); printf(” | / / \ | | | \ |
“); printf(” | | / \ | | | | |
“); printf(” | \ | | | | | / |
“); printf(” | ======= | | | | |====== |
“); printf(” | | \ / | | | \ |
“); printf(” | / \ / \ / | \ |
“); printf(” | / ========== \ / | \ |
“); printf(” | ======== ======== |
“); printf(” ============================================================================
“); } // 게임 선택 메뉴 printf(” 1. 플 레 이 2. 게 임 종 료
“); printf(” “); Start: scanf(“%d”, &UsersOrder); // 만약 사용자가 2를 입력했다면 게임을 종료 if (UsersOrder == 2) { printf(“게임을 종료합니다.
“); exit(1); } // 사용자가 1을 입력헀다면 게임을 시작 if (UsersOrder == 1) { printf(“로 딩 중….”); Sleep(1000); // 게임을 시작하기 전 콘솔을 잠깐 멈춤 CLS; while (true) { Score++; // 점수를 위한 변수 if (KeyInput() == ‘w’&&Bottom) //만약 w를 입력하고 공룡이 바닥에 위치한다면 점프 가능 { Bottom = false; //점프를 한다면 bottom이 거짓으로 변한다. Jumping = true; } if (Jumping) { DinosourHigh–; // 점프할때 y좌표 감소 } if (DinosourHigh == 2) //만약 공룡이 일정 높이가 된다면 내려가야함 (공룡 높이의 한계) { JumpingLevel = true; } if (JumpingLevel) { DinosourHigh = DinoY; // 점프 높이를 DinoY(11)로 초기화 } if (DinosourHigh == 11) // 만약 공룡이 원 위치로 돌아왔다면 다시 키입력을 받기 위한 변수들을 초기화 { JumpingLevel = false; Jumping = false; Bottom = true; } TreeX1 -= 2; // 1번째 나무를 움직이는 변수 if (TreeX1 <= 3) { TreeX1 = TreeDistance; // 1번째 나무의 x좌표가 3보다 작아진다면 나무의 위치 초기화 } if (TreeX1 == 40) { TreeX2_Flag += 1;; // 1번째 트리의 위치가 중간에 왔다면 2번째 트리 출력을 위한 변수 초기화 } if (TreeX2_Flag == 1) { Tree2(TreeX2); TreeX2 -= 2; } if (TreeX2 <= 3) { TreeX2 = TreeDistance; // 2번째 트리의 x좌표가 3보다 작아진다면 위치 초기화 TreeX2_Flag = 0; } if (TreeX1 == 7 || TreeX1 == 8) // 만약 1번째 트리의 x좌표가 7 또는 8이라면 (공룡 주위) { if (DinosourHigh == 11 || DinosourHigh == 10 || DinosourHigh == 9) // 공룡이 점프를 하지 않거나 조건보다 작게 점프했을때 (충돌처리) { End++; // 게임 종료를 위한 변수 증가 CLS; break; } } if (TreeX2 == 7 || TreeX2 == 8) //2번째 트리의 x좌표가 7 혹은 8이 되었을때 (공룡 주위) { if (DinosourHigh == 11 || DinosourHigh == 10 || DinosourHigh == 9) // 공룡이 점프를 하지 않거나 조건보다 작게 점프했을떄 (충돌처리) { End++; // 게임 종료를 위한 변수 증가 CLS; break; } } Tree1(TreeX1); DinoSour(DinosourHigh); Sleep(100); CLS; } } else //UsersOrder가 올바르게 입력되지 않았을 경우 { printf("올바른 숫자를 입력하세요"); goto Start; //69번째 Start: 로 이동하여 입력을 다시 받음 } if (End == 1) // 게임이 끝났을 경우 { printf(" "); printf(" ======================================================================================= "); printf(" | ========= ====== ======= ====== ========= | "); printf(" | / / / \ / | | | "); printf(" | | / / \ | | | | "); printf(" | \ / | | | / | | "); printf(" | ========= | | | | / |========= | "); printf(" | | | \ / |===== | | "); printf(" | | \ \ / |\ | | "); printf(" | / \ ====== | \ | | "); printf(" | ======= ======= ========== | "); printf(" | | "); printf(" | | "); printf(" | | "); printf(" | 당신의 점수는 ? : %d | ", Score); printf(" | | "); printf(" | | "); printf(" ======================================================================================= "); sleep(100); } } void DinoSour(int DinoHeight) // 공룡을 나타내는 함수 { gotoXY(0, DinoHeight); { printf(" $$$$$$$ "); printf(" $$ $$$$$ "); printf(" $$$$$$$$ "); printf("$ $$$ "); printf("$$ $$$$$$ "); printf("$$$ $$$$$ "); printf(" $$ $$$$$$$$$ "); printf(" $$$$$$$$$$$ "); printf(" $$$$$$$$$ "); printf(" $$$$$$$ "); if (DinolegsSwing) // 공룡 발을 움직이는 조건 { printf(" $ $$$ "); printf(" $$ "); DinolegsSwing = false; } else { printf(" $$$ $ "); printf(" $$ "); DinolegsSwing = true; } } } void SetConsoleView() { system("mode con cols=100 lines=25"); // 콘솔창을 가로 100 세로 25로 설정 system("title Google DinoSour Game - KBH"); // 콘솔창 제목을 정함 } void gotoXY(int x, int y) // 사물의 x좌표와 y좌표를 나타내는 함수 { COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); } void Tree1(int TreePosition) //첫번째 트리 { gotoXY(TreePosition, TreeHigh); printf(" * "); gotoXY(TreePosition, TreeHigh + 1); printf(" *** "); gotoXY(TreePosition, TreeHigh + 2); printf("*****"); gotoXY(TreePosition, TreeHigh + 3); printf(" * "); gotoXY(TreePosition, TreeHigh + 4); printf(" * "); } void Tree2(int TreePostin1) // 두번째 트리 { gotoXY(TreePostin1, TreeHigh); printf(" * "); gotoXY(TreePostin1, TreeHigh + 1); printf("*******"); gotoXY(TreePostin1, TreeHigh + 2); printf(" *** "); gotoXY(TreePostin1, TreeHigh + 3); printf(" *** "); gotoXY(TreePostin1, TreeHigh + 4); printf(" *** "); } char KeyInput() // 키 입력을 받는 함수 { if (kbhit() != 0) { return getch(); } } 결과는 이렇습니다. 만들때는 분명 재밌었는데 다 만들고 나니 아쉬움이 많이 남습니다. 예를 들자면 소스 코드가 비주얼 스튜디오에서는 오류가 생기지만 DEV C++에서는 잘 돌아간다던지 소스코드를 더 간단하고 다른 사람 눈에도 잘 들어오게 쓸 수는 없었는지 그런 점들이 아쉬운거 같습니다. 더 열심히 해야겠습니다. 마지막으로 공룡게임을 첨부해놓겠습니다. Dinosour_Game.exe 0.13MB
C언어로 게임 만들기 1. 기초 & 플레이어 움직이기 (1) 기초 함수들
C언어로 게임 만들기
1. 기초 & 플레이어 움직이기
(1) 기초 함수들
반갑습니다. 본격적인 첫 강의입니다.
1장에서는 윈도우 콘솔 게임을 만들 때 쓰이는 기초 함수의 구현과, 플레이어를 움직이는 방법에 대해 설명합니다.
그중 (1)은 가장 중요한 기초 함수들에 대한 내용입니다.
gotoxy() 함수
우리가 만드는 게임은 텍스트 모드에서 돌아갑니다. 플레이어를 움직이라는 명령을 내리면, 먼저 터미널 위의 커서가 이동하고 그 위에 플레이어를 출력하게 됩니다. 이때, 커서의 위치를 지정된 좌표로 옮기는 함수가 gotoxy() 함수입니다. gotoxy(x좌표값, y좌표값); 의 형태로 사용합니다.
// WINAPI 버전 void gotoxy(int x, int y) { COORD CursorPosition = {x, y}; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), CursorPosition); }
윈도우 API 함수를 사용하는 버전입니다. 위 함수는 Windows.h를 먼저 인클루드해야 사용할 수 있습니다. 본 강의는 윈도우를 기준으로 하므로, 이후에는 계속 이 버전이 등장할 예정입니다.
// ANSI escape code 버전 void gotoxy(int x, int y) { printf(“\033[%d;%df”, y, x); }
ANSI 이스케이프 코드를 사용하는 버전입니다. 맥과 리눅스의 터미널에서 사용 가능하며, 윈도우 10의 최신 빌드에서도 작동됩니다. (옛 윈도우는 ANSI 이스케이프 코드를 지원하지 않습니다.) 맥 또는 리눅스 유저라면 이 버전을 대신 사용하세요.
ANSI 이스케이프 코드는 쉽게 말해 텍스트 터미널 상에서 커서의 위치, 글자 색상, 폰트 등을 조정하는 명령어들의 표준입니다. 더 자세한 내용은 이곳과 이곳을 참고하세요.
보통 윈도우의 콘솔은 동시에 가로 80개, 세로 25개의 문자를 출력할 수 있습니다. (윈도우 10은 이보다 더 넓지만, 강의에서는 80*25로 통일할 것입니다.) 따라서 좌측 상단 끝이 (0, 0), 우측 하단 끝이 (79, 24)가 됩니다. 이 점에 유의하시고, 다음 예제 코드를 통해 gotoxy()의 사용 방법을 파악해 보세요.
#include
#include void gotoxy(int x, int y) { COORD CursorPosition = { x, y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), CursorPosition); } int main(void) { gotoxy(0, 0); printf(“(0, 0) 좌표에 출력했습니다.”); gotoxy(40, 12); printf(“(40, 12) 좌표에 출력했습니다.”); gotoxy(0, 24); printf(“가장 밑줄에 출력했습니다.”); } 실행 결과는 다음과 같습니다.
setcursortype() 함수
게임을 개발하다 보면, 콘솔 창의 깜박거리는 커서가 불편해집니다.
아래의 setcursortype() 함수를 이용하면 커서를 숨기거나, 다시 나타내거나, 큰 커서로 바꿀 수도 있지만, 이 강의에서는 숨기고 나타내는 기능만 사용합니다.
다음 코드는 setcursortype() 함수 정의와, 그 함수에 사용되는 열거형의 정의입니다.
// WINAPI 버전 typedef enum { NOCURSOR, SOLIDCURSOR, NORMALCURSOR } CURSOR_TYPE; void setcursortype(CURSOR_TYPE c) { CONSOLE_CURSOR_INFO CurInfo; switch (c) { case NOCURSOR: CurInfo.dwSize = 1; CurInfo.bVisible=FALSE; break; case SOLIDCURSOR: CurInfo.dwSize = 100; CurInfo.bVisible = TRUE; break; case NORMALCURSOR: CurInfo.dwSize = 20; CurInfo.bVisible = TRUE; break; } SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&CurInfo); }
위 코드도 gotoxy()와 마찬가지로 Windows.h를 인클루드해야 작동합니다.
아직 맥 및 리눅스 터미널에서 동작하는 만족스러운 대체재를 찾지 못했기 때문에, 안타깝지만 비 윈도우 유저들은 setcursortype()를 사용할 수 없습니다. 찾는 대로 업데이트하겠습니다. 커서가 있으면 성가시기는 하지만 큰 문제가 되지는 않기 때문에 일단 이 함수는 건너뛰세요.
다음 예제 코드로 실행 결과를 알아보세요.
#include
#include typedef enum { NOCURSOR, SOLIDCURSOR, NORMALCURSOR } CURSOR_TYPE; void setcursortype(CURSOR_TYPE c) { CONSOLE_CURSOR_INFO CurInfo; switch (c) { case NOCURSOR: CurInfo.dwSize = 1; CurInfo.bVisible = FALSE; break; case SOLIDCURSOR: CurInfo.dwSize = 100; CurInfo.bVisible = TRUE; break; case NORMALCURSOR: CurInfo.dwSize = 20; CurInfo.bVisible = TRUE; break; } SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CurInfo); } int main(void) { setcursortype(NOCURSOR); } 스크린샷은 올리지 않았습니다. 직접 실행해 보면, 커서가 사라진 것을 확인할 수 있습니다.
지금까지 게임을 만들 때에 필수적인 2개의 함수를 알아보았습니다. 오늘 설명한 함수 외에 기타 함수는 강의 도중에 소개하도록 하겠습니다.
다음 시간에는 플레이어를 움직이는 방법에 대해 알아보겠습니다.
이상으로 강의를 마칩니다. 감사합니다.
오류 신고나 문의사항은 댓글을 이용하세요.
키워드에 대한 정보 c 언어 게임 소스 코드
다음은 Bing에서 c 언어 게임 소스 코드 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 C 언어 무료 강의 (입문부터 게임 개발까지)
- 동영상
- 공유
- 카메라폰
- 동영상폰
- 무료
- 올리기
C #언어 #무료 #강의 #(입문부터 #게임 #개발까지)
YouTube에서 c 언어 게임 소스 코드 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 C 언어 무료 강의 (입문부터 게임 개발까지) | c 언어 게임 소스 코드, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.