C.언어 구조 배열 이 뱀 을 게 걸 스 럽 게 먹 는 작은 게임 을 실현 한다.

10305 단어 C 언어탐식 사
디자인 아이디어
뱀 은 본질 적 으로 구조 배열 이다.배열 에 좌표 x,y 의 값 을 저장 하고 하나의 순환 을 통 해 이 를 인쇄 한다.뱀의 이동 은 끊임없이 새로 고침 하고 다시 인쇄 한다.그래서 벽 에 부 딪 히 고 자신 을 물 면 배열 x,y 값 의 간단 한 비교 일 뿐이다.
2.사용 하 는 지식 포인트
구조 배열 Windows API 함수
3.구체 적 실현
먼저 정적 페이지 를 실현 하고 지도,초기 뱀 몸,음식 을 해결 합 니 다.
여기 에는 윈도 API 지식,즉 컨트롤 러 의 좌표 수정 이 필요 하 다

//        1
void Pos(int x, int y) 
{ 
 COORD pos; 
 HANDLE hOutput; 
 pos.X = x; 
 pos.Y = y; 
 hOutput = GetStdHandle(STD_OUTPUT_HANDLE); 
 SetConsoleCursorPosition(hOutput, pos); 
} 

COORD 는 윈도 API 에서 정의 하 는 구조 로 콘 솔 에 있 는 좌 표를 나타 낸다

typedef struct _COORD { 
SHORT X; // horizontal coordinate 
SHORT Y; // vertical coordinate 
} COORD;
코드 의 일곱 번 째 줄 은 화면 버퍼 의 핸들 을 얻 고 여덟 번 째 줄 은 커서 위 치 를 직접 수정 하 는 함수 입 니 다.
1.지도.
Pos()함수 가 있 으 면 상 자 를 인쇄 하 는 것 이 문제 가 되 지 않 습 니 다.만약 에 우리 가'-'를 상하 테두리 로 하고'|'을 좌우 테두리 로 한다 면 이것 은 타당 하지 않 을 것 같 지만 사실은 우 리 는 이미 구덩이 에 빠 졌 으 니 코드 와 실제 효과 도 를 직접 올 려 라.

//LONG==60
//WIDTH==30
void CreateMap() 
{ 
 int i; 
 for(i=0;i<LONG;i++)//     
 { 
 Pos(i,1); 
 printf("-"); 
 Pos(i,WIDTH-1); 
 printf("-"); 
 } 
 for(i=2;i<WIDTH-1;i++)//     
 { 
 Pos(0,i); 
 printf("|"); 
 Pos(LONG-1,i); 
 printf("|"); 
 } 
} 



문제 발 견 했 어 요?이것 은 정상 적 인 뱀 이다.근 데 왜 이상해 보 여요?테 두 리 를 모두'\#'로 바 꿔 서...

이것 은 훨씬 분명 하 다.우리 의 상하 테 두 리 는 각각 60 개의'\#'이 있 고 길이 60 너비 30 의 장방형 이 수출 된 후에 뜻밖에도 정사각형 이 되 었 다 는 것 을 알 아야 한다.
원인 은 여기에 있다.

콘 솔 에 있 는 모든 문자 의 길이 와 너비 비율(픽 셀 점)이 다 르 기 때문에 위의 그림 과 같은 알 이 아 픈 상황 이 발생 할 수 있 습 니 다.
해결 방법 도 간단 하 다.'●'■'⊙'등 특수 기 호 를 도입 해 야 한다.이 문자 들 의 특징 은 두 개의 일반 문자 의 위 치 를 차지 하 는 것 이다.
그래서 상하 테두리 에 60/2=30 개의 기호 가 있 습 니 다.정사각형 으로 유지 하려 면 좌우 도 30(28+2)개의 기호 로 설정 할 수 있 습 니 다.
코드 및 효과 도 는 다음 과 같다.

void CreateMap() 
{ 
 int i; 
 for(i=0;i<LONG;i+=2) 
 { 
 Pos(i,0); 
 printf("■"); 
 Pos(i,WIDTH-1); 
 printf("■"); 
 } 
 for(i=1;i<WIDTH-1;i++) 
 { 
 Pos(0,i); 
 printf("■"); 
 Pos(LONG-2,i); 
 printf("■"); 
 } 
} 


