c언어 테트리스 코드 짜기 질문이요ㅜ 주석처리부분 도와주세요ㅜ
글쓴이: rnghksgml / 작성시간: 일, 2016/10/30 - 6:38오후
c언어로 구조체와 파일입출력 사용으로 테트리스 코드 짜기인데 너무 어렵네요ㅜ c언어 천재님들 좀 도와주세요ㅠㅠ주석처리 한 부분 알려주세요..
#include<stdio.h> #include<stdlib.h> #include<windows.h> #include<conio.h> #include<time.h> #define NORMAL (1) #define VARIABLE_MAP (2) #define SCORE_BOARD (3) #define HARD (4) #define EXIT (0) #define MAP_HEIGHT (20) #define MAP_WIDTH (10) #define LEFT_EDGE (0) #define RIGHT_EDGE (9) #define BOTTOM_EDGE (19) #define BLOCK_SIZE (4) #define BLOCK_DIAG (7) #define DEFAULT_SPACE (0) #define FIXED_SPACE (1) #define LEFT_KEY (75) #define RIGHT_KEY (77) #define UP_KEY (72) #define DOWN_KEY (80) #define SPACE_KEY (' ') #define PAUSE_KEY ('p') #define UNIT_SPEED (10) #define FILE_NAME_LENGTH (100) #define LIST_LENGTH (10) #define NAME_LENGTH (10) typedef struct{ int x; int y; }Point; typedef struct{ Point point_set[BLOCK_SIZE]; int block_diag; int block_dir; Point current_position; }Block; void tRunNormalGame(); void tViewScoreBoard(); void tRunMapSelGame(); int tMakeMap(int map[][MAP_WIDTH]); char* selectMapList(); void tAddScore(char* name, int score); int tIsGameEnd (int map[][MAP_WIDTH]); void tBlockInitial (Block *block, int block_diag); void tManageBlockFlow(int map[][MAP_WIDTH], Block* new_block, Block* next_block, int speed, int score); void tMovingBlock2FixedSpace (int map[][MAP_WIDTH], Block* current_block); void tPrintView (int map[][MAP_WIDTH], Block current_block_pos, int score, int speed); int tConditionalDeletionLines (int map[][MAP_WIDTH]); void tDeleteLine (int map[][MAP_WIDTH], int height); void tCopyLine(int map[][MAP_WIDTH], int from_height, int to_height); int tIsFullLine(int map[][MAP_WIDTH], int height); int tIsFixedBlockSpace(Point check_point, int map[][MAP_WIDTH]); int tIsMovingBlockSpace(Point check_point, Block current_block_pos); void tMoveBlockByKey (int map[][MAP_WIDTH], Block* current_block, int key_input); void tSideMoveBlock (int map[][MAP_WIDTH], Block* current_block, int key_input); void tDownMoveBlock (int map[][MAP_WIDTH], Block* current_block); int tIsTouchWall (Block* current_block, int direction); void tLotateBlock (int map[][MAP_WIDTH], Block* current_block); int tIsTouchBottom (int map[][MAP_WIDTH], Block* current_block); int tIsTouchSideFixedBlock (int map[][MAP_WIDTH], Block* current_block, int direction); const Point block_set[BLOCK_DIAG][4][BLOCK_SIZE] = { { {{-1,-1},{0,-1},{1,-1},{2,-1}}, {{0,-1},{0,0},{0,1},{0,2}}, {{-1,-1},{0,-1},{1,-1},{2,-1}}, {{0,-1},{0,0},{0,1},{0,2}}, // □□□□ }, { {{0,-1},{0,0},{1,-1},{1,0}}, {{0,-1},{0,0},{1,-1},{1,0}}, {{0,-1},{0,0},{1,-1},{1,0}}, // □□ {{0,-1},{0,0},{1,-1},{1,0}}, // □□ }, { {{0,-1},{-1,0},{1,-1},{0,0}}, {{0,-1},{0,0},{1,0},{1,1}}, {{0,-1},{-1,0},{1,-1},{0,0}},// □□ {{0,-1},{0,0},{1,0},{1,1}}, // □□ }, { {{-1,-1},{0,-1},{0,0},{1,0}}, {{0,0},{0,1},{1,-1},{1,0}}, {{-1,-1},{0,-1},{0,0},{1,0}},// □□ {{0,0},{0,1},{1,-1},{1,0}}, // □□ }, { {{-1,0},{0,0},{1,0},{0,-1}}, {{1,0},{0,-1},{0,0},{0,1}}, {{-1,-1},{0,-1},{1,-1},{0,0}}, // □□□ {{-1,0},{0,-1},{0,0},{0,1}}, // □ }, { {{-1,0},{0,0},{1,0},{-1,-1}}, {{0,-1},{-1,-1},{-1,0},{-1,1}}, {{-1,-1},{0,-1},{1,-1},{1,0}}, // □□□ {{0,1},{1,-1},{1,0},{1,1}}, // □ }, { {{-1,0},{0,0},{1,0},{1,-1}}, {{1,1},{0,-1},{0,0},{0,1}}, {{-1,-1},{0,-1},{1,-1},{-1,0}}, // □□□ {{0,-1},{1,-1},{1,0},{1,1}}, // □ } }; int main (void) { int select; while(TRUE) { system("cls"); printf("--------- TETRIS ----------\n\n"); printf("---------- Menu ----------\n"); printf(" 1. Normal Mode\n 2. Map Selection Mode\n 3. Score Board\n 0. Exit\n\n Select : "); scanf("%d",&select); switch(select) { case NORMAL: tRunNormalGame(); break; case VARIABLE_MAP: tRunMapSelGame(); break; case SCORE_BOARD: tViewScoreBoard(); break; case HARD: case EXIT: printf("\n프로그램을 종료합니다.\n"); return 0; default: printf("\n잘못된 입력입니다. 다시 선택해주세요.\n"); fflush(stdin); getchar(); } } } void tPrintView (int map[][MAP_WIDTH], Block current_block_pos, int score, int speed) { int i,j; Point tmp; system("cls"); printf("\n\n"); for(i=0;i<MAP_HEIGHT;i++) { printf(" ■"); for(j=0;j<MAP_WIDTH;j++) { tmp.y=i; tmp.x=j; if(tIsMovingBlockSpace(tmp, current_block_pos)) printf("□"); else if(tIsFixedBlockSpace(tmp, map)) printf("▨"); else printf(" "); } printf("■"); switch(i){ case 0: printf(""); break; case 1: printf("\tNext Block"); break; case 2: printf(""); break; case 3: printf(""); break; case 4: printf(""); break; case 5: printf(""); break; case 6: printf(""); break; case 7: printf(""); break; case 8: printf(""); break; case 9: printf("\tKey"); break; case 10: printf("\t↑:블록방향 전환"); break; case 11: printf("\t←:좌측이동 →:우측이동"); break; case 12: printf("\t↓:아래로 한 칸 이동"); break; case 13: printf("\tspace bar:아래 끝으로 이동"); break; case 14: printf(""); break; case 15: printf(""); break; case 16: printf("\tSpeed : %d",speed); break; case 17: printf(""); break; case 18: printf("\tScore : %d",score); break; case 19: printf(""); break; } printf("\n"); } printf(" ■■■■■■■■■■■■"); } int tConditionalDeletionLines (int map[][MAP_WIDTH]) { int height; int score=0; int bonus_score=0; for(height=MAP_HEIGHT-1;height>=0;height--) { if(tIsFullLine(map, height)) { tDeleteLine(map, height); height++; score += (++bonus_score); } } return score; } void tDeleteLine (int map[][MAP_WIDTH], int height) { int i; if(height>=MAP_HEIGHT||height<0) return; for(i=height;i>0;i--) { tCopyLine(map,i-1,i); } } void tCopyLine(int map[][MAP_WIDTH], int from_height, int to_height) { int i; for(i=0;i<MAP_WIDTH;i++) { map[to_height][i]=map[from_height][i]; } } int tIsFullLine(int map[][MAP_WIDTH], int height) { return ( map[height][0] &&map[height][1] &&map[height][2] &&map[height][3] &&map[height][4] &&map[height][5] &&map[height][6] &&map[height][7] &&map[height][8] &&map[height][9] ); } int tIsFixedBlockSpace(Point check_point, int map[][MAP_WIDTH]) { return (map[check_point.y][check_point.x]==FIXED_SPACE); } int tIsMovingBlockSpace(Point check_point, Block current_block_pos) { int i; for(i=0;i<4;i++){ if(current_block_pos.point_set[i].x==check_point.x && current_block_pos.point_set[i].y==check_point.y) return 1; } return 0; } void tMoveBlockByKey (int map[][MAP_WIDTH], Block* current_block, int key_input) { switch(key_input){ case LEFT_KEY: // 적절히 함수를 활용 case RIGHT_KEY: // 적절히 함수를 활용 break; case UP_KEY: // 적절히 함수를 활용 break; case DOWN_KEY: // 적절히 함수를 활용 break; case SPACE_KEY: // 적절히 함수를 활용 break; default: break; } } void tSideMoveBlock (int map[][MAP_WIDTH], Block* current_block, int key_input) { if( key_input==LEFT_KEY && !tIsTouchWall(current_block, LEFT_KEY) && !tIsTouchSideFixedBlock(map, current_block, LEFT_KEY)) { current_block->point_set[0].x -= 1; current_block->point_set[1].x -= 1; current_block->point_set[2].x -= 1; current_block->point_set[3].x -= 1; current_block->current_position.x -= 1; } else if( key_input==RIGHT_KEY && !tIsTouchWall(current_block, RIGHT_KEY) && !tIsTouchSideFixedBlock(map, current_block, RIGHT_KEY)) { current_block->point_set[0].x += 1; current_block->point_set[1].x += 1; current_block->point_set[2].x += 1; current_block->point_set[3].x += 1; current_block->current_position.x += 1; } } void tDownMoveBlock (int map[][MAP_WIDTH], Block* current_block) { if(!tIsTouchBottom(map, current_block)) { current_block->point_set[0].y += 1; current_block->point_set[1].y += 1; current_block->point_set[2].y += 1; current_block->point_set[3].y += 1; current_block->current_position.y += 1; } } int tIsTouchWall (Block* current_block, int direction) { int i; if(direction==LEFT_KEY) { for(i=0;i<4;i++){ if(current_block->point_set[i].x<=0) { return 1; } } return 0; } else if(direction==RIGHT_KEY) { for(i=0;i<4;i++){ if(current_block->point_set[i].x>=MAP_WIDTH-1) { return 1; } } return 0; } } int tIsTouchSideFixedBlock (int map[][MAP_WIDTH], Block* current_block, int direction) { int i; if(direction==LEFT_KEY) for(i=0;i<4;i++) { if(map[current_block->point_set[i].y][current_block->point_set[i].x-1]==FIXED_SPACE) { return 1; } } else if(direction==RIGHT_KEY) for(i=0;i<4;i++) { if(map[current_block->point_set[i].y][current_block->point_set[i].x+1]==FIXED_SPACE) { return 1; } } return 0; } void tLotateBlock (int map[][MAP_WIDTH], Block* current_block) { int i; Block temp_block = *current_block; current_block->block_dir = (current_block->block_dir+1)%4; current_block->point_set[0].x = block_set[current_block->block_diag][current_block->block_dir][0].x+current_block->current_position.x; current_block->point_set[0].y = block_set[current_block->block_diag][current_block->block_dir][0].y+current_block->current_position.y; current_block->point_set[1].x = block_set[current_block->block_diag][current_block->block_dir][1].x+current_block->current_position.x; current_block->point_set[1].y = block_set[current_block->block_diag][current_block->block_dir][1].y+current_block->current_position.y; current_block->point_set[2].x = block_set[current_block->block_diag][current_block->block_dir][2].x+current_block->current_position.x; current_block->point_set[2].y = block_set[current_block->block_diag][current_block->block_dir][2].y+current_block->current_position.y; current_block->point_set[3].x = block_set[current_block->block_diag][current_block->block_dir][3].x+current_block->current_position.x; current_block->point_set[3].y = block_set[current_block->block_diag][current_block->block_dir][3].y+current_block->current_position.y; for(i=0;i<4;i++) { if(current_block->point_set[i].x<0 || current_block->point_set[i].x>=10) { *current_block = temp_block; return; } if(map[current_block->point_set[i].y][current_block->point_set[i].x]==FIXED_SPACE) { *current_block = temp_block; return; } } } int tIsTouchBottom (int map[][MAP_WIDTH], Block* current_block) { int i; for(i=0;i<4;i++) { if(map[current_block->point_set[i].y+1][current_block->point_set[i].x]==FIXED_SPACE || current_block->point_set[i].y==MAP_HEIGHT-1) { return 1; } } return 0; } void tMovingBlock2FixedSpace (int map[][MAP_WIDTH], Block* current_block) { int i; for(i=0;i<4;i++) map[current_block->point_set[i].y][current_block->point_set[i].x]=FIXED_SPACE; } void tManageBlockFlow(int map[][MAP_WIDTH], Block* new_block, Block* next_block, int speed, int score) { int i; char key_input; Block current_block = *new_block; tPrintView(map,current_block, score, speed); while(TRUE) { for(i=0;i<speed+5;i++){ Sleep(UNIT_SPEED); if(_kbhit()) { key_input=_getch(); if(key_input==-32) key_input=_getch(); // 키에 맞게 블록을 움직임 } } // UNIT_SPEED * speed 의 시간 // 블록을 한칸 내림 // while 내부에서 적당한 위치에 // 블록이 바닥에 접촉했을 때, 블록을 고정 된 영역으로 바꾸고, 함수를 종료시킬 수 있도록 해야함 // 블록의 변화에 따라 tPrintView() 함수로 출력을 다시 해야 함 } } void tBlockInitial (Block* block, int block_diag) { block->block_diag = block_diag; block->block_dir = 0; block->current_position.x = 4; block->current_position.y = 1; block->point_set[0].x = block_set[block_diag][block->block_dir][0].x+block->current_position.x; block->point_set[0].y = block_set[block_diag][block->block_dir][0].y+block->current_position.y; block->point_set[1].x = block_set[block_diag][block->block_dir][1].x+block->current_position.x; block->point_set[1].y = block_set[block_diag][block->block_dir][1].y+block->current_position.y; block->point_set[2].x = block_set[block_diag][block->block_dir][2].x+block->current_position.x; block->point_set[2].y = block_set[block_diag][block->block_dir][2].y+block->current_position.y; block->point_set[3].x = block_set[block_diag][block->block_dir][3].x+block->current_position.x; block->point_set[3].y = block_set[block_diag][block->block_dir][3].y+block->current_position.y; } int tIsGameEnd (int map[][MAP_WIDTH]) { if(map[0][3]==FIXED_SPACE || map[0][4]==FIXED_SPACE || map[0][5]==FIXED_SPACE || map[0][6]==FIXED_SPACE) return 1; else return 0; } void tRunNormalGame () { int map[MAP_HEIGHT][MAP_WIDTH]={0}; int score = 0; int speed=100; char player[NAME_LENGTH]; Block tmp1,tmp2; srand(time(NULL)); tBlockInitial(&tmp1,rand()%7); while(1){ // 다음블록을 생성하고, // 하나의 블록에 대한 흐름 관리(함수 활용) // 맵에서 완성된 가로줄 삭제 및 스코어 갱신 // (블록이 떨어지는 속도를 자유로운 조건 하에서 조절하도록 할 것) // 게임이 끝났는지 확인하고, // 플레이어의 이름을 입력받아 // 스코어와 함께 ScoreBoard.txt에 기록 // 이후 종료 } void tRunMapSelGame() { // 대다수 기능은 tRunNormalGame() 함수와 동일 // 블록을 생성하여 떨어뜨리기 전에, 맵 파일을 선택하여 읽고 파일 내용에 따라 맵을 수정 // 스코어는 기록하지 않음 } int tMakeMap (int map[][MAP_WIDTH]) { int x,y; char * file_name = selectMapList(); FILE * fp = NULL; if(!file_name) return FALSE; fp = fopen(file_name,"r"); if(fp==NULL) { printf("파일이 없습니다.\n"); fflush(stdin); getchar(); return FALSE; } while(2==fscanf(fp,"%d,%d",&y,&x)) { if(x>=0&&x<10&&y>=0&&y<20) map[y][x]=FIXED_SPACE; } return TRUE; } char* selectMapList () { int file_count=1, file_number; FILE * fp = fopen("mapList.txt","r"); char * file_name = (char*)malloc(sizeof(char)*FILE_NAME_LENGTH); if(fp==NULL) { printf("파일이 없습니다.\n"); fflush(stdin); getchar(); return 0; } printf("------- Map List -------\n"); while(fgets(file_name,FILE_NAME_LENGTH,fp)!=NULL) printf("%3d. %s",file_count++,file_name); printf("\n------------------------\n"); rewind(fp); printf("Select File-Number : "); fflush(stdin); scanf("%d",&file_number); if((file_count<file_number+1)||(file_number<1)) return 0; while((--file_number)!=0) fgets(file_name,FILE_NAME_LENGTH,fp); fgets(file_name,FILE_NAME_LENGTH,fp); file_name[strlen(file_name)-1]=0; printf("%s",file_name); fclose(fp); return file_name; } void tViewScoreBoard() { // ScoreBoard.txt 파일을 읽고, // 형식에 맞게 순차적으로 출력 } void tAddScore(char* name, int score) { int i,j,length=0; char name_list[_LENGTH][NAME_LENGTH]; int score_list[_LENGTH]; FILE * fp; // ScoreBoard.txt 파일을 읽고, // 순차적으로 배열에 저장한 뒤 // ScoreBoard.txt 파일에 재저장 // 인자로 받은 스코어가 ScoreBoard.txt에 기록된 스코어보다 높다면 // 그 자리에 인자로 받은 사용자 이름과 스코어를 기록하고, // 하나씩 미루어 저장 // 제한은 10개를 넘지 않는다. }
File attachments:
첨부 | 파일 크기 |
---|---|
테트리스 코드.txt | 15.02 KB |
Forums:
소스 코드는 <code> ~ </code> 블럭을
소스 코드는 <code> ~ </code> 블럭을 이용해서 올려 주세요. 그래야 코드가 소실 되지 않고 들여쓰기도 제대로 보입니다.
댓글 달기