-2048 게임이란?


http://gabrielecirulli.github.io/2048/

백번 말하는것 보다 한번 해보는것이 훨 났다.


-콘솔창으로 2048 구현하기








-구현방법 (소스)


 구현할 때 가장 고민한 것이 방향키를 눌러서 같은 수 들을 합쳐줄 때, 방향이 총 4가지가 있는데 어떻게 이것을 처리할 것인가 고민을 하다가 배열을 가상으로 돌리는 방법을 사용해서 해결했다. 

 배열을 해당하는 방향으로 돌렸을 때 열과 행 그리고 방향을 인자로 주면 해당하는 배열에 해당하는 주소를 반환하는 합수를 만들었다.





#include stdio.h
#include time.h
#include conio.h
#include windows.h
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
 
void gotoxy(int x, int y);
void game_start(int map[][17]);
void game_print(int map[][17]);
void number_print(int arr[][4], int score);
void create(int arr[][4]);
int create_check(int arr[][4]);
int dmove(int arr[][4], int d, int *score);
int *arr_tc(int arr[][4],int i,int j,int d);
void game_over(int *score);
 
void main() {
	gotoxy(10, 5); printf("2048 시작하기");
	gotoxy(12, 6); printf("PRESS ANY KEY"); getch();
	int map[17][17];
	game_start(map);//map초기화
	while (true) {//게임 종료시 다시 시작
		int score = 100, input;
		int arr[4][4] = { 0, 2, 2 ,};
		system("cls");//map을 새로그림
		game_print(map);//map을 draw함
		while (true) {//조작
			if (kbhit()) {
				if (getch() == 224) {//특수키
					switch (getch()) {//방향키를 입력받음
					case LEFT:  input = 1; break;
					case UP:    input = 2; break;
					case RIGHT: input = 3; break;
					case DOWN:  input = 4; break;
					}
//더이상 움직일 수없고 배열이 꽉참 -> 게임 오버 -> 게임 재시작
					if (dmove(arr, input, &score)) break;
				}
				number_print(arr, score);//프린트 갱신
			}
		}
	}
}
 
 
 //프린트할 위치
void gotoxy(int x, int y) {
	COORD Pos = { x * 2, y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}
 
//맵을 초기화함
void game_start(int map[][17]) {
	int arr_temp[17][17] = {
		{ 11, 1, 1, 1, 22, 1, 1, 1, 22, 1, 1, 1, 22, 1, 1, 1, 12 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 21, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 23 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 21, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 23 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 21, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 23 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2, 5, 4, 4, 2 },
		{ 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
		{ 14, 1, 1, 1, 24, 1, 1, 1, 24, 1, 1, 1, 24, 1, 1, 1, 13 }
	};
	int i, j;
	for (i = 0; i < 17; i++)
	for (j = 0; j < 17; j++)
		map[i][j] = arr_temp[i][j];
}
 
//맵을 프린트함
void game_print(int map[][17]){
	int i = 0, j = 0;
	printf("\n    score : %d\n\n", 100);
	for (int i = 0; i < 17; i++){
		printf("      ");
		for (int j = 0; j < 17; j++){
			switch (map[i][j]) {
			case 0: printf("  "); break;
			case 1: printf("─"); break;
			case 2: printf("│"); break;
			case 3: printf("┼"); break;
			case 5: printf("      ");break;
			case 11: printf("┌"); break;
			case 12: printf("┐"); break;
			case 13: printf("┘"); break;
			case 14: printf("└"); break;
			case 21: printf("├"); break;
			case 22: printf("┬"); break;
			case 23: printf("┤"); break;
			case 24: printf("┴"); break;
			}
		}
		printf("\n");
	}
}
 
//숫자를 프린트함
 void number_print(int arr[][4], int score){
	 int i,j;
	 gotoxy(6, 1);
	 printf("%d", score);
 
	 for(i=0;i<4;i++){
		 for(j=0;j<4;j++){
			gotoxy(4+j*4, 6+i*4);
			if (arr[i][j] != 0) {
				printf("%5d ", arr[i][j]);
			}
			else {
			printf("      ");
			}
		 }
	 }
 }
 
//새로운 숫자 생성
void create(int arr[][4]) {
	int locate, number;
	srand(unsigned(time(NULL)));//rand함수 랜덤설정
	if (rand() % 10 < 8) number = 2;//80퍼로 2생성
	else number = 4;// 20퍼로 4생성
	do{
		locate = rand() % 16;
	} while (arr[locate / 4][locate % 4] != 0);//빈칸나올때까직 랜덤
	arr[locate / 4][locate % 4] = number;
}
 
//create가 가능한지 체크
int create_check(int arr[][4]) {
	int i, cnt = 0;
	for (i = 0; i < 16; i++) {
		if (arr[i / 4][i % 4] != 0)
			cnt++;
	}
	if (cnt == 16) return 0;//배열이 꽉참 -> create불가
	else return 1;//creeate가능
}
 
//방향키이동
int dmove(int arr[][4], int d, int *score){
	int i,j, s, check = 0;
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			if (*arr_tc(arr, i, j, d) != 0) {
				for (s = j + 1; s < 4; s++) {//뒤와 합치기
					if (*arr_tc(arr, i, j, d) == *arr_tc(arr, i, s, d)) {
						*arr_tc(arr, i, j, d) *= 2;//
						*arr_tc(arr, i, s, d) = 0;
						*score += *arr_tc(arr, i, j, d);//점수 추가
						check++;
						break; 
					}
					else if (*arr_tc(arr, i, s, d) != 0) break;//뒤에 합치지 못하면 종료
				}
 
 
				for (s = j - 1; s >= 0; s--) {//앞에 이동할수 있나 체크
					if (*arr_tc(arr, i, s, d) != 0) {
						break;
					}
				}
				s++;
				if (j != s) {//앞에 이동할수 있으면 정렬
					*arr_tc(arr, i, s, d) = *arr_tc(arr, i, j, d);
					*arr_tc(arr, i, j, d) = 0;
					check++;
				}
			}
 
		}
	}
	// check == 0 -> 더 이상 움직일 수 없음 -> create 안함
	if (create_check(arr)) {
		if (check != 0) {
			create(arr);
		}
	}
	else//더이상 create 불가 시
	{
		game_over(score); 
		return 1;//다시시작
	}
	return 0;
}
 
//배열을 돌림 -> 방향키가 달라도 같은 코드로 조작 가능
int *arr_tc(int arr[][4], int i, int j, int d){
	int ti, tj;
	switch (d) {
	case 1: ti = i; tj = j;   break;
	case 2: ti = j; tj = 3 - i; break;
	case 3: ti = i; tj = 3 - j; break;
	case 4: ti = 3 - j; tj = 3 - i; break;
	}
	return &arr[ti][tj];
}
 
//게임 오버
void game_over(int *score) {
	system("cls");
	gotoxy(10, 5); printf("Game Over");
	gotoxy(10, 6); printf("Score : %d", *score);
	gotoxy(12, 7); printf("PRESS ANY KEY");
	getch();
	getch();
}



WRITTEN BY
Who1sth1s

,