基于C#开发的俄罗斯方块

软设之后想着休息几天再继续其他课程的学习,于是花了点时间写了一个俄罗斯方块的小游戏(通过网上大神的版本)。俄罗斯方块的游戏主要有两个类组成。一个是方块类,用于创建不同形状的俄罗斯方块,并且提供在界面画方块的方法。还有一个就是游戏类,提供了键盘响应事件以及游戏的判定。

以下是代码:

  1 方块类
  2  public class Blocks
  3     {
  4         private const int blockWidth = 21;
  5         private const int blockHeight = 21;
  6         private int _width;//方块的宽,表示有多少个单元组成
  7         private int _height;//方块的高
  8         private int _left;//方块左边的位置
  9         private int _top;//右边的位置
 10         public int[,] shape;//用于存储方块,0表示无,1表示有
 11         public int Top
 12         {
 13             get { return _top; }
 14             set { _top = value; }
 15         }
 16 
 17         public int Left
 18         {
 19             get { return _left; }
 20             set { _left = value; }
 21         }
 22         public int Height
 23         {
 24             get { return _height; }
 25             set { _height = value; }
 26         }
 27         public int Width
 28         {
 29             get { return _width; }
 30             set { _width = value; }
 31         }
 32         public Blocks()
 33         {
 34             getBlocks();
 35         }
 36         /// <summary>
 37         /// 产生一种图案的俄罗斯方块
 38         /// </summary>
 39         private void getBlocks()
 40         {
 41             Random r = new Random();           
 42             int randomId= r.Next(1,9);
 43             //int randomId = 1;
 44             switch (randomId)
 45             { 
 46                 case 1://表示横条
 47                     Width = 4;
 48                     Height = 1;
 49                     Left = 3;
 50                     Top = 0;
 51                     shape = new int[Width, Height];
 52                     shape[0, 0] = 1;
 53                     shape[1, 0] = 1;
 54                     shape[2, 0] = 1;
 55                     shape[3, 0] = 1;
 56                     break;
 57                 case 2://表示方块
 58                     Width = 2;
 59                     Height = 2;
 60                     Left = 4;
 61                     Top = 0;
 62                     shape = new int[Width, Height];
 63                     shape[0, 0] = 1;
 64                     shape[0, 1] = 1;
 65                     shape[1, 0] = 1;
 66                     shape[1, 1] = 1;
 67                     break;
 68                 case 3://表示L
 69                     Width = 2;
 70                     Height = 3;
 71                     Left = 4;
 72                     Top = 0;
 73                     shape = new int[Width, Height];
 74                     shape[0, 0] = 1;
 75                     shape[1, 2] = 1;
 76                     shape[0, 1] = 1;
 77                     shape[0, 2] = 1;
 78                     break;
 79                 case 4://表示L的反向
 80                     Width = 2;
 81                     Height = 3;
 82                     Left = 4;
 83                     Top = 0;
 84                     shape = new int[Width, Height];
 85                     shape[0, 2] = 1;
 86                     shape[1, 0] = 1;
 87                     shape[1, 1] = 1;
 88                     shape[1, 2] = 1;
 89                     break;
 90                 case 5://表示z
 91                     Width = 2;
 92                     Height = 3;
 93                     Left = 4;
 94                     Top = 0;
 95                     shape = new int[Width, Height];
 96                     shape[0, 1] = 1;
 97                     shape[1, 0] = 1;
 98                     shape[1, 1] = 1;
 99                     shape[0, 2] = 1;
100                     break;
101                 case 6://表示z的反向
102                     Width = 2;
103                     Height = 3;
104                     Left = 4;
105                     Top = 0;
106                     shape = new int[Width, Height];
107                     shape[0, 0] = 1;
108                     shape[0, 1] = 1;
109                     shape[1, 1] = 1;
110                     shape[1, 2] = 1;
111                     break;
112                 case 7://表示T
113                     Width = 3;
114                     Height = 2;
115                     Left = 4;
116                     Top = 0;
117                     shape = new int[Width, Height];
118                     shape[0, 1] = 1;
119                     shape[1, 0] = 1;
120                     shape[2, 1] = 1;
121                     shape[1, 1] = 1;
122                     break;
123                 case 8:
124                     Width = 1;
125                     Height = 1;
126                     Left = 4;
127                     Top = 0;
128                     shape=new int[Width,Height];
129                     shape[0, 0] = 1;
130                     break;
131             }
132         }
133 
134         /// <summary>
135         /// 画单元方块
136         /// </summary>
137         /// <param name="g"></param>
138         public void DrawBlock(Graphics g)
139         {
140             Image backImg = Image.FromFile("image/block0.gif");
141             for (int i = 0; i < Width; i++)
142             {
143                 for (int j = 0; j < Height; j++)
144                 {
145                     if (shape[i, j] == 1)
146                     {
147                         Rectangle rectangle = new Rectangle((Left+i)*blockWidth,(Top+j)*blockHeight,blockWidth,blockHeight);
148                         g.DrawImage(backImg,rectangle);
149                     }
150                 }
151             }
152         }
153 
154     }
  1 游戏类
  2  public class Game
  3     {
  4         public const int gameWidth = 10;
  5         public const int gameHeight = 20;
  6         public const int blockWidth = 21;
  7         public const int blockHeight = 21;
  8         private Blocks currentBlock;
  9         private Blocks nextBlock;
 10         private int[,] gameMainPile=new int[gameWidth,gameHeight];
 11         public int score=0;
 12         public bool over=false;
 13         private AxWindowsMediaPlayer musicPlayer;
 14         public Game(AxWindowsMediaPlayer musicPlayer)
 15         {
 16             ClearPile();
 17             CreateNewBlock();
 18             this.musicPlayer = musicPlayer;
 19             //musicPlayer.settings.setMode("loop", true);
 20         }
 21 
 22         /// <summary>
 23         /// 初始化游戏面板
 24         /// </summary>
 25         private void ClearPile()
 26         {
 27             for (int i = 0; i < gameWidth; i++)
 28             {
 29                 for (int j = 0; j < gameHeight; j++)
 30                 {
 31                     gameMainPile[i, j] = 0;
 32                 }
 33             }
 34         }
 35 
 36         /// <summary>
 37         /// 创建一个俄罗斯方块
 38         /// </summary>
 39         private void CreateNewBlock()
 40         {
 41             if (nextBlock != null)
 42             {
 43                 currentBlock = nextBlock;
 44             }
 45             else
 46             {
 47                 currentBlock = new Blocks();
 48             }
 49             nextBlock = new Blocks();
 50         }
 51 
 52         /// <summary>
 53         /// 画游戏主界面
 54         /// </summary>
 55         /// <param name="g"></param>
 56         public void DrawPile(Graphics g)
 57         {
 58             Image backImg = Image.FromFile("image/block1.gif");
 59             for (int i = 0; i < gameWidth; i++)
 60             {
 61                 for (int j = 0; j < gameHeight; j++)
 62                 {
 63                     if (gameMainPile[i, j] == 1)
 64                     {
 65                         Rectangle rectangle = new Rectangle(i*blockWidth,j*blockHeight,blockWidth,blockHeight);
 66                         g.DrawImage(backImg,rectangle);
 67                     }
 68                 }
 69             }
 70         }
 71 
 72         /// <summary>
 73         /// 画出当前方块所在位置
 74         /// </summary>
 75         /// <param name="g"></param>
 76         public void DrawCurrentBlock(Graphics g)
 77         {
 78             if (currentBlock != null)
 79             {
 80                 currentBlock.DrawBlock(g);
 81             }
 82         }
 83 
 84         /// <summary>
 85         /// 画出下一个俄罗斯方块
 86         /// </summary>
 87         /// <param name="g"></param>
 88         public void DrawNextBlock(Graphics g)
 89         {
 90             if (nextBlock != null)
 91             {
 92                 int tempLeft = nextBlock.Left;
 93                 int tempTop = nextBlock.Top;
 94                 nextBlock.Left = (6 - nextBlock.Width) / 2;
 95                 nextBlock.Top = (6 - nextBlock.Height) / 2;
 96                 nextBlock.DrawBlock(g);
 97                 nextBlock.Left = tempLeft;
 98                 nextBlock.Top = tempTop;
 99             }
100         }
101 
102         /// <summary>
103         /// 固定当前俄罗斯方块
104         /// </summary>
105         private void FixedCurrentBlock()
106         {
107             int fx, fy;
108             for (int i = 0; i < currentBlock.Width; i++)
109             {
110                 for (int j = 0; j < currentBlock.Height; j++)
111                 {
112                     fx = currentBlock.Left + i;
113                     fy = currentBlock.Top + j;
114                     if (currentBlock.shape[i, j] == 1)
115                     {
116                         gameMainPile[fx, fy] = 1;
117                     }
118                 }
119             }
120             int n = CheckFullLines();
121             if (n > 0)
122             {
123                 musicPlayer.URL = "sounds/line.mp3";
124             }
125             else
126             {
127                 musicPlayer.URL = "sounds/hit.mp3";
128             }
129             musicPlayer.Ctlcontrols.play();
130             if (CheckOver())    
131             {
132                 over = true;
133             }
134         }
135 
136         /// <summary>
137         /// 判断俄罗斯方块是否到达底边
138         /// </summary>
139         /// <returns></returns>
140         public bool DownCheck()
141         {
142             bool hit = false;
143             currentBlock.Top++;
144             if ((currentBlock.Top + currentBlock.Height) > gameHeight)
145             {
146                 //已经触碰到了底边
147                 hit = true;
148             }
149             else
150             {
151                 //检测是否触碰到已经存在的行
152                 int fx, fy;
153                 for (int i = 0; i < currentBlock.Width; i++)
154                 {
155                     for (int j = 0; j < currentBlock.Height; j++)
156                     {
157                         fx = currentBlock.Left + i;
158                         fy = currentBlock.Top + j;
159                         if ((currentBlock.shape[i, j] == 1) && (gameMainPile[fx, fy] == 1))
160                         {
161                             hit = true;
162                         }
163                     }
164                 }
165             }
166 
167             if (hit)
168             {
169                 currentBlock.Top--;
170                 FixedCurrentBlock();
171                 CreateNewBlock();
172             }
173             return hit;
174         }
175 
176         /// <summary>
177         /// 键盘按键后响应移动俄罗斯方块
178         /// </summary>
179         /// <param name="direction"></param>
180         public void MoveBlocks(string direction)
181         {
182             bool canMove = true;
183             int fx, fy;
184             if (direction == "left")
185             { 
186                 //向左运动
187                 if (currentBlock.Left > 0)
188                 {
189                     for (int i = 0; i < currentBlock.Width; i++)
190                     {
191                         for (int j = 0; j < currentBlock.Height; j++)
192                         {
193                             fx = currentBlock.Left + i;
194                             fy = currentBlock.Top + j;
195                             if ((currentBlock.shape[i, j] == 1) && (gameMainPile[(fx - 1), fy] == 1))
196                             {
197                                 canMove = false;
198                             }
199                         }
200                     }
201                     if (canMove)
202                     {
203                         currentBlock.Left--;
204                     }
205                 }
206                 
207             }
208             else if (direction == "right")
209             { 
210                 //向右运动
211                 if ((currentBlock.Left + currentBlock.Width) < gameWidth)
212                 {
213                     for (int i = 0; i < currentBlock.Width; i++)
214                     {
215                         for (int j = 0; j < currentBlock.Height; j++)
216                         {
217                             fx = currentBlock.Left + i;
218                             fy = currentBlock.Top  + j;
219                             if (currentBlock.shape[i, j] == 1 && gameMainPile[(fx + 1), fy] == 1)
220                             {
221                                 canMove = false;
222                             }
223                         }
224                     }
225                     if (canMove)
226                     {
227                         currentBlock.Left++;
228                     }
229                 }
230                 
231             }
232             else if (direction == "up")
233             { 
234                 //旋转
235                 RotateCurrentBlock();
236             }
237         }
238 
239         private void RotateCurrentBlock() //旋转方块
240         {
241             bool canRotate = true;
242             int newWidth = 0;
243             int newHeight = 0;
244             int[,] newShape;
245             newWidth = currentBlock.Height;
246             newHeight = currentBlock.Width;
247             newShape = new int[newWidth, newHeight];
248             int x, y;
249             if (((currentBlock.Left + newWidth) <= gameWidth)
250                 && ((currentBlock.Top + newHeight) < gameHeight))
251             {
252                 for (int i = 0; i < currentBlock.Width; i++)
253                 {
254                     for (int j = 0; j < currentBlock.Height; j++)
255                     {
256                         x = ((currentBlock.Height - 1) - j);
257                         y = i;
258                         newShape[x, y] = currentBlock.shape[i, j];
259                         if (newShape[x, y] == 1 && gameMainPile[x + currentBlock.Left, y + currentBlock.Top] == 1)
260                         {
261                             canRotate = false;
262                             return; //不能旋转 
263                         }
264                     }
265                 }
266                 if (canRotate)
267                 {
268                     currentBlock.Width = newWidth;
269                     currentBlock.Height = newHeight;
270                     currentBlock.shape = newShape;
271                 }
272             }
273         }
274 
275         /// <summary>e
276         /// 检查消除的行
277         /// </summary>
278         /// <returns></returns>
279         private int CheckFullLines()
280         {
281             int numLines = 0;
282             int[] fullLines=new int[gameHeight];
283             for (int j = gameHeight-1; j > 0; j--)
284             {
285                 bool fullLine = true;
286                 for (int i = 0; i < gameWidth; i++)
287                 {
288                     if (gameMainPile[i, j] == 0)
289                     {
290                         fullLine = false;
291                         break;
292                     }
293                 }
294                 if (fullLine)
295                 {
296                     numLines++;
297                     fullLines[numLines] = j;
298                 }
299             }
300             if (numLines > 0)
301             {
302                 for (int i = 1; i <= numLines; i++)
303                 {
304                     ClearLine(fullLines[i]+i-1);
305                 }
306                 score += 5 * (numLines * (numLines + 1));
307                 
308             }
309             return numLines;
310         }
311 
312         /// <summary>
313         /// 消除行
314         /// </summary>
315         /// <param name="lineNumber"></param>
316         private void ClearLine(int lineNumber)
317         {
318             for (int j = lineNumber; j > 0; j--)
319             {
320                 for (int i = 0; i < gameWidth; i++)
321                 {
322                     gameMainPile[i, j] = gameMainPile[i, j - 1];
323                 }
324             }
325             for (int i = 0; i < gameWidth; i++)
326             {
327                 gameMainPile[i, 0] = 0;
328             }
329         }
330         public bool CheckOver()
331         {
332             if (currentBlock.Top == 0)
333             {
334                 return true;
335             }
336             else
337             {
338                 return false;
339             }
340         }
341 
342 
343 
344 
345     }
  1 public partial class frmMain : Form
  2     {
  3        
  4         Game game;
  5         public frmMain()
  6         {
  7             InitializeComponent();
  8             comboBox1.SelectedIndex = 0;
  9         }
 10 
 11         private void btnStart_Click(object sender, EventArgs e)
 12         {
 13             game = new Game(musicPlayer);
 14             pbMain.Width = Game.blockWidth * Game.gameWidth + 3;
 15             pbMain.Height = Game.blockHeight * Game.gameHeight + 3;
 16             pbMain.Invalidate();
 17             timer1.Enabled = true;
 18             btnStart.Enabled = false;
 19         }
 20 
 21         private void pbMain_Paint(object sender, PaintEventArgs e)
 22         {
 23             if (game != null)
 24             {
 25                 game.DrawPile(e.Graphics);
 26                 game.DrawCurrentBlock(e.Graphics);
 27             }
 28         }
 29 
 30         private void pbNextBlock_Paint(object sender, PaintEventArgs e)
 31         {
 32             if (game != null)
 33             {
 34                 game.DrawNextBlock(e.Graphics);
 35             }
 36         }
 37 
 38         private void timer1_Tick(object sender, EventArgs e)
 39         {
 40             if (!game.DownCheck())
 41             {
 42                 pbMain.Invalidate();
 43                 pbNextBlock.Invalidate();
 44             }
 45             lblScore.Text = game.score.ToString();
 46             if (game.score >= 1000)
 47             {
 48                 timer1.Enabled = false;
 49                 musicPlayer.URL = "sounds/level.mp3";
 50                 musicPlayer.Ctlcontrols.play();
 51                 MessageBox.Show("厉害厉害");
 52                 btnStart.Enabled = true;
 53                 btnStop.Enabled = false;
 54             }
 55             if (game.over)
 56             {
 57                 timer1.Enabled = false;
 58                 MessageBox.Show("游戏结束","提示");
 59                 btnStart.Enabled = true;
 60             }
 61         }
 62 
 63         private void frmMain_KeyDown(object sender, KeyEventArgs e)
 64         {
 65             //int key;
 66             //string direction = "left";
 67             //key = e.KeyValue;
 68             //if (key == 37)
 69             //{
 70             //    direction = "left";
 71             //}
 72             //else if (key == 38)
 73             //{
 74             //    direction = "up";
 75             //}
 76             //else if (key == 39)
 77             //{
 78             //    direction = "right";
 79             //}
 80             //else if (key == 40)
 81             //{
 82             //    direction = "down";
 83             //}
 84             //else
 85             //{
 86             //    direction = "space";
 87             //}
 88             //game.MoveBlocks(direction);
 89             //pbMain.Invalidate();
 90             //pbNextBlock.Invalidate();
 91         }
 92 
 93         protected override bool ProcessCmdKey(ref Message msg, Keys e)
 94         //重写ProcessCmdKey方法
 95         {
 96             if (btnStop.Text == "继续游戏") return true; //暂停时不响应键盘
 97             if (e == Keys.Up || e == Keys.Down || e == Keys.Space ||
 98                 e == Keys.Left || e == Keys.Right)
 99             {
100                 MyKeyPress(this, new KeyPressEventArgs((char)e));
101             }
102             return true;
103         }
104         private void MyKeyPress(object sender, KeyPressEventArgs e)
105         {
106             switch (e.KeyChar)
107             {
108                 case (char)Keys.Up:
109                     game.MoveBlocks("up");
110                     break;
111                 case (char)Keys.Down:
112                     if (!game.DownCheck())
113                         pbMain.Invalidate(); //重画游戏面板区域
114                     break;
115                 case (char)Keys.Right:
116                     game.MoveBlocks("right");
117                     break;
118                 case (char)Keys.Left:
119                     game.MoveBlocks("left");
120                     break;
121                 case (char)Keys.Space:
122                     break;
123             }
124             pbMain.Invalidate();
125             pbNextBlock.Invalidate();
126         }
127 
128         private void btnStop_Click(object sender, EventArgs e)
129         {
130             if (btnStop.Text == "暂停游戏")
131             {
132                 timer1.Enabled = false;
133                 btnStop.Text="继续游戏";
134             }
135             else if (btnStop.Text == "继续游戏")
136             {
137                 timer1.Enabled = true;
138                 btnStop.Text = "暂停游戏";
139             }
140         }
141 
142         private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
143         {
144             timer1.Interval = 550 - Convert.ToInt32(comboBox1.SelectedItem)*50;
145         }
146     }

记得以前在贴吧看到过什么玩到10000分之后就会有情书弹出来。这个可以通过一个弹窗来实现。不过,对于一个分手1年多的人我就不写了。

提供可执行文件,可以自己加工后去表白:

http://pan.baidu.com/s/1c29liVY

原文地址:https://www.cnblogs.com/pushudepu/p/6064656.html