https://jubrodev.tistory.com/6
저번시간에 사실상 게임의 모든 구조는 다 완성했다.
이제 부가적으로 조금 더 욕심을 내자면,
점수 기능을 추가해서 랭킹시스템을 만들 것이다.
점수 시스템 구성
점수는 간단하게 main함수 안에 count++을 해줘서 올려주고
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//게임 UI
void ShowOption() {
int score_num = score;
DrawSprite(1, 39, 7, 1, "총알 : ");
for (int i = 0; i <= 10; i++) {
if (b_index - 1 >= i)
EditMap(10 + i, 39, 'X');
else
EditMap(10 + i, 39, 'O');
}
DrawSprite(60, 37, 18, 1, "조작 : ↑,↓,←,→");
DrawSprite(60, 38, 12, 1, "공격 : Space");
DrawSprite(60, 39, 13, 1, "재장전 : Ctrl");
//아래는 점수 UI DrawSprite(30, 1, 8, 1, "SCORE : ");
for (int j = 0; j <= 10; j++) {
char str = score_num % 10 + 48; //일의자리 숫자부터 아스키코드값으로 가져옴
EditMap(48 - j, 1, str);
score_num = score_num / 10;
}
}
|
cs |
저번 UI를 생성하는 함수 안에 점수를 표시하는 UI도 추가해준다.
긴 자릿수를 일의자리부터 출력하는건 다들 알거라 생각하고(for문 참고)
입력을 한다면 다음과 같이 된다.
점수가 제대로 잘 오르는 것을 볼 수 있다!
게임오버시 점수 입력 및 랭킹 시스템
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//랭크작성
void rank_input() {
char player_name[50];
printf("게임오버! 이름을 입력해주세요(10자이내): ");
scanf("%s", player_name);
// 메모장 열기
FILE* file = fopen("Rank_List.txt", "a");
if (file == NULL) {
printf("Error opening file!");
return;
}
// 입력받은 이름과 게임 점수 입력하기
fprintf(file, "Player Name: %s\t", player_name);
fprintf(file, "Score : %d\n", score);
fclose(file);
}
|
cs |
일단 게임이 오버된다면, 이름을 따로 입력받아 입력받은 이름과 그 판의 점수를 메모장에 적어놓았다.
일단 입력받는건 문제없이 잘 되는걸 확인했다.
메모장 생성에 입력까지 성공!
이제 이걸 배열화 시키고 내림차순 정렬을 해서 랭킹을 완성시켜야겠다.
파일 입출력 관련 함수들
- fopen(): 파일을 여는 데 사용되며 후속 파일 작업에 사용할 수 있는 파일 포인터를 반환합니다. 파일 이름과 파일을 여는 모드(예: 읽기 모드의 경우 "r", 쓰기 모드의 경우 "w", 추가 모드의 경우 "a")의 두 가지 인수를 사용합니다.
예: FILE* file = fopen("myfile.txt", "r"); - fclose(): 이 함수는 fopen()을 사용하여 열린 파일을 닫는 데 사용됩니다. 파일 포인터를 인수로 사용합니다.
예: fclose(file); - fprintf(): 포맷된 데이터를 파일에 쓰는 데 사용됩니다. printf()와 유사하게 작동하지만 콘솔에 인쇄하는 대신 지정된 파일에 데이터를 씁니다.
예: fprintf(file, "Hello, World!"); - fscanf(): 파일에서 포맷된 데이터를 읽는 데 사용됩니다. scanf()와 유사하게 작동하지만 콘솔에서 읽는 대신 지정된 파일에서 데이터를 읽습니다.
예: fscanf(file, "%d", &num); - fgetc(): 이 함수는 파일에서 단일 문자를 읽는 데 사용됩니다. 더 이상 읽을 문자가 없으면 int 또는 EOF(파일 끝)로 읽은 문자를 반환합니다.
예: int ch = fgetc(file); - fputc(): 이 함수는 파일에 단일 문자를 쓰는 데 사용됩니다. 문자와 파일 포인터를 인수로 사용합니다.
예: fputc('A', file); - fgets(): 이 함수는 파일에서 한 줄의 텍스트를 읽는 데 사용됩니다. 개행 문자 또는 파일의 끝이 나타날 때까지 문자를 읽습니다.
예: char buffer[100]; fgets(buffer, sizeof(buffer), file); - fputs(): 이 함수는 파일에 문자열을 쓰는 데 사용됩니다. 문자열과 파일 포인터를 인수로 사용합니다.
예: fputs("Hello, World!", file); - feof(): 이 함수는 파일의 끝에 도달했는지 확인하는 데 사용됩니다. 파일 끝에 도달하면 0이 아닌 값을 반환하고 그렇지 않으면 0을 반환합니다.
예: if (feof(file)) { /* end of file reached */ }
파일관리모드
r | 읽기모드. 반드시 파일이 존재해야함. |
w | 쓰기모드. 파일이 없으면 만들고 있을시 기존내용 모두 삭제후 쓰기. |
a | 추가모드. 파일이 없으면 만들고 있을시 기존내용 끝에 내용 추가. |
rb | 바이너리형식 읽기모드. (바이너리는 이진데이터이다!) |
wb | 바이너리형식 쓰기모드. |
ab | 바이너리형식 추가모드. |
랭킹 내림차순 정렬
링크드 리스트로 내림차순 정렬을 했는데 이 블로그를 많이 참고하였다.
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
|
//랭크작성
void rank_input(void) {
char player_name[50];
printf("게임오버! 이름을 입력해주세요(10자이내): ");
scanf("%s", player_name);
// 메모장 열기
FILE* file = fopen("Rank_List.txt", "a");
if (file == NULL) {
printf("Error opening file!");
return;
}
// 입력받은 이름과 게임 점수 입력하기
fprintf(file, "%s\t", player_name);
fprintf(file, "%d\n", score);
fclose(file);
}
//랭크 보여주는 장면(콘솔)
void RankingShow(void) {
system("mode con: cols=50 lines=30");
system("title 랭킹 확인");
FILE* fp = fopen("Rank_List.txt", "rt");
if (fp == NULL) {
MessageBox(NULL, TEXT("The file does not exist."), NULL, NULL);
return;
}
LINKEDLIST* lnk = (LINKEDLIST*)malloc(sizeof(LINKEDLIST));
lnk->cur = NULL;
lnk->head = NULL;
lnk->tail = NULL;
char tempName[50];
int tempScore;
while (fscanf(fp, "%s %d", tempName, &tempScore) == 2) {
insertData(lnk, tempName, tempScore);
}
fclose(fp);
printScore(lnk);
while (lnk->head != NULL) {
deleteLastNode(lnk);
}
Sleep(1000);
return;
}
//콘솔에 내림차순으로 print하기
void printScore(LINKEDLIST* lnk) {
int cnt = 0;
RNKINFO* cur;
cur = lnk->head;
while (cur != NULL) {
cnt++;
cur = cur->next;
}
RNKINFO** ptr = (RNKINFO**)malloc(sizeof(RNKINFO*) * cnt);
int i, j;
RNKINFO* temp;
for (i = 0, cur = lnk->head; i < cnt; i++) {
ptr[i] = cur;
if (cur == NULL)
break;
cur = cur->next;
}
for (i = 0; i < cnt - 1; i++) {
for (j = i + 1; j < cnt; j++) {
if (ptr[i]->score <= ptr[j]->score) {
temp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = temp;
}
}
}
for (i = 0; i < cnt; i++) {
printf("%d. Name: %s \t\t Score: %d\n", i + 1, ptr[i]->name, ptr[i]->score);
}
free(ptr);
}
//메모장 데이터를 노드에 입력하기
void insertData(LINKEDLIST* lnk, char* name, int score) {
RNKINFO* newRNK = (RNKINFO*)malloc(sizeof(RNKINFO));
newRNK->name = (char*)malloc(sizeof(char) * (strlen(name) + 1));
strcpy(newRNK->name, name);
newRNK->score = score;
newRNK->next = NULL;
if (lnk->head == NULL && lnk->tail == NULL) {
lnk->head = lnk->tail = newRNK;
}
else {
lnk->tail->next = newRNK;
lnk->tail = newRNK;
}
return;
}
// 마지막 노드 지우기
void deleteLastNode(LINKEDLIST* lnk) {
if (lnk->head == NULL) {
return; // No nodes to delete
}
else if (lnk->head == lnk->tail) {
// Only one node in the list
free(lnk->head->name);
free(lnk->head);
lnk->head = lnk->tail = NULL;
}
else {
RNKINFO* cur = lnk->head;
while (cur->next != lnk->tail) {
cur = cur->next;
}
cur->next = NULL;
free(lnk->tail->name);
free(lnk->tail);
lnk->tail = cur;
}
return;
}
|
cs |
링크드 리스트 더 공부해야겠다....
하여튼 위의 코드를 통해 게임이 끝나면 메모장에 다음과 같이 적혀지고,
또 이 메모장을 읽어 게임오버 화면에서 랭킹을 들어가면 다음과 같이 링킹 순서대로 보여준다.
이제 진짜 끝~~
다음시간엔 전체 코드 및 구현 동영상으로 마무리 정리하겠다.
Reference