我正在尝试使用C#在Windows窗体中创建俄罗斯方块游戏。这是我的Form1.cs代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tetris
{
public partial class Form1 : Form
{
Control s;
int value = 1;
Point startPointOfWindow;//red square-left top corner
Point endPointOfWindow;//red square- right bottom corner
public Timer timer1;
public Form1()
{
InitializeComponent();
}
private void Process()
{
do
{
this.s = ChooseOneShape();
this.s.Location = new System.Drawing.Point(10, 10);
//this.ResumeLayout(false);
//this.s.PerformLayout();
timer1 = new Timer();
timer1.Tick += new System.EventHandler(timer1_Tick);
timer1.Interval = 800;
timer1.Enabled = true;
//await Task.Delay(2000);
Application.DoEvents();
this.Controls.Add(this.s);
value++;
// System.Threading.Thread.Sleep(2000);
} while (value <= 3);
}
private Control ChooseOneShape()
{
Shape1 s2 = new Shape1();//rectangle
Shape2 s1 = new Shape2();//square
List<Control> list = new List<Control>();
list.Add(s2);
list.Add(s1);
Random r = new Random();
int index = r.Next(list.Count);
return list[index];
}
private void timer1_Tick(object sender, EventArgs e)
{
var oldLocation = new Point(this.s.Location.X + this.s.Width, this.s.Location.Y + this.s.Height);
if (oldLocation.X < endPointOfWindow.X && oldLocation.X >= startPointOfWindow.X &&
oldLocation.Y < endPointOfWindow.Y && oldLocation.Y >= startPointOfWindow.Y)
this.s.Location = new Point(this.s.Location.X + 10, this.s.Location.Y + 10);
else if (oldLocation.Y + 10 >= endPointOfWindow.Y && oldLocation.Y + 10 > startPointOfWindow.Y)
timer1.Enabled = false;
else if (oldLocation.X + 10 >= endPointOfWindow.X && oldLocation.X + 10 > startPointOfWindow.X)
this.s.Location = new Point(this.s.Location.X, this.s.Location.Y + 10);
else if (oldLocation.X < endPointOfWindow.X && oldLocation.X >= startPointOfWindow.X)
this.s.Location = new Point(this.s.Location.X + 10, this.s.Location.Y);
else if (oldLocation.Y < endPointOfWindow.Y && oldLocation.Y >= startPointOfWindow.Y)
this.s.Location = new Point(this.s.Location.X, this.s.Location.Y + 10);
else timer1.Enabled = false;
}
private void Form1_Shown(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
g.DrawRectangle(new Pen(Color.Red), 10, 10, 350, 250);
startPointOfWindow = new Point(10, 10);
endPointOfWindow = new Point(350, 250);
Process();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
var x = this.s.Location;
var size = this.s.Size;
//capture left arrow key
if (keyData == Keys.Left && x.X > 0 && x.Y + this.s.Height < 250)
{
this.s.Location = new System.Drawing.Point(x.X - 10, x.Y);
return true;
}
//capture right arrow key
if (keyData == Keys.Right && x.X + this.s.Width < 350 && x.Y + this.s.Height < 250)
{
this.s.Location = new System.Drawing.Point(x.X + 10, x.Y);
return true;
}
if (keyData == Keys.Down && x.Y + this.s.Height < 250)
{
this.s.Location = new System.Drawing.Point(x.X, x.Y + 10);
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
这是我的Shape1和Shape2:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
namespace Tetris
{
public class Shape1 : UserControl
{
protected override void OnPaint(PaintEventArgs pevent)
{
Graphics g = this.CreateGraphics();
Brush brush = new SolidBrush(Color.Red);
g.FillRectangle(brush, 0, 0, 80, 20);
base.Width = 80;
base.Height = 20;
}
}
public class Shape2 : UserControl
{
protected override void OnPaint(PaintEventArgs pevent)
{
Graphics g = this.CreateGraphics();
Brush brush = new SolidBrush(Color.MediumVioletRed);
g.FillRectangle(brush, 0, 0, 40, 40);
base.Width = 40;
base.Height = 40;
}
}
}
问题是计时器适用于选定的第二个形状。
这里是图像,当value = 2时选择了紫色正方形,并且计时器对其正常工作。但是,当value = 1时,计时器无法正常显示红色矩形。
因此上述代码中存在许多错误。但是我得到了解决方案。所以我只用了一个计时器,下面是代码。
在计时器的每个滴答声中,我都使用它来更新Shape的位置(即向下,向左,向右移动),当该形状到达底部时,我就调用了下一个随机选择的形状。我还使用了UserControl的Paint()方法在计时器的每个刻度上绘制形状。因此,每当在timer1_tick()中更新位置时,我就会调用UserControl的Invalidate()方法来更新UserControl的位置。
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tetris
{
public partial class Form1 : Form
{
Control s;
int value = 1;
Point startPointOfWindow;//red square-left top corner
Point endPointOfWindow;//red square- right bottom corner
public System.Windows.Forms.Timer timer3;
List<string> list;
public Form1()
{
InitializeComponent();
Shape1 s1 = new Shape1();//rectangle
Shape2 s2 = new Shape2();//square
list = new List<string>();
list.Add("Shape1");
list.Add("Shape2");
timer3 = new System.Windows.Forms.Timer();
timer3.Interval = 800;
timer3.Tick += new System.EventHandler(timer1_Tick);
timer3.Enabled = true;
Process();
}
private void Process()
{
switch (ChooseOneShape())
{
case "Shape1":
this.s = new Shape1();break;
case "Shape2":
this.s = new Shape2();break;
}
this.s.Location = new System.Drawing.Point(10, 10);
this.Controls.Add(this.s);
}
private string ChooseOneShape()
{
Random r = new Random();
int index = r.Next(list.Count);
return list[index];
}
private void timer1_Tick(object sender, EventArgs e)
{
var oldLocation = new Point(this.s.Location.X + this.s.Width, this.s.Location.Y + this.s.Height);
if (oldLocation.X < endPointOfWindow.X && oldLocation.X >= startPointOfWindow.X &&
oldLocation.Y < endPointOfWindow.Y && oldLocation.Y >= startPointOfWindow.Y)
{
s.Location = new Point(this.s.Location.X + 30, this.s.Location.Y + 30);
s.Invalidate();
}
else if (oldLocation.Y + 10 >= endPointOfWindow.Y && oldLocation.Y + 10 > startPointOfWindow.Y)
Process();
else if (oldLocation.X + 10 >= endPointOfWindow.X && oldLocation.X + 10 > startPointOfWindow.X)
{
this.s.Location = new Point(this.s.Location.X, this.s.Location.Y + 30);
s.Invalidate();
}
else if (oldLocation.X < endPointOfWindow.X && oldLocation.X >= startPointOfWindow.X)
{
this.s.Location = new Point(this.s.Location.X + 30, this.s.Location.Y);
s.Invalidate();
}
else if (oldLocation.Y < endPointOfWindow.Y && oldLocation.Y >= startPointOfWindow.Y)
{
this.s.Location = new Point(this.s.Location.X, this.s.Location.Y + 10);
s.Invalidate();
}
else Process();
//Refresh();
//Invalidate();
}
private void Form1_Shown(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
g.DrawRectangle(new Pen(Color.Red), 0, 0, 350, 250);
startPointOfWindow = new Point(0, 0);
endPointOfWindow = new Point(350, 250);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
var x = this.s.Location;
var size = this.s.Size;
//capture left arrow key
if (keyData == Keys.Left && x.X > 0 && x.Y + this.s.Height < 250)
{
this.s.Location = new System.Drawing.Point(x.X - 10, x.Y);
return true;
}
//capture right arrow key
if (keyData == Keys.Right && x.X + this.s.Width < 350 && x.Y + this.s.Height < 250)
{
this.s.Location = new System.Drawing.Point(x.X + 10, x.Y);
return true;
}
if (keyData == Keys.Down && x.Y + this.s.Height < 250)
{
this.s.Location = new System.Drawing.Point(x.X, x.Y + 10);
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
这是创建的2个UserControl:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
namespace Tetris
{
public class Shape1 : UserControl //Control
{
//rectangle
protected override void OnPaint(PaintEventArgs e)
{
Brush brush = new SolidBrush(Color.Red);
e.Graphics.FillRectangle(brush, 0, 0, 80, 20);
base.Width = 80;
base.Height = 20;
}
}
public class Shape2 : UserControl// Control
{
//square
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Brush brush = new SolidBrush(Color.MediumVioletRed);
g.FillRectangle(brush, 0, 0, 40, 40);
base.Width = 40;
base.Height = 40;
}
}
}