Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
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
Archives
Today
Total
관리 메뉴

시작은 0부터

20. 지뢰찾기 100% - 마우스 좌 + 우 클릭 기능 구현 본문

C# 학습일지

20. 지뢰찾기 100% - 마우스 좌 + 우 클릭 기능 구현

0base 2022. 7. 26. 22:48

오늘 수업중에 지뢰찾기의 모든 기능을 완벽하게 구현한줄 알았는데 동기가 문제를 발견했다.

지뢰찾기 게임에는 세 가지의 버튼이 있다. 마우스 왼쪽 : 블록 열기, 마우스 오른쪽 : 깃발 꽂기, 마우스 왼쪽+오른쪽 : 열린 블록의 숫자와 닫힌 블록과 깃발을 비교해서 닫힌 블록보다 숫자가 크거나, 또는 숫자가 주변 8방향의 깃발수보다 작거나 같은 경우에 자동으로 열리는 것이다. 그리고 이때, 지뢰가 아닌 곳에 깃발을 꽂아두었다면 바로 게임오버가 된다.

 

동기의 코드를 보고 원리를 이해하여 0블록을 클릭시 주변 0블록이 열리는 코드를 구현하고, 다 끝났다 싶었는데 개인적으로 지뢰찾기의 핵심이라고 생각하는 마우스 좌우 동시 클릭기능을 구현해야 진정한 지뢰찾기 게임의 완성이라고 생각하여 코드를 작성했다. 잘 되는줄 알았는데 숫자보다 닫힌 블록이 많은 경우에도 열려버리는 문제가 있어서 수정했다. 그리고 테스트 결과 이상없이 잘 돌아간다.

 

        public void CheckAroundType2(int X, int Y) //좌 + 우 클릭으로 숫자 눌렀을 때
        {

            int y = Y;
            int x = X;
            int close = 0;
            int check = 0;
            for (int ay = -1; ay < 2; ay++) //8방향 오픈 개수 체크용
            {

                for (int ax = -1; ax < 2; ax++)
                {
                    int sumy = y + ay;
                    int sumx = x + ax;

                    if (sumy - 1 < -1 || sumy + 1 > bufferY || sumx - 1 < -1 || sumx + 1 > bufferX) //범위 벗어나면 패스
                    {
                        continue;
                    }
                    if (world[sumy, sumx] < 10) //미공개된 경우
                    {
                        ++close;
                    }
                    if (world[sumy, sumx] > 99) //깃발꽂힌 경우
                    {
                        ++check;
                    }
                }
            }
            // 실행 조건
            if (world[y, x] - 10 >= check) // 1. 숫자가 깃발갯수보다 크거나 같으면
            {
                if (world[y, x] - 10 >= close + check || world[y, x] - 10 == check) // 2. 닫힌구역보다 숫자가 크거나 같거나 또는 깃발개수랑 같다면
                {
                    for (int ay = -1; ay < 2; ay++)
                    {
                        if (IsBomb == true)
                        { break; }
                        for (int ax = -1; ax < 2; ax++)
                        {
                            int sumy = y + ay;
                            int sumx = x + ax;

                            if (sumy - 1 < -1 || sumy + 1 > bufferY || sumx - 1 < -1 || sumx + 1 > bufferX) //범위 벗어나면 패스
                            {
                                continue;
                            }
                            if (world[sumy, sumx] > 100 && world[sumy, sumx] != 109) //깃발 잘못 꼽으면 사망
                            {
                                IsBomb = true;
                                ShowAll();
                                break;
                            }
                            if (world[sumy, sumx] == 0)
                            {
                                world[sumy, sumx] += 10;
                                CheckAround(sumx, sumy);
                            }

                            else if (world[sumy, sumx] < 10 && world[sumy, sumx] != 9)
                            {
                                world[sumy, sumx] += 10;
                            }
                        }
                    }
                }
            }
        }

좌+우 클릭을 나타내는 버튼이 인식되면 위 함수가 호출되어 실행한다. 먼저 클릭한 블록의 공개된 숫자 주변 8방향을 체크하여 깃발의 개수와 열리지 않은 블록의 개수를 카운트한다. 이후, 조건을 넣어 조건을 충족하는 경우에만 자동으로 확장되면서 열리는 기능이 실행된다. 이때, 기존의 0블록을 클릭하여 확장했을 때와는 달리, 깃발을 잘못꼽은 위치가 있으면 바로 게임오버가 되는 것이다. 이 확장 기능이 실행되는 조건을 어떻게 주어야할지를 고민했는데 한 줄로는 생각이 안나서 이중으로 처리했다. 먼저 첫번째 조건으로 클릭한 블록 숫자가 깃발보다 크거나 같은 경우이다. 이 조건문은 주변 8방향에 깃발을 체크하지 않는 경우에도 해당될 수 있고, 깃발을 꽂았을 때도 해당될 수 있기 때문에 첫번째 조건으로 걸었다. 그 다음 깃발의 갯수가 숫자의 개수랑 같거나, 또는 닫힌 블록 갯수와 깃발의 갯수보다 숫자가 클 경우에만 열리도록 조건을 걸었다.

 

현재로서 생각나는 지뢰찾기의 모든 기능은 다 구현했다. 이제 이전 시간에 마저 해결하지 못한 레이싱게임을 마저 해결해야겠다.