C#实现俄罗斯方块的基本功能

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace 俄罗斯方块
{
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}
		PictureBox pb;
		const int w = 10;
		const int h = 20;
		const int a = 40;
		int speed = 400;
		int marks = 0;
		bool gameoverflag = false;
		int[,] p = new int[w, h];
		int[,] c = new int[w, h];
		int[,] c_old = new int[w, h];
		Timer timer;
		
		void MainForm_Load(object sender, EventArgs e)
		{
			this.StartPosition = FormStartPosition.CenterScreen;
			this.AutoSize = true;
			this.MaximizeBox = false;
			this.FormBorderStyle = FormBorderStyle.FixedSingle;
			pb = new PictureBox();
			pb.Margin = new Padding(0, 0, 0, 0);
			pb.Width = w * a;
			pb.Height = h * a;
			pb.Location = new Point(0, 0);
			pb.BackColor = Color.LightGray;
			this.Controls.Add(pb);
			this.KeyDown += new KeyEventHandler(MainForm_KeyDown);
			this.KeyUp += new KeyEventHandler(MainForm_KeyUp);
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					p[i, j] = 0;
				}
			}
			c = make_diamond(0);
			c_old = make_emptydiamond();
			timer = new Timer();
			timer.Interval = speed;
			timer.Tick += new EventHandler(timer_Tick);
			draw();
		}

		void timer_Tick(object sender, EventArgs e)
		{
			if(isequal(c, c_old))
			{
				p = add_p_c(c);
				int[] l_temp = detect_fullline();
				int lines = 0;
				for(int i = 0; i < h; i++)
				{
					if(l_temp[i] == 1)
					{
						lines++;
					}
				}
				marks += lines * lines;
				p = clear_fullline();
				if(isgameover())
				{
					timer.Enabled = false;
					gameoverflag = true;
					MessageBox.Show("Game Over!");
					return;
				}
				c = make_diamond(0);
				c_old = make_emptydiamond();
			}
			else if(isequal(c, move_down()))
			{
				c_old = c;
			}
			else if(!isequal(c, move_down()))
			{
				c = move_down();
			}
			draw();
			this.Text = "俄罗斯方块 得分:" + marks.ToString();
		}

		int[,] make_diamond(int n)
		{
			int[,] c_temp = new int[w, h];
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					c_temp[i, j] = 0;
				}
			}
			switch (n)
			{
				case 0:
					int seed = (int)DateTime.Now.Millisecond;
					Random rd = new Random(seed);
					return make_diamond(rd.Next(1, 25));
				case 1:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[0, 2] = 1;
					c_temp[0, 3] = 1;
					break;
				case 2:
					c_temp[0, 0] = 1;
					c_temp[1, 0] = 1;
					c_temp[2, 0] = 1;
					c_temp[3, 0] = 1;
					break;
				case 3:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 1] = 1;
					c_temp[1, 2] = 1;
					break;
				case 4:
					c_temp[1, 0] = 1;
					c_temp[2, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 1] = 1;
					break;
				case 5:
					c_temp[0, 1] = 1;
					c_temp[0, 2] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					break;
				case 6:
					c_temp[0, 0] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					c_temp[2, 1] = 1;
					break;
				case 7:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[0, 2] = 1;
					c_temp[1, 1] = 1;
					break;
				case 8:
					c_temp[0, 0] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					c_temp[2, 0] = 1;
					break;
				case 9:
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					c_temp[1, 2] = 1;
					break;
				case 10:
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					c_temp[2, 1] = 1;
					break;
				case 11:
					c_temp[0, 0] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					c_temp[1, 2] = 1;
					break;
				case 12:
					c_temp[0, 1] = 1;
					c_temp[1, 1] = 1;
					c_temp[2, 0] = 1;
					c_temp[2, 1] = 1;
					break;
				case 13:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[0, 2] = 1;
					c_temp[1, 2] = 1;
					break;
				case 14:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[2, 0] = 1;
					break;
				case 15:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[0, 2] = 1;
					c_temp[1, 0] = 1;
					break;
				case 16:
					c_temp[0, 0] = 1;
					c_temp[1, 0] = 1;
					c_temp[2, 0] = 1;
					c_temp[2, 1] = 1;
					break;
				case 17:
					c_temp[0, 2] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					c_temp[1, 2] = 1;
					break;
				case 18:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 1] = 1;
					c_temp[2, 1] = 1;
					break;
				case 19:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					break;
				case 20:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					break;
				case 21:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					break;
				case 22:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[1, 0] = 1;
					c_temp[1, 1] = 1;
					break;
				case 23:
					c_temp[0, 0] = 1;
					c_temp[0, 1] = 1;
					c_temp[0, 2] = 1;
					c_temp[0, 3] = 1;
					break;
				case 24:
					c_temp[0, 0] = 1;
					c_temp[1, 0] = 1;
					c_temp[2, 0] = 1;
					c_temp[3, 0] = 1;
					break;
			}
			return c_temp;
		}
		
		int[,] add_p_c(int[,] c_temp)
		{
			int[,] p_temp = new int[w, h];
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					p_temp[i, j] = p[i, j] + c_temp[i, j];
				}
			}
			return p_temp;
		}
		
		int[] detect_border()
		{
			int i_min = w;
			int i_max = -1;
			int j_min = h;
			int j_max = -1;
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					if(c[i, j] != 0)
					{
						i_min = i;
						break;
					}
				}
				if(i_min != w)
				{
					break;
				}
			}
			for(int i = w - 1; i >= 0; i--)
			{
				for(int j = 0; j < h; j++)
				{
					if(c[i, j] != 0)
					{
						i_max = i;
						break;
					}
				}
				if(i_max != -1)
				{
					break;
				}
			}
			for(int j = 0; j < h; j++)
			{
				for(int i = 0; i < w; i++)
				{
					if(c[i, j] != 0)
					{
						j_min = j;
						break;
					}
				}
				if(j_min != h)
				{
					break;
				}
			}
			for(int j = h - 1; j >= 0; j--)
			{
				for(int i = 0; i < w; i++)
				{
					if(c[i, j] != 0)
					{
						j_max = j;
						break;
					}
				}
				if(j_max != -1)
				{
					break;
				}
			}
			int[] border = {j_min, j_max, i_min, i_max};//上下左右边界
			return border;
		}
		
		bool overlap(int[,] c_temp)
		{
			bool bl = false;
			int[,] p_temp = add_p_c(c_temp);
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					if(p_temp[i, j] > 1)
					{
						return true;
					}
				}
			}
			return bl;
		}
		
		int[,] make_emptydiamond()
		{
			int[,] c_temp = new int[w, h];
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					c_temp[i, j] = 0;
				}
			}
			return c_temp;
		}
		
		bool isempty(int[,] c_temp)
		{
			bool bl = true;
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					if(c_temp[i, j] > 0)
					{
						return false;
					}
				}
			}	
			return bl;
		}
		
		bool isequal(int[,] c1, int[,] c2)
		{
			bool bl = true;
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					if(c1[i, j] != c2[i, j])
					{
						return false;
					}
				}
			}
			return bl;
		}
		
		int[] detect_fullline()
		{
			int[] l = new int[h];
			for(int i = 0; i < h; i++)
			{
				l[i] = 1;
			}
			for(int j = 0; j < h; j ++)
			{
				for(int i = 0; i < w; i++)
				{
					if(p[i, j] == 0)
					{
						l[j] = 0;
						break;
					}
				}
			}
			return l;
		}
		
		int[,] clear_fullline()
		{
			int[,] p_temp = make_emptydiamond();
			int flag = h - 1;
			int[] l = detect_fullline();
			for(int i = h - 1; i >= 0; i--)
			{
				if(l[i] == 0)
				{
					for(int j = 0; j < w; j++)
					{
						p_temp[j, flag] = p[j, i];
					}
					flag--;
				}
			}
			return p_temp;
		}
		
		bool isgameover()
		{
			bool bl = false;
			for(int i = 0; i < w; i++)
			{
				if(p[i, 0] > 0)
				{
					return true;
				}
			}
			return bl;
		}
		
		int[,] turn()
		{
			int[,] c_temp = make_emptydiamond();
			int[] border_temp = detect_border();
			int u = border_temp[0];
			int d = border_temp[1];
			int l = border_temp[2];
			int r = border_temp[3];
			if(!(w - 1 - l < d - u || h - 1 - u < r - l))
			{
				if(r - l == 1 && d - u == 1)
				{
					return c;
				}
				else if(r - l == 3)
				{
					c_temp[l, u] = c[l, u];
					c_temp[l, u + 1] = c[l + 1, u];
					c_temp[l, u + 2] = c[l + 2, u];
					c_temp[l, u + 3] = c[l + 3, u];
				}
				else if(d - u == 3)
				{
					c_temp[l, u] = c[l, u];
					c_temp[l + 1, u] = c[l, u + 1];
					c_temp[l + 2, u] = c[l, u + 2];
					c_temp[l + 3, u] = c[l, u + 3];
				}
				else if(r - l == 2)
				{
					c_temp[l, u] = c[l, u + 1];
					c_temp[l + 1, u] = c[l, u];
					c_temp[l, u + 1] = c[l + 1, u + 1];
					c_temp[l + 1, u + 1] = c[l + 1, u];
					c_temp[l, u + 2] = c[l + 2, u + 1];
					c_temp[l + 1, u + 2] = c[l + 2, u];
				}
				else if(d - u == 2)
				{
					c_temp[l, u] = c[l, u + 2];
					c_temp[l + 1, u] = c[l, u + 1];
					c_temp[l + 2, u] = c[l, u];
					c_temp[l, u + 1] = c[l + 1, u + 2];
					c_temp[l + 1, u + 1] = c[l + 1, u + 1];
					c_temp[l + 2, u + 1] = c[l + 1, u];
				}
			}
			if(overlap(c_temp) || isempty(c_temp))
			{
				return c;
			}
			return c_temp;
		}
		
		int[,] move_down()
		{
			int[,] c_temp = make_emptydiamond();
			if(!(detect_border()[1] == h - 1))
			{
				for (int i = 0; i < w; i++)
                {
                    for (int j = 1; j < h; j++)
                    {
                        c_temp[i, j] = c[i, j - 1];
                    }
                }
			}
			if(overlap(c_temp) || isempty(c_temp))
			{
				return c;
			}
			return c_temp;
		}
		
		int[,] move_left()
		{
			int[,] c_temp = make_emptydiamond();
			if(!(detect_border()[2] == 0))
			{
				for (int j = 0; j < h; j++)
                {
                    for (int i = 0; i < w - 1; i++)
                    {
                        c_temp[i, j] = c[i + 1, j];
                    }
                }
			}
			if(overlap(c_temp) || isempty(c_temp))
			{
				return c;
			}
			return c_temp;
		}
		
		int[,] move_right()
		{
			int[,] c_temp = make_emptydiamond();
			if(!(detect_border()[3] == w - 1))
			{
				for (int j = 0; j < h; j++)
                {
                    for (int i = 1; i < w; i++)
                    {
                        c_temp[i, j] = c[i - 1, j];
                    }
                }
			}
			if(overlap(c_temp) || isempty(c_temp))
			{
				return c;
			}
			return c_temp;
		}
		
		void draw()
		{
			int[,] p_temp = add_p_c(c);
			Bitmap bmp = new Bitmap(pb.Width, pb.Height);
			Graphics g = Graphics.FromImage(bmp);
			g.FillRectangle(new SolidBrush(pb.BackColor), new Rectangle(0, 0, pb.Width, pb.Height));
			for(int i = 1; i < w; i++)
			{
				g.DrawLine(new Pen(Color.Black, 1), i * a, 0, i * a, h * a);
			}
			for(int j = 1; j < h; j++)
			{
				g.DrawLine(new Pen(Color.Black, 1), 0, j * a, w * a, j * a);
			}
			for(int i = 0; i < w; i++)
			{
				for(int j = 0; j < h; j++)
				{
					switch(p_temp[i, j])
					{
						case 1:
							g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(a * i, a * j, a, a));
							break;
						default:
							break;
					}
				}
			}
			pb.Image = bmp;
			GC.Collect();
		}
		
		void MainForm_KeyDown(object sender, KeyEventArgs e)
		{
			if(gameoverflag)
			{
				return;
			}
			switch (e.KeyData)
			{
				case Keys.W:
					c = turn();
					break;
				case Keys.Up:
					c = turn();
					break;
				case Keys.S:
					timer.Interval = speed / 10;
					break;
				case Keys.Down:
					timer.Interval = speed / 10;
					break;
				case Keys.A:
					c = move_left();
					break;
				case Keys.Left:
					c = move_left();
					break;
				case Keys.D:
					c = move_right();
					break;
				case Keys.Right:
					c = move_right();
					break;
				case Keys.Space:
					timer.Enabled = timer.Enabled == false ? true : false;
					break;
				default:
					break;
			}
			draw();
		}
		
		void MainForm_KeyUp(object sender, KeyEventArgs e)
		{
			if(e.KeyData == Keys.S || e.KeyData == Keys.Down)
			{
				timer.Interval = speed;
			}
		}
	}
}


很短点的一段代码,实现了俄罗斯方块的基本功能,可以很方便的修改和扩展。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值