c# winform贪吃蛇小游戏

关于贪吃蛇需要用的对象:   1.蛇  (Snake)2.食物(Food)  3.  记录蛇身的位置(Snake_body[x,y]) 4 .食物位置Food[x,y]

简单业务:    1.蛇身移动

                    2.随机食物

                    3.蛇头与食物重叠

                     4.窗体检测上下左右方向,控制蛇身体移动方向

好了,废话不多说,开始:在页面拖入panle1,两个lable和button按钮,页面有点丑 ,关于页面位置的调整在Load实事件中调整,

首先定义成员变量,score  得分,每吃掉一次食物+1、 _Key_Name 初始蛇的移动方向(键盘)、_Snake_Body是蛇身数组、_Random产生随机数定义食物位置

#region 定义成员变量
/// <summary>
/// 得分
/// </summary>
private int score = 0;
/// <summary>
/// 键盘状态,初始为 start
/// </summary>
string _Key_Name = "Start";
/// <summary>
/// 蛇身数组
/// </summary>
Label[] _Snake_Body = new Label[3000];
/// <summary>
/// 随机数生成Food
/// </summary>
Random _Random = new Random();
/// <summary>
/// 记录位置
/// </summary>
int Snake_Boby_content_x = 0, Snake_Boby_content_y = 0;
#endregion

好了 ,接下来,初始化舍身和食物    在窗体的初始化事件Form1_Load中添加长度为5个label的蛇身
一个label的初始大小为10*10,并设置其的一些属性。
其中
Timer_Tick为蛇的移动事件,既每隔一次timer.Tick执行一次Timer_Tick
Form1_KeyDown为对键盘的监控,_point 指定panel的位置,Snake_food()生成食物 

Bitmap _bitmap = new Bitmap(Resource.zyd);
IntPtr h = _bitmap.GetHicon();
this.Icon = System.Drawing.Icon.FromHandle(h);
this.Text="Snake张益达";
this.Width = 1000;
this.Height = 850;

panel1.BorderStyle = BorderStyle.FixedSingle;
panel1.Width = 800;
panel1.Height = 840;
Point _point = new Point
{
X = this.Width - 150,
Y = 100
};
Point _point1 = new Point
{
X = this.Width - 80,
Y = 100
};
label1.Location = _point;
TxtScore.Location = _point1;
//初始化蛇 5个label 一个label x =y=10
for (int i=0;i<8;i++) {
//身段
Label Snake_Body_Content = new Label
{
Height = 10,
Width = 10,
Top = 200,//蛇的位置
Left = 200 - (i * 10),
BackColor = Color.Black,//背景色
ForeColor = Color.Black,
Text = "▉", //显示类型
Tag=i
};

this.BackColor = Color.White;

//加入蛇体型
_Snake_Body[i] = Snake_Body_Content;
panel1.Controls.Add(Snake_Body_Content);
}
//每隔一段时间发生右移动
timer1.Tick += new EventHandler(Timer_Tick);
timer1.Interval = 1000;
//检测事件监控
Snake_food();
}

接下来就是蛇体移动事件 ,在timer中执行 

public void Timer_Tick(object sender,EventArgs e) {

int x, y;//记录Snake的Head的XY坐标
x = _Snake_Body[0].Left;
y = _Snake_Body[0].Top;
if (_Key_Name == "Start") {

_Snake_Body[0].Left = x + 10; //向右偏移x+10
SnakeMove(x, y);
}
if (_Key_Name == "Right") //键盘状态 向右
{
_Snake_Body[0].Left = x + 10; //向右偏移x+10
SnakeMove(x, y);

}
if (_Key_Name == "Up") //键盘状态向上
{
_Snake_Body[0].Top =y -10; //向右偏移y-10
SnakeMove(x, y);
}
if (_Key_Name == "Left")
{
_Snake_Body[0].Left = x - 10; //向右偏移x-10
SnakeMove(x, y);
}
if (_Key_Name == "Down")
{
_Snake_Body[0].Top = y + 10; //向右偏移y+10
SnakeMove(x, y);
}
//穿墙设置
if (x > 800) {

_Snake_Body[0].Left = 0;
}
if (y > 850)
{

_Snake_Body[0].Top = 0;
}
if (x < 0)
{

_Snake_Body[0].Left = 800;
}
if (y < 0)
{

_Snake_Body[0].Top = 840;
}

}

/// <summary>
/// 键盘相应事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormZyd_KeyDown(Object sender, KeyEventArgs e)
{

int x, y;
x = _Snake_Body[0].Left;
y = _Snake_Body[0].Top;
_Key_Name = e.KeyCode.ToString();
//获取键盘代码
if (_Key_Name == "Right") {
_Snake_Body[0].Left = x + 10;
SnakeMove(x, y);
}
if (_Key_Name == "Left")
{
_Snake_Body[0].Left = x - 10;
SnakeMove(x, y);

}
if (_Key_Name == "Up")
{
_Snake_Body[0].Top = y - 10;
SnakeMove(x, y);
}
if (_Key_Name == "Down")
{
_Snake_Body[0].Top = y + 10;
SnakeMove(x, y);
}
//每按一次,判断是否与食物重合
Eat_time();
}

