• C#版俄罗斯方块


    C++是游戏编程的首选语言,但我相信C++能做到的C#也能做到。

    本篇介绍用C#编写一个俄罗斯方块程序的原理,以及在C#里面播放声音,保存游戏设置的方法。

    游戏界面预览:



    菜单预览:



    自定义每个小方块颜色功能界面:



    游戏主要有四部分组成:Square类,Block类,gameField类,游戏引擎

    Square类:
              这个类描述的对象是组成大方块中的每个小正方形实体。
         类设计:
        class Square
        {
            public Point location;   //小方块的坐标
            public Size size;          //小方块大小
            public Color foreColor;  //小方块前景色
            public Color backColor; //小方块背景色
            public Square(Size initSize,Color initForeColor,Color initBackColor) //构造函数
            {  ……}
             public void Draw(System.IntPtr winHandle) //在指定设备上画方块
            {  …… }
             public void Erase(System.IntPtr winHandle)//擦除方块
            { ……  }
         }

    Block类:
              这个类描述的对象是某一个大方块的实体。每个大方块由四个小正方形组成,一共有7种组合方式。这个类需要实现一个大方块实体所有的属性和动作。包括:方块的形状,位置,方块左移,右移,下移,旋转等。
          类设计:
     class Block
        {
            public Square square1;  //组成block的四个小方块
            public Square square2;
            public Square square3;
            public Square square4;

            private const int squareSize = GameField.SquareSize; //小方块的边长
            public enum BlockTypes
            {
                undefined = 0,
                square = 1,
                line = 2,
                J = 3,
                L = 4,
                T = 5,
                Z = 6,
                S = 7
            };//一共有7种形状
            public BlockTypes blockType;  //方块的形状
            //七个小方块的颜色数组
            private Color foreColor;
            private Color backColor;
            //方块的方向
            public enum RotateDirections
            {
                North = 1,
                East = 2,
                South = 3,
                West = 4
            };
            public RotateDirections myRotation = RotateDirections.North;
           
            public Block(Point thisLocation,BlockTypes bType)
            { ……}
            //含有自定义颜色的重载
            public Block(Point thisLocation, BlockTypes bType,Color fc,Color bc)
            { ……}

            /*画方块*/
            public void Draw(System.IntPtr winHandle)
            {…… }
            /*擦方块*/
            public void Erase(System.IntPtr winHandle)
            {…… }

            /*移动*/
            public bool down()
            {……}
            public bool left()
            {……}
            public bool right()
            {……}
            /*旋转block*/
            public void Rotate()
            {……}
            /*检测是否到顶*/
            public int Top()
            {……}
        }

    GameField类:
            这个类描述的对象是游戏场景实体,包括场景的背景色,大小,方块是否还可以移动,以及场景中填满一行的检测等。
            类设计:
         class GameField
        {
            public const int width = 20;           //场景的宽,以方块个数为单位
            public const int height = 30;
            public const int SquareSize = 15;      //每个四分之一小方块的边长
            public static Color BackColor;         //场景的背景色
            public static System.IntPtr winHandle; //场景的handle
            public static Color[] BlockForeColor ={ Color.Blue, Color.Beige, Color.DarkKhaki, Color.DarkMagenta, Color.DarkOliveGreen, Color.DarkOrange, Color.DarkRed };
            public static Color[] BlockBackColor ={ Color.LightCyan, Color.DarkSeaGreen, Color.Beige, Color.Beige, Color.Beige, Color.Beige, Color.Beige };
            public static bool isChanged=false; //设置是否被更改的标志位
            public static SoundPlayer sound = new SoundPlayer();  //播放声音

            public static Square[,] arriveBlock = new Square[width, height]; //保存已经不能再下落了的方块
            public static int[] arrBitBlock=new int[height];  //位数组:当某个位置有方块时,该行的该位为1
            private const int bitEmpty = 0x0;      //0000 0000 0000 0000 0000
            private const int bitFull = 0xFFFFF;   //1111 1111 1111 1111 1111

            /*检测某个位置是否为空*/
            public static bool isEmpty(int x, int y)
            {……}
            /*将方块停住*/
            public static void stopSquare(Square sq, int x, int y)
            {……}
            /*检测行是否满
             * 返回:成功消除的行数和  (方便统计分数)
             */

            public static int CheckLines()
            { ……}
            /*播放声音*/
            public static void PlaySound(string soundstr)
            {……}
            /*重画*/
            public static void Redraw()
            { …… }
             //结束
        }

    游戏引擎:
          游戏引擎正如其名,就像一个发动机一样让游戏不间断运行。本游戏中就是让方块以一定的速度下落。并响应键盘事件,实行左右移动,和向下加速功能。(代码见源码)

    声音播放:

         音效是游戏不可缺少的一部分。在.Net2.0中已经提供了一个类来播放声音。在using System.Media;命名空间。
         本游戏中播放声音的代码如下:(在 GameField类中)
         using System.Media;

         public static SoundPlayer sound = new SoundPlayer();
         
         /*播放声音*/
            public static void PlaySound(string soundstr)
            {
                switch (soundstr)
                {
                    case "FinishOneLine": //消除一行的声音
                        if (!File.Exists("FinishOneLine.wav")) return;
                        sound.SoundLocation = "FinishOneLine.wav";
                        break;
                    case "CanNotDo": //当无法操作时
                        if (!File.Exists("CanNotDo.wav")) return;
                        sound.SoundLocation = "CanNotDo.wav";
                        break;
                }
                sound.Play();
            }
            要播放的时候调用PlaySound()方法即可。
            其实步骤很简单,先引用System.Media空间,然后创建一个SoundPlayer 对象,用SoundLocation 属性设置声音文件的地址,然后调用Play()方法即可播放。不过注意,这个类可以播放的声音格式只有Wav文件。

    保存游戏设置:
          在游戏中经常要保存用户自定义的设置。本游戏通过写进ini文件来保存。
          主要代码如:

           /*加载窗体时从配置文件Setting.ini中读取游戏设置*/
            private void getSettings()
            {
                if (!File.Exists("Setting.ini"))
                    return;
                FileStream fs = new FileStream("Setting.ini", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                StreamReader sr = new StreamReader(fs);
                string line1=sr.ReadLine();
                string line2=sr.ReadLine();
                string line3=sr.ReadLine();
                if (line1 != null && line1.Split('=').Length > 1)
                {
                    GameField.BackColor = Color.FromArgb(int.Parse(line1.Split('=')[1]));
                    picBackGround.BackColor = GameField.BackColor;
                }
                if (line2 != null && line2.Split('=').Length > 1)
                    GameField.BlockForeColor = strToColor(line2.Split('=')[1]);
                if (line3 != null && line3.Split('=').Length > 1)
                    GameField.BlockBackColor = strToColor(line3.Split('=')[1]);
                sr.Close();
                fs.Close();
            }
            /*如果游戏设置被更改,将新的设置保存到Setting.ini*/
            private void saveSettings()
            {
                FileStream fs = new FileStream("Setting.ini", FileMode.Create, FileAccess.ReadWrite);
                StreamWriter sw = new StreamWriter(fs);
                sw.WriteLine("GameFieldColor="+GameField.BackColor.ToArgb());
                sw.WriteLine("BlockFroeColor=" + colorToStr(GameField.BlockForeColor));
                sw.WriteLine("BlockBackColor=" + colorToStr(GameField.BlockBackColor));
                sw.Flush();
                sw.Close();
                fs.Close();
            }

    麻雀虽小,五脏俱全,了解更多请看源码。
    游戏源码下载:CODE

  • 相关阅读:
    P1772 [ZJOI2006]物流运输
    P3951 小凯的疑惑
    P1082 同余方程(【模板】exgcd)
    T107741 【模板】权值线段树合并
    P3205 [HNOI2010]合唱队
    P1062 数列
    P1144 最短路计数
    P1502 窗口的星星
    P4147 玉蟾宫(【模板】悬线法)
    CSP模拟赛#3 分段(T1-26)
  • 原文地址:https://www.cnblogs.com/tuyile006/p/748256.html
Copyright © 2020-2023  润新知