using System;
using System.Drawing;
using System.Windows.Forms;

namespace MyGame
{
    public delegate void KillWoodEventHandler();
    public interface IGameBo
    {
        int[,] Grids { get; }
        int XPos { get; }
        int YPos { get; }
    }
    public interface IGameBiz
    {
        void Run();
    }
    public interface IGameLogic
    {
        void Draw(Graphics e);
        void KeyDown(KeyEventArgs e);
    }
    public interface IGameWood : IGameLogic
    {
        event KillWoodEventHandler KillWood;
    }
    public interface IWoodBo
    {
        int[,] Grids { get; }
    }
    public interface IWoodBiz
    {
        bool OnAngle();
        bool CanLeft();
        bool CanRight();
        bool CanDown();
    }
    public interface IWood : IWoodBiz, IWoodBo
    {
    }

    public class WoodGame : IGameBo, IGameBiz, IGameLogic, IGameWood
    {
        public const int X = 20, Y = 20;
        public const int StartPos = 7;
        public const int Dimension = 18;
        public const int XDimension = XSize * Dimension;
        public const int YDimension = YSize * Dimension;
        public const int XSize = 16;
        public const int YSize = 26;
        public event KillWoodEventHandler KillWood;

        int[,] Grids { get; set; }
        int XPos { get; set; }
        int YPos { get; set; }

        int[,] IGameBo.Grids { get { return this.Grids; } }
        int IGameBo.XPos { get { return this.XPos; } }
        int IGameBo.YPos { get { return this.YPos; } }

        Random Random = new Random();
        IWood CurrentWood, NextWood;
        Bitmap bmp;
        public WoodGame()
        {
            Init();
        }
        ~WoodGame()
        {
            UnInit();
        }