//移动
public void SnakeMove(int x,int y) {
//记录XY中间变量
int Temp_X = 0, Temp_Y = 0;

//蛇身移动
for (int i = 1; _Snake_Body[i] != null; i++)
{
if (i >= 3) {
//将记录每个位置都给中间变量
Temp_X = Snake_Boby_content_x;
Temp_Y = Snake_Boby_content_y;
}

if (i == 1)
{
Temp_X = _Snake_Body[i].Left; //将改变前的位置记录 X
Temp_Y = _Snake_Body[i].Top; //将改变前的位置记录 Y
_Snake_Body[i].Left = x; //并且赋值给第一蛇段
_Snake_Body[i].Top = y;//并且赋值给第一蛇段

}
else {

Snake_Boby_content_x = _Snake_Body[i].Left; //记录蛇段的改变前的位置x
Snake_Boby_content_y = _Snake_Body[i].Top;//记录蛇段的改变前的位置y

_Snake_Body[i].Left = Temp_X; //temp_赋给第二-N个蛇段,
_Snake_Body[i].Top = Temp_Y; //temp_赋给第二-N个蛇段,
}
}}

此处关于KeyDown检测不了方向键问题解决方法如下:

protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Up || keyData == Keys.Down ||

keyData == Keys.Left || keyData == Keys.Right)

return false;
else
return base.ProcessDialogKey(keyData);

}

重写ProcessDialogKey事件,当keyData为方向键时,返回false不执行系统处理,MSDN是这样解释的

在消息预处理过程中调用此方法,以处理对话框字符,比如 Tab、Return、Esc 和箭头键。只有当 IsInputKey 方法指示控件未在处理该键时,才调用此方法。ProcessDialogKey 方法只是将字符发送给父级的 ProcessDialogKey 方法,或者,在该控件没有父级的情况下返回 false。Form 类重写此方法来执行对话框键的实际处理。仅当控件承载在 Windows 窗体应用程序中或充当 ActiveX 控件时,才调用此方法。


蛇的移动事件主要包括:

1.每隔一段时间执行一次的Timer_Tick方法,蛇的自动移动方法既通过判别Key_Name(键盘状态)来确定自动移动的方向,改变Snake_Boby[0](蛇头)的位置,然后Snake_Boby[0]位置改变后再调用Snake_move方法,
Snake_move方法是蛇移动的关键,既根据蛇头位置的改变,对蛇体进行遍历,将蛇头后面每一个元素的位置变为它前一个元素改变之前的位置,实现蛇的移动。
2.Form1_KeyDown方法既当this.KeyDown监控到键盘发生变化时,改变Key_Name(键盘状态)的值,并改变蛇头位置,执行Snake_move。
3.移动事件最后都要执行Eat_time()方法判断是否与食物相遇。
4.食物生成:也是生成一个label控件,并设置大小,text等属性。

public void Snake_food() {

Label Food = new Label
{
Width = 10,
Height =10,
Top = _Random.Next(1, 20) * 20,
Left = _Random.Next(1, 20) * 20,
Text = "❤",
Tag = "Food",
BackColor = Color.White,
ForeColor = Color.Black

};
panel1.Controls.Add(Food);
}

蛇吃食物事件 :

  1. Eat_time方法判别是否和蛇头相遇,如果相遇,调用Snake_eat方法蛇长加一,且改变食物位置
  2. Snake_eat遍历到蛇尾部,生成一个label位置设为蛇尾。
  3. 吃掉一次食物加分,并且

     

/// <summary>
/// 判断是否吃到实物
/// </summary>
public void Eat_time() {

//蛇头部位置

//取得食物的位置
double x1=1 , y1=1 , x2=1 , y2=1;
foreach (Label _Label in this.panel1.Controls) {

if (_Label.Tag.ToString() == "Food".ToString()) { //食物

x2 = _Label.Left;
y2 = _Label.Top;
}
if (_Label.Tag.ToString() == "0".ToString())//Snake
{
x1 = _Label.Left;
y1 = _Label.Top;
}

if (x1 == x2 && y1 == y2) {
MessageBox.Show($"{x1},{y1},{x2},{y2}");
//吃掉食物
Snake_Eat();
score++;
TxtScore.Text=$"共{score}分";
//将食物移位 更换坐标
foreach (Label lb in this.panel1.Controls)
{
if (lb.Tag.ToString() == "Food".ToString())
{
lb.Top = _Random.Next(1, 20) * 20;
lb.Left = _Random.Next(1, 20) * 20;
}
}

}
}
}
/// <summary>
/// 吃掉食物
/// </summary>
public void Snake_Eat() {

int i = 0;
//遍历到蛇尾
for (; _Snake_Body[i] != null; i++) ;
MessageBox.Show(i.ToString());
Label Snake_Boby_content = new Label
{
Width = 10,
Height = 10,
Top = Snake_Boby_content_x, //蛇尾位置X
Left =Snake_Boby_content_y, //蛇尾位置Y
BackColor = Color.Black,
Text= "▉",
Tag=i,
};
_Snake_Body[i] = Snake_Boby_content;
Snake_Boby_content.BackColor = Color.Black;
this.Controls.Add(Snake_Boby_content);

}

开始按钮:

private void Btnstart_Click(object sender, EventArgs e)
{
this.KeyDown += new KeyEventHandler(FormZyd_KeyDown);
timer1.Start() ;
this.KeyPreview = true;
}

暂停按钮:

private void Btnsuspend_Click(object sender, EventArgs e)
{
timer1.Stop();
this.KeyPreview = false;
}

原文地址:https://www.cnblogs.com/dashanboke/p/10598315.html