언어/C

[코딩자율학습] 13일차 프로젝트 어항에 물주기

홍시_코딩기록 2024. 3. 20. 23:38

 

 

 

 

전체코드

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

//전역변수 선언
int level; // 레벨
int arrayFish[6]; // 어항
int* cursor; // 어항 배열에 접근해야하니까 포인터 변수 사용.

//함수 선언
void initData(); // 게임 초기화
void printfFishes(); //어항 물 높이 출력 함수
void decreaseWater(long elapsedTime); //어항의 물을 증발(감소)시키는 함수 선언
int checkFishAlive(); //모든 물고기가 죽었는지 확인 함수

int main(void) {
	long startTime = 0; // long은 int와 같이 정수를 담을 때 사용, 시간을 다룰 때 주로 long을 사용
	int num;  //사용자가 입력하는 어항 번호를 받을 변수
	long totalElapsedTime = 0; // 총 경과시간;
	long prevElapsedTime = 0; //직전에 물을 준 시간(물을 준 시간 간격) : 10초에 물을 주고 13초에 다시 물을 줬다면 그 사이 간격이 3초 
	initData();
	startTime = clock(); // c에서 제공하는 clock() 함수, 프로그램 수행 시작 시점부터 현재까지 흐른 시간을 밀리초 단위로 반환
	cursor = arrayFish; // 포인터 변수에 어항 배열의 시작 주소 넣기
	while (1) { // 어항에 물 주기 무한 반복
		printfFishes();
		printf("몇 번 어항에 물을 줄까요(1~6)");
		scanf_s("%d", &num); //어항 번호 받기
		if (num < 1 || num > 6) {
			printf("\\n\\n === 입력값이 잘못됐습니다 === \\n\\n"); // 1~6인 어항 번호만 받을 수 있으므로 아닐 경우 안내 메세지
			continue; // 어항 번호를 입력 받는 부분으로 다시 돌아가기
		}
		//총 경과시간, 초 단위로 표시
		totalElapsedTime = (clock() - startTime) / CLOCKS_PER_SEC;// 총 경과 시간, 초 단위로 표시: 밀리초 단위라서 CLOCKS_PER_SEC(나눈 값을 초단위로 보여줌)로 나눔. 
		printf("총 경과시간: %1d초\\n", totalElapsedTime); // 총 시간 결과 
		// 물을 준 시간 간격
		prevElapsedTime = totalElapsedTime - prevElapsedTime; // 물을 준 시간 간격 : 총 경과시간 - 직전에 물을 준 시간
		printf("최근 경과시간: %1d초\\n", prevElapsedTime); // 최근 경과 시간
		decreaseWater(prevElapsedTime); // 어항 물 증발(감소) 함수 호출

		//사용자가 입력한 번호의 어항에 물 주기
		if (cursor[num - 1] <= 0) {
			printf("%d번 어항의 물고기는 이미 죽었으므로 물을 주지 않습니다.\\n", num);
			//조건1: 어항 물 높이가 0어서 물고기 죽음.
			//포인터 변수 cursor로 접근하고 몇 번 어항인지는 num변수로 알 수 있음.
			// 배열은 0부터 시작하니까 num - 1을 해서 실제 배열의 인덱스가 되게 함.
		}
		else if (cursor[num - 1] + 1 <= 100) {
			printf("%d번 어항에 물을 줍니다.\\n\\n", num);
			cursor[num - 1] += 1;
			// 조건2: 물높이가 100을 넘을 때
			//조건에 해당하면 현재 물높이에 1을 더함.
		}
		if (totalElapsedTime / 20 > level - 1) {//레벨업 확인(20초마다 한번씩 수행)
			level++; //레벨업
			printf("***축하합니다. %d레벨에서 %d레벨로 올랐습니다. ***\\n\\n", level - 1, level); // 기존 레벨을 출력할 땐level - 1을 해야함.
			if (level == 5) {
				printf("***\\n\\n 축하합니다. 최고 레벨을 달성했습니다. 게임을 종료합니다.\\n\\n");
				exit(0);
				//최고레벨 확인 후 게임 종료
			}
		}
		//모든 물고기가 죽었는지 확인
		if (checkFishAlive() == 0) { //함수 호출해서 물고기가 0인지 확인
			printf("모든 물고기가 죽음 ㅠㅜㅜ");
			exit(0);
		}
		else {
			printf("물고기 아직 살아있음.1!");
		}
		prevElapsedTime = totalElapsedTime;
	}
	return 0;
}

void initData() {
	level = 1;
	for (int i = 0; i < 6; i++) {
		arrayFish[i] = 100; // 어항의 물은 가득 차있으니까 초기값 100
	}
}

void printfFishes() {
	printf("%3d번 %3d번%3d번%3d번%3d번%3d번\\n", 1, 2, 3, 4, 5, 6);
	for (int i = 0; i < 6; i++) {
		printf(" %3d", arrayFish[i]); // 어항 배열을 돌면서 6개 어항 물높이 출력, 최대 3자리까지만 출력
	}
	printf("\\n\\n");
}

void decreaseWater(long elapsedTime) { // 어항 6개에서 물을 증발시키는 동일한 작업을 수행하니 for문으로 돌리기
	for (int i = 0; i < 6; i++) {
		arrayFish[i] -= (level * 3 * (int)elapsedTime);
		// 어항 6개 물 높이는 arrayFish에 저장되어 있음. 여기서 - 증발한 물의 양을 하면 현재 어항 물높이가 됨.
		// 증발하는 물의 양은 난이도 조절을 위해 3으로 정함.
		// int형인 다른 값과 곱하기 위해 앞에 int를 붙여 정수형으로 형변환
		// ex) 1레벨에서 직전에 물을 주고 10초가 지났다면 1(level) * 3 * 10(elapsedTime) = 30만큼 물높이가 줄어들음.
		if (arrayFish[i] < 0) { 
			arrayFish[i] = 0;
			// 물 높이가 0이 되면 더이상 줄어들지 x, 그래서 값이 0보다 작으면 arrayFish[i] 값을 0으로 저장하고 다음 어항으로 넘어감.
		}
	}
}

int checkFishAlive() {
	for (int i = 0; i < 6; i++) {
		if (arrayFish[i] > 0) {
			return 1;
		}
	}
	return 0;
	// 6개어항 중 물높이가 0보다 높은 어항이 하나도 없으면 물고기는 모두 죽음. 
	// if문을 실행하지 못하고 for문이 바로 끝나므로 for 문 뒤에서 0 반환
}

 

 

서식 지정자의 형식 태그

  • printfFishes() 함수에서 서식 지정자에 넣는 숫자 3은 서식지정자에 옵션을 추가할 수 있는 형식 태그의 하나 자릿수라고 보면 되는데 3을 넣으면 3자리를 지정함.
  • 만약 출력할 값이 지정 너비보다 작으면 자릿수를 맞추기 위해 빈칸으로 채움.

형변환

  • C언어에서는 원하는 연산 결과를 얻기 위해 정수를 실수로, 실수를 정수로 바꾸는 경우가 있는데, 이를 형변환이라고 함. 즉 어떤 자료형을 다른 자료형으로 바꾸는 것.
더보기

 == 형식 == (바꿀 자료형)변수명/값

 

어항에 물주기 에서는 arrayFish[i] -= (level * 3 * (int)elapsedTime); 이 부분