-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();
}