实际上根据是以前网上流传的VB版本的思路改编的,设计的非常巧妙,本人可没这原创思路。非常短小的一个游戏,将数组玩的得心应手,还包含碰撞检测等等。。。
下面是我设计的界面:
别小看它,玩起来难度很大,坚持60秒都难。点我下载!
1 using System; 2 using System.Drawing; 3 using System.Drawing.Drawing2D; 4 using System.Windows.Forms; 5 6 namespace 方块赛车 7 { 8 public partial class Form1 : Form 9 { 10 const int Unit = 20; // 一个方格单元的大小,单位像素 11 const int Road = 20; // 跑道的长度,单位方块;路面宽7个方格,小车占用3个 12 const int Wall = 20; // 墙的厚度,单位像素 13 float OriginX; // 作图的原点X轴坐标,小车位于正中时左下角(车身)的坐标 14 float OriginY; // 作图的原点Y轴坐标,也就是跑道最底部y轴的坐标 15 int[] LeftWay = new int[Road]; // 左边每段跑道的障碍物的大小,也就是方格的数量 16 int[] RightWay = new int[Road]; // 右边每段跑道的障碍物的大小,也就是方格的数量 17 float CarX; // 赛车左下角X轴的坐标(赛车只做水平移动,不需记录Y轴坐标) 18 int Second; // 记录已玩秒数 19 Graphics g; 20 Random random = new Random(); 21 22 public Form1() 23 { 24 InitializeComponent(); 25 g = this.CreateGraphics(); 26 OriginX = (this.ClientSize.Width - 3 * Unit) / 2; 27 OriginY = Road * Unit; 28 } 29 30 private void button1_Click(object sender, EventArgs e) 31 { 32 this.Refresh(); 33 CarX = OriginX; // 小车复位 34 DrawWall(); 35 for (int i = 0; i < Road; i++) // 障碍复位 36 { 37 LeftWay[i] = 0; 38 RightWay[i] = 0; 39 DrawWay(i); 40 } 41 DrawCar(); 42 Second = 0; 43 timer1.Enabled = true; 44 button1.Enabled = false; 45 checkBox1.Enabled = true; 46 checkBox1.Focus(); 47 Console.WriteLine(this.CanSelect); // True 48 Console.WriteLine(this.Focus()); // False 49 } 50 51 private void DrawWall() 52 { 53 Brush brickBrush = new HatchBrush(HatchStyle.HorizontalBrick, Color.Black, Color.Gray); 54 Pen penLine = new Pen(brickBrush, Wall); 55 float x1 = OriginX - 2 * Unit - Wall / 2, x2 = OriginX + 5 * Unit + Wall / 2; 56 g.DrawLine(penLine, x1, 0, x1, OriginY); // 画路的左边线 57 g.DrawLine(penLine, x2, 0, x2, OriginY); // 画路的右边线 58 } 59 60 private void DrawCar() // 车可以不擦,擦跑道的时候就把车全擦了 61 { 62 Brush brushCar = Brushes.Green; 63 g.FillRectangle(brushCar, CarX, OriginY - Unit, 3 * Unit, Unit); // 车身 64 g.FillRectangle(brushCar, CarX + Unit, OriginY - 2 * Unit, Unit, Unit); // 车头 65 } 66 67 private void DrawWay(int index) // 画一层跑道(含障碍) 68 { 69 SolidBrush brushBack = new SolidBrush(Color.LightGray); 70 Brush brushWay = Brushes.Black; 71 float x1 = OriginX - 2 * Unit, x2 = OriginX + 5 * Unit - RightWay[index] * Unit; 72 float y = OriginY - (index + 1) * Unit; 73 g.FillRectangle(brushBack, x1, y, 7 * Unit, Unit); // 擦除所有障碍 74 g.FillRectangle(brushWay, x1, y, LeftWay[index] * Unit, Unit); // 画左边障碍 75 g.FillRectangle(brushWay, x2, y, RightWay[index] * Unit, Unit); // 画右边障碍 76 } 77 78 private void timer1_Tick(object sender, EventArgs e) 79 { 80 for (int i = 0; i < Road - 1; i++) // 每一层跑道往下移 81 { 82 LeftWay[i] = LeftWay[i + 1]; 83 RightWay[i] = RightWay[i + 1]; 84 DrawWay(i); 85 } 86 do 87 { 88 LeftWay[Road - 1] = random.Next(5); // 最上层的路段设置随机值[0,4] 89 RightWay[Road - 1] = random.Next(5); 90 } while ((LeftWay[Road - 1] + RightWay[Road - 1] > 4) || 91 (LeftWay[Road - 2] + RightWay[Road - 1] > 4) || (LeftWay[Road - 1] + RightWay[Road - 2] > 4) || 92 (LeftWay[Road - 3] + RightWay[Road - 1] > 5) || (LeftWay[Road - 1] + RightWay[Road - 3] > 5)); 93 // 条件必须满足:第一行满足路面能够容纳车身,第二行满足往前走一步时车身能通过;第三行满足往前走一步时车头能通过 94 DrawWay(Road - 1); 95 DrawCar(); 96 CrashDetection(); 97 Second = Second + 1; 98 label1.Text = "时间:" + Second * timer1.Interval / 1000 + "秒"; 99 } 100 101 private void CrashDetection() 102 { 103 Brush brushCrash = Brushes.Yellow; 104 if (CarX < OriginX - 2 * Unit + LeftWay[0] * Unit) // 车身左侧发生碰撞 105 { 106 g.FillRectangle(brushCrash, CarX, OriginY - Unit, Unit, Unit); 107 GameOver(); 108 } 109 if (CarX + 3 * Unit > OriginX + 5 * Unit - RightWay[0] * Unit) // 车身右侧发生碰撞 110 { 111 g.FillRectangle(brushCrash, CarX + 2 * Unit, OriginY - Unit, Unit, Unit); 112 GameOver(); 113 } 114 if (CarX + Unit < OriginX - 2 * Unit + LeftWay[1] * Unit || // 车头与左侧障碍发生碰撞 115 CarX + 2 * Unit > OriginX + 5 * Unit - RightWay[1] * Unit) // 车头与右侧障碍发生碰撞 116 { 117 g.FillRectangle(brushCrash, CarX + Unit, OriginY - 2 * Unit, Unit, Unit); 118 GameOver(); 119 } 120 } 121 122 private void GameOver() 123 { 124 g.DrawString("Game Over", new Font("微软雅黑", 40), Brushes.Red, 50, 200); 125 timer1.Enabled = false; 126 button1.Enabled = true; 127 checkBox1.Enabled = false; 128 button1.Focus(); 129 } 130 131 private void Form1_KeyDown(object sender, KeyEventArgs e) 132 { 133 Console.WriteLine("KeyCode: {0}", e.KeyCode); // 因窗体上控件焦点导致箭头键无法使用 134 if (e.KeyCode == Keys.Left) CarX -= Unit; 135 if (e.KeyCode == Keys.Right) CarX += Unit; 136 if (e.KeyCode == Keys.A) CarX -= Unit; 137 if (e.KeyCode == Keys.D) CarX += Unit; 138 } 139 140 private void checkBox1_Click(object sender, EventArgs e) 141 { 142 timer1.Enabled = !checkBox1.Checked; 143 } 144 145 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 146 { 147 if (comboBox1.SelectedIndex == 0) timer1.Interval = 350; 148 if (comboBox1.SelectedIndex == 1) timer1.Interval = 250; 149 if (comboBox1.SelectedIndex == 2) timer1.Interval = 150; 150 } 151 152 private void Form1_KeyPress(object sender, KeyPressEventArgs e) 153 { 154 Console.WriteLine("KeyChar: {0}", e.KeyChar); 155 e.Handled = true; 156 } 157 158 // 把窗体上所有子控件的IsInputKey属性设置为true后,箭头键终于可以用了 159 private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 160 { 161 e.IsInputKey = true; 162 } 163 164 private void checkBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 165 { 166 e.IsInputKey = true; 167 } 168 } 169 }