• 基于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

  • 相关阅读:
    vue比较模板来跟新数据
    iframe自适应高度
    springmvc接口ios网络请求
    spring mvc实现接口参数统一更改
    spring mvc实现自定义注解
    基于redis集群实现的分布式锁,可用于秒杀,定时器。
    java使用javax.mail进行免费的邮件发送
    前端图片压缩上传(纯js的质量压缩,非长宽压缩)
    java项目中的路径获取,request
    阿里云(腾讯云类似)服务器控制台配置开放所有的端口
  • 原文地址:https://www.cnblogs.com/pushudepu/p/6064656.html
Copyright © 2020-2023  润新知