이렇게 보면 훨씬 편안 하지만 복잡 도 를 향상 시 켰 다.위의 테두리 의 모든 기호의 좌 표 는 각각(0,0)(2,0)(4,0).
2.뱀 한 마리 초기 화
뱀 과 음식 은 본질 적 으로 하나의 좌표 이기 때문에 우 리 는 새로운 데이터 유형 Node 를 정의 할 수 있다.모든 Node 는 두 개의 변수(x,y)를 저장 한 구조 체 이 고 Node 를 통 해 뱀 과 음식 을 정의 할 수 있다.

typedef struct node{ 
 int x; 
 int y; 
}Node; 
 
 
Node snake[60];
자,이제 snake 라 는 뱀 을 정 의 했 습 니 다.이 뱀 은 비만 의 적당 한 길이 와 너비 가 일치 하기 위해 서 우 리 는'⊙'으로 뱀의 매 절 을 대표 한다.처음에 우 리 는 뱀 을 지도 중간 에 나타 나 게 했 는데 뱀 머리 는 오른쪽 에 있 고 모두 3 개의 노드 가 있 었 다.그래서 우 리 는 모든 노드 의 좌 표를 구 해 야 한다.

 void InitializeSnake() 
{ 
 int i; 
 for(i=0;i<3;i++) 
 { 
 snake[i].x = (LONG/2-i*2);//(30,15)(28,15)(26,15) 
 snake[i].y = WIDTH/2; 
 Pos(snake[i].x,snake[i].y); 
 printf("⊙"); 
 } 
} 
이렇게 해서 우 리 는(30,15)(28,15)(26,15)세 좌표 에서 뱀 한 마 리 를 확정 했다.X 좌표 사이 에서 2 가 줄 어 든 것 은 X 축 이 두 기본 치 를 차지 하기 때문이다.

3.무 작위 음식 등장
먼저 음식의 좌 표를 저장 할 변 수 를 만 듭 니 다.
Nodefood;
그것 의 좌 표를 얻 는 것 은 사실 랜 덤 값 으로 길 고 넓 은 값 을 취하 여 구간(지도)범위 안에 있 게 하 는 것 이다.

void CreateFood() 
{ 
 int i; 
 srand((unsigned int)time(0)); 
 while(1) 
 { 
 do{ 
  food.x = rand()%(LONG-6)+2; 
 }while(food.x%2!=0); 
 food.y = rand()%(WIDTH-2)+1; 
 for(i=0;i<3+length;i++) 
  if(food.x==snake[i].x && food.y==snake[i].y) 
  { 
  i=-1; 
  break; 
  } 
 if(i>=0) 
 { 
  Pos(food.x,food.y); 
  printf("●"); 
  break; 
 } 
 } 
 //AfterEatFood(); 
} 

X 의 좌표 값 구법 은 rand()%(LONG-6)+2 이다.음식'●'도 두 글자 의 위치 이기 때문에 가능 한 수 치 는(2,y)(4,y)...(56,y)상하 가 모두 30 글자 로 넓 어 지고 0 부터 각각+2 이기 때문에 마지막 하 나 는(58,y)이다.
Rand()%(LONG)의 수치 범 위 는 0~59 이 고 x=1,x=2,x=58,x=59 는 지도 범위 이기 때문에 LONG-6(60-6=54)에 나머지 를 취해 야 한다.그러면 수치 범 위 는 0~54 이 고 2 를 더 하면 2~56 이 된다.또한 뱀의 각 절 좌표 와 이동 x 좌 표 는 모두+2 이기 때문에 음식의 x 좌 표 는 반드시 짝수 여야 한다.이것 은 도(...)while()로 해결 하고 먼저 값 을 취하 고 판단 하면 안 되면 다시 수치 를 얻 을 수 있다.
Y 의 좌 표 는 조금 간단 합 니 다.좌표 값 이 1~28 이면 됩 니 다.
또 좌 표를 구하 고 음식 이 뱀 몸 과 겹 치 는 지 판단 하고 겹 치면 다시 값 을 부여 한다.
위의 것 을 다 하면 우 리 는 기본 적 인(정적)효 과 를 얻 을 수 있다.지금 우 리 는 그것 을 움 직 이게 해 야 한다.

