본문 바로가기
프로그래밍/C 언어(코딩)

C언어] 슬라이딩 퍼즐-3

by 곰나나 2023. 12. 31.

[슬라이딩 퍼즐]

툴 버전 : Visual Studio 2022

 

슬라이딩 퍼즐 퍼즐보드가 입력 받은 숫자크기 만큼 설정

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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
 
//& 퍼즐 상태를 나타내는 구조체
typedef struct
{
    //& 퍼즐 보드를 나타내는 2D 배열, 퍼즐의 행과 열의 개수, 빈 칸의 위치
    int** board;    
    int rows, cols; 
    int emptyRow, emptyCol; 
} PuzzleState;
 
//& 현재 퍼즐 상태를 출력하는 함수
void printPuzzle(const PuzzleState* state)
{
    printf("이동키 : ←:w, →:d, ↑:w, ↓:s, q:종료, r:다시, v: 다시 입력 \n\n");
    printf("현재 행: %d, 현재 열: %d\n\n", state->rows, state->cols);
    for (int i = 0; i < state->rows; ++i)
    {
        for (int j = 0; j < state->cols; ++j)
        {
            printf("\t %2d ", state->board[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}// printPuzzle
 
//& 빈 칸을 이동시키는 함수
void moveEmptyCell(PuzzleState* state, int moveRow, int moveCol)
{
    int newRow = state->emptyRow + moveRow;
    int newCol = state->emptyCol + moveCol;
 
    //& 새로운 위치가 퍼즐의 범위 내에 있는지 확인
    if (newRow >= 0 && newRow < state->rows && newCol >= 0 && newCol < state->cols)
    {
        //& 빈 칸과 인접한 칸을 교환
        state->board[state->emptyRow][state->emptyCol] = state->board[newRow][newCol];
        state->board[newRow][newCol] = 0;
        state->emptyRow = newRow;
        state->emptyCol = newCol;
    }
}// moveEmptyCell
 
//& 퍼즐을 초기화하는 함수
void initializePuzzle(PuzzleState* state)
{
    //& 임시로 숫자를 저장할 배열 할당
    int* numbers = (int*)malloc((state->rows * state->cols - 1* sizeof(int));
 
    if (numbers == NULL)
    {
        fprintf(stderr, "메모리 할당 실패.\n");
        exit(EXIT_FAILURE);
    }
 
    //& 숫자 배열을 연속된 숫자로 초기화
    for (int i = 0; i < state->rows * state->cols - 1++i)
    {
        numbers[i] = i + 1;
    }
 
    //& Fisher-Yates 알고리즘을 사용하여 숫자 배열 섞기
    for (int i = state->rows * state->cols - 2; i > 0--i)
    {
        int j = rand() % (i + 1);
        int temp = numbers[i];
        numbers[i] = numbers[j];
        numbers[j] = temp;
    }
 
    int count = 0;
    //& 퍼즐 보드를 섞인 숫자로 초기화
    for (int i = 0; i < state->rows; ++i)
    {
        for (int j = 0; j < state->cols; ++j)
        {
            if (count == state->rows * state->cols - 1)
            {
                // 빈 칸은 0으로 표시
                state->board[i][j] = 0;
                state->emptyRow = i;
                state->emptyCol = j;
            }
            else
            {
                state->board[i][j] = numbers[count++];
            }
        }
    }
 
    //& 할당한 메모리 해제
    free(numbers);
}// initializePuzzle
 
int main()
{
    //& PuzzleState 구조체의 인스턴스 생성
    PuzzleState currentState;
 
    //& 사용자에게 퍼즐의 행과 열의 개수를 입력받음
    printf("퍼즐의 행 수를 입력하세요: ");
    scanf_s("%d"&currentState.rows);
 
    printf("퍼즐의 열 수를 입력하세요: ");
    scanf_s("%d"&currentState.cols);
 
    //& 퍼즐 보드를 위한 메모리 할당
    currentState.board = (int**)malloc(currentState.rows * sizeof(int*));
    for (int i = 0; i < currentState.rows; ++i)
    {
        currentState.board[i] = (int*)malloc(currentState.cols * sizeof(int));
    }
 
    //& 난수 발생기를 현재 시간으로 초기화
    srand((unsigned int)time(NULL));
 
    //& 랜덤한 숫자 배열로 퍼즐 초기화
    initializePuzzle(&currentState);
 
    //& 메인 게임 루프
    while (1)
    {   
        //& 콘솔 화면 지우기 (Windows 용)
        system("cls"); 
 
        //& 현재 퍼즐 상태 출력
        printPuzzle(&currentState);
 
        //& 키 입력 대기
        char ch = _getch(); 
 
            //& 사용자 입력에 따라 빈 칸 이동이나 다른 동작 수행
            switch (ch)
            {
            case 'w':
                moveEmptyCell(&currentState, -10);
                break;
            case 's':
                moveEmptyCell(&currentState, 10);
                break;
            case 'a':
                moveEmptyCell(&currentState, 0-1);
                break;
            case 'd':
                moveEmptyCell(&currentState, 01);
                break;
            case 'r':
                initializePuzzle(&currentState);
                break;
            case 'v':
                // 행과 열 다시 입력 받음
                printf("퍼즐의 행 수를 입력하세요: ");
                scanf_s("%d"&currentState.rows);
 
                printf("퍼즐의 열 수를 입력하세요: ");
                scanf_s("%d"&currentState.cols);
 
                // 퍼즐 보드를 위한 메모리 다시 할당
                currentState.board = (int**)malloc(currentState.rows * sizeof(int*));
                for (int i = 0; i < currentState.rows; ++i)
                {
                    currentState.board[i] = (int*)malloc(currentState.cols * sizeof(int));
                }
 
                // 랜덤한 숫자 배열로 퍼즐 초기화
                initializePuzzle(&currentState);
                break;
            case 'q':
                printf("게임 종료\n");
                return 0;
            }
        
    }
 
    //& 할당한 메모리 해제
    for (int i = 0; i < currentState.rows; ++i)
    {
        free(currentState.board[i]);
    }
    free(currentState.board);
 
    return 0;
}// main
cs

728x90