배열탓인지 C언어 뱀게임 만들었는데 오류가 나요

조회수 2355회
// 0401_Snake.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#define up 119
#define down 115
#define right 100
#define left 97
void gotoxy(int x, int y)
{
    COORD pos = { 2 * (x+1), y+1 };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void start()
{   
    system("cls");
    system("mode con: cols=49 lines=20");
    printf("■■■  ■    ■  ■          ■    ■  ■■■■\n");
    printf("■      ■■  ■  ■■■      ■  ■    ■      \n");
    printf("■■■  ■  ■■  ■    ■    ■■      ■■■■\n");
    printf("    ■  ■    ■  ■■■■■  ■  ■    ■\n");
    printf("■■■  ■    ■  ■      ■■■    ■  ■■■■\n\n\n");
    gotoxy(4, 10);
    printf("▲Press any key to start  ▲\n");
    while (!_kbhit());
    Sleep(300);
    system("cls");
}
void drawborder()
{
    int i = 0;
    printf("□□□□□□□□□□□□□□□□□□□□□□\n");
    while (i < 15)
    {
        printf("□                                        □\n");
        i++;
    }
    printf("□□□□□□□□□□□□□□□□□□□□□□\n");
}
void move(int x[], int y[], int *key, int *length, int *tail_x, int *tail_y)
{   
    *tail_x = x[*length-1], *tail_y = y[*length-1];
    for (int i = *length-1; i > 0; i--)
    {
        x[i] = x[i - 1];
        y[i] = y[i - 1];
    }
    if (_kbhit())
    {
        *key = _getch();
        switch (*key)
        {
        case right:
            x[0] = x[1] + 1;
            break;
        case left:
            x[0] = x[1] - 1;
            break;
        case down:
            y[0] = y[1] + 1;
            break;
        case up:
            y[0] = y[1] - 1;
            break;
        }
    }
    else 
    {
        switch (*key)
        {
        case right:
            x[0] = x[1] + 1;
            break;
        case left:
            x[0] = x[1] - 1;
            break;
        case down:
            y[0] = y[1] + 1;
            break;
        case up:
            y[0] = y[1] - 1;
            break;
        }
    }
}
void body(int *x, int *y, int *length, int *xlength, int *tail_x, int *tail_y)
{
    if (*length == *xlength)
    {
        gotoxy(*tail_x, *tail_y);
        {
            printf("  ");
        }
    }
    else { *xlength = *length; }
    for (int i = *length - 1; i >= 0; i--)
    {
        gotoxy(x[i], y[i]);
        printf("■");
    }
}
void food(int *food_x, int *food_y, int *x, int *y, int tail_x, int tail_y, int *length)
{
    if (*food_x == *x&&*food_y == *y)//food와 snake가 만난다면.
    {   //원래는 없어질 칸이었던 tail_x,tail_y를 snake의 마지막 칸으로 바꿈
        x[*length] = tail_x;
        y[*length] = tail_y;
        *length = *length+1;
        while (1)
        {
            *food_x = rand() % 20, *food_y = rand() % 15;
            for (int i = *length - 1; i >= 0; i--)
            {
                if (*food_x != x[i]|| *food_y != y[i]) break;
                else continue;
            }
            break;
        }

    }
    gotoxy(*food_x, *food_y);
    printf("◎");;
}
void gameover()
{
    gotoxy(-1, 5);
    printf("    ■■■    ■      ■  ■■■■■  ■■■■\n");
    printf("  ■      ■  ■      ■  ■          ■      ■\n");
    printf("  ■      ■    ■  ■    ■■■■■  ■■■■\n");
    printf("  ■      ■    ■  ■    ■          ■  ■\n");
    printf("  ■      ■    ■  ■    ■          ■    ■\n");
    printf("    ■■■        ■      ■■■■■  ■      ■\n");
}
int main()
{
restart: //goto라벨
    start();
    srand((int)time(NULL));
    drawborder();
    int init_x = rand() % 10; int init_y = rand() % 10;
    //시작점이 맨 끝이면 곤란하니까 대충 14랑 10 정도로

    int x[10] = { init_x + 3, init_x+2, init_x+1, init_x };
    int y[10] = { init_y , init_y , init_y , init_y };
    //초기 x,y의 길이가 네 개이므로 초기 x,y를 가로로 네 개 놓음.
    int key = right;
    //일단 처음엔 오른쪽으로 진행
    int length = 4, xlength=4;
    //food와 만나면 length가 하나 길어짐.
    //xlength는 길어지기 이전의 길이니까 두개가 다르면 길이가 길어졌을 때의 코드 사용
    int tail_x = 0, tail_y = 0;
    //꼬리의 좌표. 꼬리는 한 턴 지나면 없어져야함.
    int food_x = rand()%19,  food_y = rand()%14;
    while (1)//게임진행 무한 루프
    {
        Sleep(125);
        move(x,y,&key, &length,&tail_x, &tail_y);
        food(&food_x, &food_y, x, y, tail_x, tail_y, &length);
        body(x, y, &length, &xlength, &tail_x, &tail_y);

        //머리가 몸이랑 충돌하면 게임오버
        for (int i = length - 1; i >= 1; i--)
        {
            if (x[i] == x[0] && y[i] == y[0])
            {
                while (!_kbhit())
                {
                    system("cls");
                    Sleep(150);
                    gameover();
                    Sleep(150);
                }
                int p = _getch();
                goto restart;
            }

        }

        //머리가 벽에 부딫히면 게임오버
        if (x[0] == -1 || x[0] == 20 || y[0] == -1 || y[0] == 15)
        {

            while (!_kbhit())
            {
                system("cls");
                Sleep(150);
                gameover();
                Sleep(150);
            }
            int p = _getch();
            //kbhit에 의한 문자를 버퍼에서 지움
            goto restart;
        }
    }
}

main 함수속에

int x[10] = { init_x + 3, init_x+2, init_x+1, init_x };
int y[10] = { init_y , init_y , init_y , init_y };
//초기 x,y의 길이가 네 개이므로 초기 x,y를 가로로 네 개 놓음.
int key = right;
//일단 처음엔 오른쪽으로 진행
int length = 4, xlength=4;
//food와 만나면 length가 하나 길어짐.
//xlength는 길어지기 이전의 길이니까 두개가 다르면 길이가 길어졌을 때의 코드 사용

이 부분이 문제인 것 같은데요. x[n], y[n]으로 배열을 를 설정하면 length가 n+3가 될 때 때 자꾸 이상하게 뱀이 나가요. 그래서 그냥 x[25] y[25] 이렇게 크게 설정해 놓고 마무리 지었는데 왜 그런지 궁금해요 ㅜㅜ

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • x[n] 과 같이 할당된 배열에는 x[n-1] 을 넘기면, 안되요.

    food 함수의 3번째 줄의 코드에서 인덱스가 n 을 넘길 수 있을 것 같네요.

        x[*length] = tail_x;
        y[*length] = tail_y;
    

    x[n] 을 할당했다면, x[0], x[1], x[2] ... xn-1의 메모리가 할당됩니다. length가 n 이 되는 순간부터 할당된 메모리를 벗어나 다른 영역에 값을 바꿔버립니다.

    n+3 이 될 때 뱀이 나간다는 것은 우연히도 x[n+3], y[n+3] 이 가리키는 위치의 값이 변경되면 뱀이 나가는 경우로 보이네요.

    모든 변수의 주소를 정수형으로 찍어서 확인해보세요.

    x+3, y+3, &key, &length, &tail_x, &tail_y, &food_x, &food_y 
    

    아마도 겹치는 것이 있을 겁니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 오랜만에 봬요! 정토드 2017.4.5 17:35

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)