뭐라도 쓰겠지
25.03.06 / 비트 플래그를 이용한 퀘스트 클리어 여부 확인 본문
#include <stdio.h>
// 퀘스트 나열
enum Quest {
q1 = 1,
q2 = 2,
q3 = 4,
q4 = 8,
q5 = 16,
q6 = 32,
q7 = 64,
q8 = 128
};
//현재 클리어 퀘스트
unsigned char player_quest;
// 퀘스트 클리어
void ClearQuest(int* _questNum, int _quest) {
*_questNum |= _quest;
}
// XOR 연산자를 이용한 퀘스트 포기
void ForgiveQuest(int* _questNum, int _quest) {
*_questNum ^= _quest;
}
// AND NOT 연산자를 이용한 퀘스트 포기
void ForgiveQuest(int* _questNum, int _quest) {
*_questNum &= ~_quest;
}
// 클리어한 퀘스트 출력
void PrintQuest(int _quest) {
if (_quest & q1) printf("1번 퀘스트 클리어\n");
if (_quest & q2) printf("2번 퀘스트 클리어\n");
if (_quest & q3) printf("3번 퀘스트 클리어\n");
if (_quest & q4) printf("4번 퀘스트 클리어\n");
if (_quest & q5) printf("5번 퀘스트 클리어\n");
if (_quest & q6) printf("6번 퀘스트 클리어\n");
if (_quest & q7) printf("7번 퀘스트 클리어\n");
if (_quest & q8) printf("8번 퀘스트 클리어\n");
printf("\n");
}
int main(void) {
ClearQuest(&player_quest, (q1 | q2 | q3));
PrintQuest(player_quest);
ClearQuest(&player_quest, (q4 | q5 | q6));
PrintQuest(player_quest);
ClearQuest(&player_quest, (q7 | q8));
PrintQuest(player_quest);
ForgiveQuest(&player_quest, q1);
PrintQuest(player_quest);
ForgiveQuest(&player_quest, q1);
PrintQuest(player_quest);
return 0;
}
코드를 살펴보면 퀘스트 포기가 XOR 연산자를 사용하는게 있고 AND NOT 연산자를 사용하는게 있다. 두 개의 차이에 대해 알아보자.
// XOR 연산자를 이용한 퀘스트 포기
void ForgiveQuest(int* _questNum, int _quest) {
*_questNum ^= _quest;
}
예를 들어 현재 q1, q3, q5를 완료한 상태라 가정하자. 그럼 player_quest에 저장된 값은 00010101(2)이다. 만약 여기서 퀘스트 q1, q3을 포기를 하는 경우
00010101 // q1 q3 q5 클리어
^00000101 // q1 q3 포기
=00010000 // q5만 남음
XOR 연산을 통해 00010000(2)가 되어 q5만 성공에 남아있게 된다. 그런데 만약 성공하지 않은 퀘스트를 포기하려 하면 어떻게 될까?
00010101 // q1 q3 q5 클리어
^00000010 // q2 포기
=00010111 // q1 q2 q3 q5 클리어?
이렇게 성공하지 않은 상태로 포기한 q2가 성공처리 되는 오류가 발생한다. 실제 인게임이라면 버그로 퀘스트가 깨져버린 상황이 된거다.
이번엔 AND와 NOT 연산을 통해 퀘스트를 포기해보자.
// AND NOT 연산자를 이용한 퀘스트 포기
void ForgiveQuest(int* _questNum, int _quest) {
*_questNum &= ~_quest;
}
위의 예시와 똑같이 q1, q3, q5를 완료한 상태라 가정하자. 똑같이 player_quest에 저장된 값은 00010101(2)이다. 만약 여기서 퀘스트 q1, q3을 포기하는 경우
00010101 // q1 q3 q5클리어
~00000101 // q1 q3 포기
&11111010 // 반전한 q1, q3값
00010000 // 겹치는 q5만 1로 남음
여기까진 똑같은 결과가 나온다. 그렇다면 q2를 포기하는 경우엔 어떻게 될까?
00010101 // q1 q3 q5 클리어
~00000010 // q2를 NOT 연산
&11111101 // 그 이후 player_quest와 ~q2를 AND 연산
=00010101 // q1 q3 q5 클리어로 오류 발생하지 않음!
이렇게 q2가 클리어되지 않고 정상적으로 처리된다.
물론 게임 내에서 클리어하지 않은 퀘스트를 포기 처리하지 못하게 방지하면 되지만, 애초부터 이렇게 코드를 작성하면 오류가 발생할 가능성이 없어진다.
'프로그래밍 > C' 카테고리의 다른 글
| 25.03.07 / 삼각수를 이용해 중첩 반복문 없이 피라미드 출력하기 (0) | 2025.03.07 |
|---|---|
| 25.03.07-25.03.11 / 중첩 반복문을 사용한 피라미드 (0) | 2025.03.07 |
| 25.03.06 / 비트 연산자를 이용한 2진법 출력 (0) | 2025.03.06 |
| 25.03.04 / 재귀함수를 이용한 2진법 변환기 (0) | 2025.03.04 |
| 25.03.04 / Hello World 뜯어보기 (0) | 2025.03.04 |