안녕하세요. 언휴예요.
이번 강의는 “테트리스 프로젝트 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(); } } }