반응형
소스 코드
GameRule.cs
namespace 도형_이동
{
class GameRule
{
internal const int B_WIDTH = 30;
internal const int B_HEIGHT = 30;
internal const int BX = 12;
internal const int BY = 20;
internal const int SX = 4;
internal const int SY = 0;
}
}
BlockValue.cs
namespace 도형_이동
{
static class BlockValue
{
static public readonly int[,,,] bvals = new int[7, 4, 4, 4]
{
{
#region 벽돌1
{
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 }
}
},
#endregion 벽돌1
#region 벽돌2
{
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
}
},
#endregion 벽돌2
#region 벽돌3
{
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 1 },
{ 0, 1, 1, 1 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 1 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 0 }
}
},
#endregion 벽돌3
#region 벽돌4
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 1, 1, 1 },
{ 0, 0, 0, 1 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 1, 1, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 1, 1 },
{ 0, 0, 0, 0 }
}
},
#endregion 벽돌4
#region 벽돌5
{
{
{ 0, 0, 1, 0 },
{ 0, 0, 1, 1 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 1 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 1, 0 },
{ 0, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }
}
},
#endregion 벽돌5
#region 벽돌6
{
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 1 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 1 },
{ 0, 0, 1, 1 },
{ 0, 0, 1, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 1 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 1 },
{ 0, 0, 1, 1 },
{ 0, 0, 1, 0 }
}
},
#endregion 벽돌6
#region 벽돌7
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 1 },
{ 0, 0, 0, 1 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 1 },
{ 0, 0, 0, 1 }
}
}
#endregion 벽돌7
};
}
}
Diagram.cs
using System;
namespace 도형_이동
{
internal class Diagram
{
internal int X
{
get;
private set;
}
internal int Y
{
get;
private set;
}
internal int Turn
{
get;
private set;
}
internal int BlockNum
{
get;
private set;
}
internal Diagram()
{
Reset();
}
internal void Reset()
{
Random rand = new Random();
X = GameRule.SX;
Y = GameRule.SY;
Turn = rand.Next()%4;
BlockNum = rand.Next() % 7;
}
internal void MoveLeft()
{
X--;
}
internal void MoveRight()
{
X++;
}
internal void MoveDown()
{
Y++;
}
internal void MoveTurn()
{
Turn = (Turn + 1) % 4;
}
}
}
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];
}
}
}
CheckLines(y+3);
}
private void CheckLines(int y)
{
int yy = 0;
for(yy=0;(yy<4);yy++)
{
if(y-yy<GameRule.BY)
{
if (CheckLine(y - yy))
{
ClearLine(y - yy);
y++;
}
}
}
}
private void ClearLine(int y)
{
for (; y > 0; y--)
{
for (int xx = 0; xx < GameRule.BX; xx++)
{
board[xx, y] = board[xx, y - 1];
}
}
}
private bool CheckLine(int y)
{
for(int xx= 0; xx<GameRule.BX;xx++)
{
if(board[xx,y]==0)
{
return false;
}
}
return true;
}
internal void ClearBoard()
{
for(int xx=0;xx<GameRule.BX;xx++)
{
for(int yy=0;yy<GameRule.BY;yy++)
{
board[xx, yy] = 0;
}
}
}
}
}
Game.cs
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 bool Next()
{
now.Reset();
return gboard.MoveEnable(now.BlockNum, Turn, now.X, now.Y);
}
internal void ReStart()
{
gboard.ClearBoard();
}
}
}
Form1.cs
using System;
using System.Drawing;
using System.Windows.Forms;
namespace 도형_이동
{
public partial class Form1 : Form
{
Game game;
int bx;
int by;
int bwidth;
int bheight;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
game = Game.Singleton;
bx = GameRule.BX;
by = GameRule.BY;
bwidth = GameRule.B_WIDTH;
bheight = GameRule.B_HEIGHT;
this.SetClientSizeCore(GameRule.BX * GameRule.B_WIDTH, GameRule.BY * GameRule.B_HEIGHT);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
DoubleBuffered = true;
DrawGraduation(e.Graphics);
DrawDiagram(e.Graphics);
DrawBoard(e.Graphics);
}
private void DrawBoard(Graphics graphics)
{
for(int xx=0;xx<bx;xx++)
{
for(int yy=0; yy<by;yy++)
{
if(game[xx,yy]!=0)
{
Rectangle now_rt = new Rectangle(xx * bwidth + 2, yy * bheight + 2, bwidth - 4, bheight - 4);
graphics.DrawRectangle(Pens.Green, now_rt);
graphics.FillRectangle(Brushes.Red, now_rt);
}
}
}
}
private void DrawDiagram(Graphics graphics)
{
Pen dpen = new Pen(Color.Red, 4);
Point now = game.NowPosition;
int bn = game.BlockNum;
int tn = game.Turn;
for(int xx=0;xx<4;xx++)
{
for(int yy=0;yy<4;yy++)
{
if(BlockValue.bvals[bn,tn,xx,yy]!=0)
{
Rectangle now_rt = new Rectangle((now.X+xx) * bwidth + 2, (now.Y+yy) * bheight + 2, bwidth - 4, bheight - 4);
graphics.DrawRectangle(dpen, now_rt);
}
}
}
}
private void DrawGraduation(Graphics graphics)
{
DrawHorizons(graphics);
DrawVerticals(graphics);
}
private void DrawVerticals(Graphics graphics)
{
Point st = new Point();
Point et = new Point();
for (int cx = 0; cx < bx; cx++)
{
st.X = cx * bwidth;
st.Y = 0;
et.X = st.X;
et.Y = by * bheight;
graphics.DrawLine(Pens.Purple, st, et);
}
}
private void DrawHorizons(Graphics graphics)
{
Point st = new Point();
Point et = new Point();
for (int cy = 0; cy < by; cy++)
{
st.X = 0;
st.Y = cy * bheight;
et.X = bx * bwidth;
et.Y = cy * bheight;
graphics.DrawLine(Pens.Green, st, et);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch(e.KeyCode)
{
case Keys.Right: MoveRight(); return;
case Keys.Left: MoveLeft(); return;
case Keys.Space: MoveSSDown();return;
case Keys.Up: MoveTurn();return;
case Keys.Down: MoveDown(); return;
}
}
private void MoveSSDown()
{
while (game.MoveDown())
{
Region rg = MakeRegion(0, -1);
Invalidate(rg);
}
EndingCheck();
}
private void MoveTurn()
{
if(game.MoveTurn())
{
Region rg = MakeRegion();
Invalidate(rg);
}
}
private void MoveDown()
{
if(game.MoveDown())
{
Region rg = MakeRegion(0, -1);
Invalidate(rg);
}
else
{
EndingCheck();
}
}
private void EndingCheck()
{
if (game.Next())
{
Invalidate();
}
else
{
timer_down.Enabled = false;
if (DialogResult.Yes == MessageBox.Show("계속 하실건가요?", "계속 진행 확인 창", MessageBoxButtons.YesNo))
{
game.ReStart();
timer_down.Enabled = true;
Invalidate();
}
else
{
this.Close();
}
}
}
private void MoveLeft()
{
if (game.MoveLeft())
{
Region rg = MakeRegion(1, 0);
Invalidate(rg);
}
}
private Region MakeRegion(int cx, int cy)
{
Point now = game.NowPosition;
int bn = game.BlockNum;
int tn = game.Turn;
Region region = new Region();
for (int xx = 0; xx < 4; xx++)
{
for (int yy = 0; yy < 4; yy++)
{
if (BlockValue.bvals[bn, tn, xx, yy] != 0)
{
Rectangle rect1 = new Rectangle((now.X + xx) * bwidth + 2, (now.Y + yy) * bheight + 2, bwidth - 4, bheight - 4);
Rectangle rect2 = new Rectangle((now.X + cx+xx) * bwidth, (now.Y + cy+yy) * bheight, bwidth, bheight);
Region rg1 = new Region(rect1);
Region rg2 = new Region(rect2);
region.Union(rg1);
region.Union(rg2);
}
}
}
return region;
}
private Region MakeRegion()
{
Point now = game.NowPosition;
int bn = game.BlockNum;
int tn = game.Turn;
int oldtn = (tn + 3) % 4;
Region region = new Region();
for (int xx = 0; xx < 4; xx++)
{
for (int yy = 0; yy < 4; yy++)
{
if (BlockValue.bvals[bn, tn, xx, yy] != 0)
{
Rectangle rect1 = new Rectangle((now.X + xx) * bwidth + 2, (now.Y + yy) * bheight + 2, bwidth - 4, bheight - 4);
Region rg1 = new Region(rect1);
region.Union(rg1);
}
if (BlockValue.bvals[bn, oldtn, xx, yy] != 0)
{
Rectangle rect1 = new Rectangle((now.X + xx) * bwidth + 2, (now.Y + yy) * bheight + 2, bwidth - 4, bheight - 4);
Region rg1 = new Region(rect1);
region.Union(rg1);
}
}
}
return region;
}
private void MoveRight()
{
if (game.MoveRight())
{
Region rg = MakeRegion(-1, 0);
Invalidate(rg);
}
}
private void timer_down_Tick(object sender, EventArgs e)
{
MoveDown();
}
}
}
반응형
'프로젝트 > 테트리스 만들기' 카테고리의 다른 글
[C# 프로젝트] 테트리스 만들기 (0) | 2022.06.23 |
---|---|
[.NET C# 프로젝트] 테트리스 만들기 Part3. 도형 쌓기 (0) | 2020.04.17 |
[.NET C# 프로젝트] 테트리스 만들기 - Part 2. 벽돌 모양 정의하기, 회전 (0) | 2020.04.17 |
[.NET C# 프로젝트] 테트리스 만들기 - Part1. 도형 이동시키기 (0) | 2020.04.17 |