주:86 줄 은 콘 솔 창 이 길 고 넓 은 시스템 함 수 를 설정 합 니 다.
4.뱀 을 움 직 이게 한다
뱀 이 이동 할 때마다 발생 하 는 일 은 배열 의 값 이 바 뀌 고 모든 좌표 위치 에서 뱀 몸 을 인쇄 하 는 것 이다.
뱀 이 계속 움 직 이기 위해 서 우 리 는 순환 이 필요 하 다.   

while(1) 
{ 
 //    ,     
 //         
} 
우선,우 리 는 방향 을 정 해 야 한다.이것 은 두 개의 변수 가 필요 하 다.하 나 는 입력 값(임의의 값 일 수 있다)이 고,다른 하 나 는 방향 을 정 하 는 변수 이다.
여기 함수 하나 소개 할 게 요.

int kbhit(void); 
//            ,        0 ,    0
이것 은 비 차단 함수 입 니 다.키 를 눌 렀 을 때 0 이 아 닌 것 으로 되 돌아 갑 니 다.그러나 이 때 버튼 코드 는 키보드 버퍼 대기 열 에 있 습 니 다.따라서 키보드 에 응답 이 있 는 지 확인 한 후에 char 변 수 를 사용 하여 입력 을 버퍼 에서 조정 합 니 다.

if(kbhit()) 
 ch = getch(); 
ch 를 판단 하고 상황(뒤로 갈 수 없 음 등)에 맞 는 입력 이 라면 switch 를 실행 하여 좌 표를 바 꿉 니 다.

if(ch=='w'&&direction!='s') 
 direction = ch; 
else if(ch=='s'&&direction!='w') 
 direction = ch; 
else if(ch=='a'&&direction!='d') 
 direction = ch; 
else if(ch=='d'&&direction!='a') 
 direction = ch; 
else if(ch==' ') 
 continue; 


여기 빈 칸 을 설정 하 는 것 은 일시 정지 입 니 다.뱀 이 처음부터 이동 하도록 direction 을 d(오른쪽으로)로 설정 합 니 다. 
방향 이 확 정 된 후에 하나의 switch 문 구 를 사용 하여 좌 표를 판단 합 니 다.

switch(direction) 
{ 
 case 'w': 
 if(snake[0].x==food.x && snake[0].y-1==food.y) 
 { 
  length++; 
  score+=10; 
  snake[2+length].x = snake[2+length-1].x; 
  snake[2+length].y = snake[2+length-1].y; 
  for(i=length+3-2;i>0;i--) 
  { 
  snake[i].x = snake[i-1].x; 
  snake[i].y = snake[i-1].y; 
  } 
  CreateFood(); 
 } 
 else 
 { 
  Pos(snake[2+length].x,snake[2+length].y); 
  printf(" "); 
  for(i=length+3-1;i>0;i--) 
  { 
  snake[i].x = snake[i-1].x; 
  snake[i].y = snake[i-1].y; 
  } 
 } 
 snake[0].y -=1; 
 break; 
 case 's': 
 //。。。 
 case 'a': 
 //。。。 
 case 'd': 
 //。。。 
} 
뱀 머리의 다음 단 계 를 판단 하고 음식 을 먹 었 을 때 점수 등 전역 변 수 를 처리 한 다음 에 snake[2+length-1](음식 을 먹 은 후의 마지막 두 번 째 변수)의 값 을 snake[2+length](이때 새로 추 가 된 꼬리 부분)에 부여 합 니 다.
마지막 두 번 째 절 부터 앞의 절 좌표 값 을 뒤의 절 에 부여 하고 두 번 째 절 이 이전의 뱀 머리 좌 표를 얻 을 때 까지 한다.음식 이 먹 힌 후에 무 작위 로 음식 함수 가 나타난다.
음식 을 먹 지 못 했다 면 마지막 절 좌표 에 먼저 가서 빈 칸 을 입력 하면 없 애고 각 절 에 다시 값 을 부여 하 는 셈 이다.뱀 머리 뒤에 마디 마다 값 을 부여 한 후에 입력 값 에 따라 단독으로 뱀 머리 에 값 을 부여 합 니 다.예 를 들 어'w'를 입력 하면 위로 올 라 가기 때문에 뱀 머리 는 세로 좌표 에서 1 을 줄 입 니 다.
나머지 입력 도 마찬가지 입 니 다.snake 배열 의 각 값 을 업데이트 한 후에 하나의 함수 로 인쇄 합 니 다.
이렇게 이동 부분 이 이 루어 졌 으 니 이 제 는 작은 모듈 만 처리 하면 된다.
5.이동 후 처리.
이 부분 은 상대 적 으로 간단 하 다.즉,뱀 이 벽 에 부 딪 혔 는 지,자신 을 물 었 는 지 판단 한 다음 에 이런 상황 을 처리 하 는 것 이다.우 리 는 두 가지 함수 로 그것 을 해결 하 는 것 이다.

