[C# 프로젝트] 테트리스 만들기 – Part 3. 벽돌 쌓기

프로젝트 다운로드

 안녕하세요. 언휴예요.

 이번 강의는 “테트리스 프로젝트 Part 3. 벽돌 쌓기” 입니다.

 Board 형식 정의

 벽돌을 쌓기 위해서는 Board의 상태를 기억할 형식이 필요합니다. 하나의 개체만 필요해서 단일체로 표현할게요.

    class Board
    {
        internal static Board GameBoard
        {
            get;
            private set;
        }
        static Board()
        {
            GameBoard = new Board();
        }
        Board()
        {
        }
    }

 벽돌을 쌓기 위한 배열 멤버 필드를 선언하고 배열 개체를 생성하세요.

        int[,] board = new int[GameRule.BX, GameRule.BY];

 보드의 특정 영역이 어떤 값인지 확인할 수 있게 속성을 정의합시다.

        internal int this[int x,int y]
        {
            get
            {
                return board[x, y];
            }
        }

 특정 벽돌이 이동 가능한지 판별하는 메서드를 제공합시다. 벽돌의 4X4 영역을 모두 확인하여 돌이 있는 영역에 보드 공간도 이미 있을 때는 이동 실패입니다.

        internal bool MoveEnable(int bn,int tn,int x,int y)
        {
            for(int xx=0;xx<4;xx++)
            {
                for(int yy=0;yy<4;yy++)
                {
                    if(BlockValue.bvals[bn,tn,xx,yy]!=0)
                    {
                        if(board[x+xx,y+yy]!=0)
                        {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

 이제 벽돌을 쌓는 메서드를 정의합시다. 벽돌의 4X4 공간을 하나씩 확인합니다. 만약 해당 공간의 x,y 좌표와 현재 벽돌이 보드에 있는 x,y 좌표를 적용한 값이 보드 공간 내에 있을 때 보드의 값과 벽돌의 값을 더한 값으로 보드에 저장합니다.

        internal void Store(int bn, int turn, int x, int y)
        {
            for (int xx = 0; xx < 4; xx++)
            {
                for(int yy = 0; yy<4;yy++)
                {
                    if(((x+xx)>=0)&&(x+xx<GameRule.BX)&&(y+yy>=0)&&(y+yy<GameRule.BY))
                    {

                        board[x + xx, y + yy] += BlockValue.bvals[bn, turn, xx, yy];
                    }
                }
            }
        }

 현재까지 작성한 Board.cs 소스 코드입니다.

namespace 도형_이동
{
    class Board
    {
        internal static Board GameBoard
        {
            get;
            private set;
        }
        static Board()
        {
            GameBoard = new Board();
        }
        Board()
        {
        }
        int[,] board = new int[GameRule.BX, GameRule.BY];
        internal int this[int x,int y]
        {
            get
            {
                return board[x, y];
            }
        }
        internal bool MoveEnable(int bn,int tn,int x,int y)
        {
            for(int xx=0;xx<4;xx++)
            {
                for(int yy=0;yy<4;yy++)
                {
                    if(BlockValue.bvals[bn,tn,xx,yy]!=0)
                    {
                        if(board[x+xx,y+yy]!=0)
                        {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
        internal void Store(int bn, int turn, int x, int y)
        {
            for (int xx = 0; xx < 4; xx++)
            {
                for(int yy = 0; yy<4;yy++)
                {
                    if(((x+xx)>=0)&&(x+xx<GameRule.BX)&&(y+yy>=0)&&(y+yy<GameRule.BY))
                    {

                        board[x + xx, y + yy] += BlockValue.bvals[bn, turn, xx, yy];
                    }
                }
            }
        }
    }
}

Game 형식 수정

 MoveDown 메서드에서 이동하지 못할 때 보드에 Store 메서드를 호출합니다. 

        internal bool MoveDown()
        {
            for (int xx = 0; xx < 4; xx++)
            {
                for (int yy = 0; yy < 4; yy++)
                {
                    if (BlockValue.bvals[now.BlockNum, Turn, xx, yy] != 0)
                    {
                        if ((now.Y + yy + 1) >=GameRule.BY)
                        {
                            gboard.Store(now.BlockNum, Turn, now.X, now.Y);
                            return false;
                        }
                    }
                }
            }
            if (gboard.MoveEnable(now.BlockNum, Turn, now.X, now.Y + 1))
            {
                now.MoveDown();
                return true;
            }
            gboard.Store(now.BlockNum, Turn, now.X, now.Y);
            return false;
        }

 현재까지 작성한 Game.cs 소스 코드입니다.

using System;
using System.Drawing;

namespace 도형_이동
{
    class Game
    {
        Diagram now;
        Board gboard = Board.GameBoard;
        internal Point NowPosition
        {
            get
            {
                return new Point(now.X, now.Y);
            }
        }
        internal int BlockNum
        {
            get
            {
                return now.BlockNum;
            }
        }
        internal int Turn
        {
            get
            {
                return now.Turn;
            }
        }

        internal static Game Singleton
        {
            get;
            private set;
        }
        internal int this[int x,int y]
        {
            get
            {
                return gboard[x, y];
            }
        }
        static Game()
        {
            Singleton = new Game();
        }
        Game()
        {
            now = new Diagram();
        }
        internal bool MoveLeft()
        {               
            for(int xx=0;xx<4;xx++)
            {
                for(int yy=0;yy<4;yy++)
                {
                    if(BlockValue.bvals[now.BlockNum,Turn, xx,yy]!=0)
                    {
                        if (now.X + xx <= 0)
                        {
                            return false;
                        }
                    }
                }
            }

            if (gboard.MoveEnable(now.BlockNum, Turn, now.X - 1, now.Y))
            {
                now.MoveLeft();
                return true;
            }
            return false;
        }

        internal bool MoveRight()
        {
            for (int xx = 0; xx < 4; xx++)
            {
                for (int yy = 0; yy < 4; yy++)
                {
                    if (BlockValue.bvals[now.BlockNum, Turn, xx, yy] != 0)
                    {
                        if ((now.X + xx+1) >= GameRule.BX)
                        {
                            return false;
                        }
                    }
                }
            }
            if (gboard.MoveEnable(now.BlockNum, Turn, now.X + 1, now.Y))
            {
                now.MoveRight();
                return true;
            }
            return false;
        }

        internal bool MoveDown()
        {
            for (int xx = 0; xx < 4; xx++)
            {
                for (int yy = 0; yy < 4; yy++)
                {
                    if (BlockValue.bvals[now.BlockNum, Turn, xx, yy] != 0)
                    {
                        if ((now.Y + yy + 1) >=GameRule.BY)
                        {
                            gboard.Store(now.BlockNum, Turn, now.X, now.Y);
                            return false;
                        }
                    }
                }
            }
            if (gboard.MoveEnable(now.BlockNum, Turn, now.X, now.Y + 1))
            {
                now.MoveDown();
                return true;
            }
            gboard.Store(now.BlockNum, Turn, now.X, now.Y);
            return false;
        }

        internal bool MoveTurn()
        {
            for (int xx = 0; xx < 4; xx++)
            {
                for (int yy = 0; yy < 4; yy++)
                {
                    if (BlockValue.bvals[now.BlockNum, (Turn+1)%4, xx, yy] != 0)
                    {
                        if (((now.X + xx) < 0)|| ((now.X + xx) >= GameRule.BX)||((now.Y+yy)>=GameRule.BY))
                        {
                            return false;
                        }
                    }
                }
            }
            if (gboard.MoveEnable(now.BlockNum, (Turn + 1) % 4, now.X, now.Y))
            {
                now.MoveTurn();
                return true;
            }
            return false;
        }

        internal void Next()
        {
            now.Reset();
        }
    }
}