用C#写的方块赛车

实际上根据是以前网上流传的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 }

 

posted @ 2020-10-20 06:35  黑衫老腰  阅读(251)  评论(0编辑  收藏  举报