        public void Draw(Graphics e)
        {
            using (Graphics graphics = Graphics.FromImage(bmp))
            {
                graphics.Clear(Color.White);
                DrawContext(graphics);
            }
            e.DrawImage(bmp, X, Y);
        }
        public void KeyDown(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Left:
                    if (CurrentWood.CanLeft())
                    {
                        XPos--;
                        this.OnDraw();
                    }
                    break;
                case Keys.Right:
                    if (CurrentWood.CanRight())
                    {
                        XPos++;
                        this.OnDraw();
                    }
                    break;
                case Keys.Down:
                    Run();
                    break;
                case Keys.Space:
                    if (CurrentWood.OnAngle())
                        this.OnDraw();
                    break;
            }
        }
        public void Run()
        {
            if (CurrentWood.CanDown())
            {
                YPos++;
            }
            else
            {
                FinishWood();
                StartWood();
            }
            this.OnDraw();
        }
        void Init()
        {
            bmp = new Bitmap(XDimension + 1, YDimension + 1);
            Grids = new int[XSize, YSize];
            NextWood = GetWood();
            StartWood();
        }
        void UnInit()
        {
            bmp.Dispose();
        }
        void StartWood()
        {
            CurrentWood = NextWood;
            NextWood = GetWood();
            XPos = StartPos;
            YPos = 0;
        }
        void FinishWood()
        {
            int size = CurrentWood.Grids.GetLength(0);

            for (int y = 0; y < size; y++)
            {
                for (int x = 0; x < size; x++)
                {
                    if (CurrentWood.Grids[x, y] != 0)
                        Grids[XPos + x, YPos + y] = 1;
                }
            }
            PriKillWood();
            OnDraw();
        }
        void PriKillWood()
        {
            int size = CurrentWood.Grids.GetLength(0);
            int y1 = Math.Min(YPos + size, YSize) - 1;
            int y2 = y1;

            while (y1 >= YPos)
            {
                int x1 = 0;
                while (x1 < XSize)
                {
                    if (Grids[x1, y1] == 0)
                        break;
                    x1++;
                }
                if (x1 == XSize)
                {
                    OnKillWood();
                }
                else
                {
                    for (int x = 0; x < XSize; x++)
                        Grids[x, y2] = Grids[x, y1];
                    y2--;
                }
                y1--;
            }
            while (y1 >= 0)
            {
                for (int x = 0; x < XSize; x++)
                    Grids[x, y2] = Grids[x, y1];
                y2--;
                y1--;
            }
        }
        void OnDraw()
        {
            if (Form.ActiveForm != null)
                Form.ActiveForm.Refresh();
        }
        void DrawContext(Graphics e)
        {
            for (int x = 0; x <= XDimension; x += Dimension)
                e.DrawLine(Pens.SlateGray, x, 0, x, YDimension);

            for (int y = 0; y <= YDimension; y += Dimension)
                e.DrawLine(Pens.SlateGray, 0, y, XDimension, y);

            int size = CurrentWood.Grids.GetLength(0);

            for (int x = 0; x < XSize; x++)
            {
                for (int y = 0; y < YSize; y++)
                {
                    if (Grids[x, y] == 1)
                        e.FillRectangle(Brushes.Black, new Rectangle(x * Dimension + 2, y * Dimension + 2, Dimension - 3, Dimension - 3));
                }
            }
            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    if (CurrentWood.Grids[x, y] == 1)
                        e.FillRectangle(Brushes.Black, new Rectangle((XPos + x) * Dimension + 2, (YPos + y) * Dimension + 2, Dimension - 3, Dimension - 3));
                }
            }
        }
        private void OnKillWood()
        {
            if (KillWood != null)
            {
                KillWood();
            }
        }
        Wood GetWood()
        {
            int rnd = Random.Next() % 8;
            switch (rnd)
            {
                case 0:
                    rnd = Random.Next() % 2;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{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}},
                    }, rnd);
                case 1:
                    rnd = Random.Next() % 4;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{1,0,0},
                        {1,0,0},
                        {1,1,0}},

                       {{0,0,0},
                        {1,1,1},
                        {1,0,0}},

                       {{1,1,0},
                        {0,1,0},
                        {0,1,0}},

                       {{0,0,0},
                        {0,0,1},
                        {1,1,1}}
                    }, rnd);
                case 2:
                    rnd = Random.Next() % 2;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{1,1,0},
                        {0,1,1},
                        {0,0,0}},

                       {{0,1,0},
                        {1,1,0},
                        {1,0,0}},
                    }, rnd);
                case 3:
                    rnd = Random.Next() % 2;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{0,1,1},
                        {1,1,0},
                        {0,0,0}},

                       {{1,0,0},
                        {1,1,0},
                        {0,1,0}},
                    }, rnd);
                case 4:
                    rnd = Random.Next() % 4;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{0,0,1},
                        {0,0,1},
                        {0,1,1}},

                       {{0,0,0},
                        {1,0,0},
                        {1,1,1}},

                       {{0,1,1},
                        {0,1,0},
                        {0,1,0}},

                       {{0,0,0},
                        {1,1,1},
                        {0,0,1}}
                    }, rnd);
                case 5:
                    return new AngleWood(this, new int[,,] 
                    {
                       {{1,1},
                        {1,1}}
                    }, 0);
                case 6:
                    rnd = Random.Next() % 4;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{0,1,1},
                        {0,0,1},
                        {0,1,1}},

                       {{0,0,0},
                        {1,0,1},
                        {1,1,1}},

                       {{1,1,0},
                        {1,0,0},
                        {1,1,0}},

                       {{1,1,1},
                        {1,0,1},
                        {0,0,0}}
                    }, rnd);
                case 7:
                    rnd = Random.Next() % 4;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{1,1,1},
                        {0,1,0},
                        {0,0,0}},

                       {{0,0,1},
                        {0,1,1},
                        {0,0,1}},

                       {{0,0,0},
                        {0,1,0},
                        {1,1,1}},

                       {{1,0,0},
                        {1,1,0},
                        {1,0,0}}
                    }, rnd);/*
                case 8:
                    rnd = Random.Next() % 4;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{0,1,0},
                        {0,1,0},
                        {1,1,1}},

                       {{1,0,0},
                        {1,1,1},
                        {1,0,0}},

                       {{1,1,1},
                        {0,1,0},
                        {0,1,0}},

                       {{0,0,1},
                        {1,1,1},
                        {0,0,1}}
                    }, rnd);
                case 9:
                    rnd = Random.Next() % 4;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{1,0,0,0},
                        {1,1,0,0},
                        {1,1,1,0},
                        {1,1,1,1}},
                       {{1,1,1,1},
                        {1,1,1,0},
                        {1,1,0,0},
                        {1,0,0,0}},
                       {{1,1,1,1},
                        {0,1,1,1},
                        {0,0,1,1},
                        {0,0,0,1}},
                       {{0,0,0,1},
                        {0,0,1,1},
                        {0,1,1,1},
                        {1,1,1,1}}
                    }, rnd);
                case 10:
                    rnd = Random.Next() % 2;
                    return new AngleWood(this, new int[,,] 
                    {
                       {{1,1,1},
                        {0,0,0},
                        {1,1,1}},

                       {{1,0,1},
                        {1,0,1},
                        {1,0,1}}
                    }, rnd);*/
            }
            throw new Exception();
        }
    }

    public abstract class Wood : IWood
    {
        public IGameBo Game;
        public int[,] Grids { get; set; }

        public Wood(IGameBo mGame, int[,] mGrids)
        {
            this.Game = mGame;
            this.Grids = mGrids;
        }
        public abstract bool OnAngle();
        public virtual bool CanLeft()
        {
            return Check(Grids, Game.XPos - 1, Game.YPos);
        }
        public virtual bool CanRight()
        {
            return Check(Grids, Game.XPos + 1, Game.YPos);
        }
        public virtual bool CanDown()
        {
            return Check(Grids, Game.XPos, Game.YPos + 1);
        }
        public virtual int GetSize()
        {
            return Grids.GetLength(0);
        }
        protected bool Check(int[,] mGrids, int mXPos, int mYPos)
        {
            int size = this.GetSize();
            for (int y = 0; y < size; y++)
            {
                for (int x = 0; x < size; x++)
                {
                    if (mGrids[x, y] == 0)
                        continue;
                    if (mXPos + x < 0 || mXPos + x >= WoodGame.XSize || mYPos + y >= WoodGame.YSize || (mXPos + x >= 0 && mYPos + y >= 0 && Game.Grids[mXPos + x, mYPos + y] != 0))
                        return false;
                }
            }
            return true;
        }
    }

    public class AngleWood : Wood
    {
        int Angle;
        int AngleTime;
        int[, ,] AngleGrids;
        public AngleWood(IGameBo mGame, int[, ,] mAngleGrids, int mAngle)
            : base(mGame, GetAngle(mAngleGrids, mAngle))
        {
            this.Angle = mAngle;
            this.AngleTime = mAngleGrids.GetLength(0);
            this.AngleGrids = mAngleGrids;
        }
        public override bool OnAngle()
        {
            int angle = this.Angle;
            if (angle == this.AngleTime - 1)
                angle = 0;
            else
                angle++;

            int[,] newGrids;
            if (CanAngle(angle, out newGrids))
            {
                Grids = newGrids;
                this.Angle = angle;
                return true;
            }
            return false;
        }
        static int[,] GetAngle(int[, ,] mAngleGrids, int mAngle)
        {
            int size = mAngleGrids.GetLength(1);
            int[,] grids = new int[size, size];
            for (int x = 0; x < size; x++)
                for (int y = 0; y < size; y++)
                    grids[x, y] = mAngleGrids[mAngle, y, x];

            return grids;
        }
        public virtual bool CanAngle(int mAngle, out int[,] mNewGrids)
        {
            int size = this.GetSize();
            int[,] newAngle = GetAngle(AngleGrids, mAngle);
            mNewGrids = null;

            if (!Check(newAngle, Game.XPos, Game.YPos))
                return false;

            mNewGrids = newAngle;
            return true;
        }
    }

    static class GameProgram
    {
        class GameForm : Form
        {
            const string text = "俄罗斯方块,分数:";

            IGameWood game;
            public GameForm()
            {
                int cx = WoodGame.XDimension + WoodGame.X * 2 + SystemInformation.Border3DSize.Width * 2 + 3;
                int cy = WoodGame.YDimension + WoodGame.Y * 2 + SystemInformation.Border3DSize.Height * 2 + SystemInformation.CaptionHeight + 3;
                this.Size = new Size(cx, cy);
                this.DoubleBuffered = true;
                this.MaximizeBox = false;
                this.FormBorderStyle = FormBorderStyle.FixedSingle;
                this.Text = text + "0";

                game = new WoodGame();
                game.KillWood += game_KillWood;
            }
            int i = 0;
            void game_KillWood()
            {
                i += 100;
                this.Text = text + i;
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                game.Draw(e.Graphics);
            }
            protected override void OnKeyDown(KeyEventArgs e)
            {
                game.KeyDown(e);
            }
        }
        static void Main()
        {
            Application.Run(new GameForm());
        }
    }
}

 

posted on 2013-04-04 21:22  阔然开朗  阅读(322)  评论(0编辑  收藏  举报