int ThroughWall() 
{ 
 if(snake[0].x==0 || snake[0].x==58 || 
 snake[0].y==0 || snake[0].y==29) 
 { 
  Pos(25,15); 
  printf("       "); 
  return 1; 
 } 
 Pos(0,WIDTH); 
 printf(" "); 
} 

int BiteItself() 
{ 
 int i; 
 for(i=3;i<=2+length;i++) 
 if((snake[0].x==snake[i].x) && (snake[0].y==snake[i].y)) 
 { 
  Pos(25,15); 
  printf("         "); 
  return 1; 
 } 
} 
반환 값 이 1 이면 게임 도 GG 입 니 다.

if(ThroughWall()==1) 
{ 
 Pos(25,WIDTH); 
 system("pause"); 
 exit(0); 
} 
if(BiteItself()==1) 
{ 
 Pos(25,WIDTH); 
 system("pause"); 
 exit(0); 
}
마지막 으로 Sleep()함 수 를 한 줄 더 추가 하여 리 셋 시간(매번 다시 인쇄 하 는 시간 간격)을 처리 합 니 다.speed 는 음식 을 먹 을 때마다 줄 어드 는 변수 이다.
Sleep(speed);
소스 코드 여기 있 습 니 다:구조 배열 구현_탐식 하 다.
4.정리 와 반성.
먼저 뱀의 구조 적 으로 볼 때 구조 배열 의 실현 은'효율'이라는 단 어 를 직접적 으로 무시 했다.배열 은 대량의 공간 을 차지 하고 용량 제한 이 있 으 며 좋 은 방법 이 아니다.
그 다음으로 BUG 의 문 제 는 Through Wall()함수 에서 뱀 머리 좌 표를 판단 할 때 뱀 머리 에서(x,1)위치 로 이동 할 때 게임 이 바로 끝나 고 아무런 힌트 도 없다.
그러나 이상 하 게 도 판단 후 Pos(0,WIDTH)를 넣는다.printf(" "); 이 두 줄 의 상 관 없 는 문장 후에 이 문 제 는 해결 되 었 고,나 는 이 두 줄 의 문장 에 대한 원래 의 목적 은 단지 끊임없이 반 짝 이 는 커서 를 지도 밖으로 내 보 내 려 고 했 을 뿐이다.
그리고 while()순환 에 코드 줄 이 너무 많 습 니 다.특히 switch-case 에 있 는 각종 뱀 몸의 이동(구조 배열 의 요소 좌표 값 변환)은 move()함수 로 추상 화 되 어야 합 니 다.
기타
이것 은 나의 첫 번 째 코드(snakeV 1.0)에 대한 재 구성 으로 프로그램 구조 에 큰 변화 가 있다.
재 구성 기간 에링크 구현탐식 하 다.을 연 구 했 고 구조 적 으로 안의 일부 사상 을 채택 했다.
개인 텅 빈 github:MagicXyxxx 의 github
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기