WPF实现简易贪吃蛇游戏

WPF实现简易贪吃蛇游戏

说到贪吃蛇,想必大家多多少少都玩过,而今天我们就用WPF来亲自做一个贪吃蛇的游戏

实现贪吃蛇游戏的基本过程

1,创建canvas和加载事件

在XAML设计界面中将改为并取名name=“abc”

在window设计界面里面,通过Loaded="Canvas_Loaded"向界面添加加载事件

<Window ……
    ……  Title="MainWindow" Height="450" Width="800" Loaded="Canvas_Loaded">
    <Canvas Name="abc">

2,设置窗体边框和窗体透明度

public MainWindow()
        {
            this.WindowStyle = WindowStyle.None;//窗体的边框样式为无边框
            this.AllowsTransparency = true;//窗体的透明为可以透明

        }

3,在加载事件外创建一系列贪吃蛇中需要用到的控件

Random ra = new Random();//创建随机数
        Border shiwu = new Border();//创建贪吃蛇食物
        Border shiwuer = new Border();//创建贪吃蛇食物二
        Border dushiwu = new Border();//创建贪吃蛇毒食物
        List<Border> snake = new List<Border>();//创建一个集合用来存取蛇身
        List<Border> snakeer = new List<Border>();//再创建一个集合用来存取蛇身二
        DispatcherTimer timer = new DispatcherTimer();//创建一个计时器控制贪吃蛇的移动
        double size = 20;//定义一个数size为20,就是定义一个格子为20个单位
        Label fs = new Label();//创建label控件,用于记录所得分数
        int zj = 0;//定义一个整形zj,设置初始分数为0
        MediaPlayer media = new MediaPlayer();//创建媒体播放器
//定义两个数值,表示屏幕格子数的x和y的大小
        int gzsx = 60;
        int gzsy=40;

4,加载事件

(1),设置窗体的显示大小,透明度以及背景颜色和窗口中canvas的大小

//Window_loaded意思是窗口加载完成以后执行
        private void Canvas_Loaded(object sender, RoutedEventArgs e)
        {
            this.Background = Brushes.Transparent;//窗体的背景颜色完全透明
            this.WindowState = WindowState.Maximized;//窗口最大化,全屏显示
            abc.Background = new RadialGradientBrush(Colors.Red,Colors.Green);//设置显示时的颜色为渐变色
            abc.Opacity = 0.5;//窗体的(不)透明度为0.5
            //canvas的大小和窗体的大小一致
            abc.Width = this.Width;
            abc.Height = this.Height;

(2),计时器的初始频率和创建计时器事件

timer.Interval = TimeSpan.FromMilliseconds(300);//计时器频率设置为FromMilliseconds,每300毫秒移动一下
            timer.Tick += Timer_Tick;//创建timer事件

(3),贪吃蛇游戏开始和暂停按钮的创建

Button ks = new Button();//创建开始按钮,用于控制游戏的开始
            ks.Width = 100;
            ks.Height = 50;
            ks.FontSize = 30; //按钮中字体的大小
            ks.Content = "冲冲冲!";//按钮的文本内容
            //开始按钮在屏幕中的位置
            Canvas.SetLeft(ks, abc.Width-200);
            Canvas.SetTop(ks, abc.Height-700);
            ks.Background = new RadialGradientBrush(Colors.White, Colors.Yellow);//设置按钮的背景颜色为渐变色
            ks.Click += Ks_Click;//创建点击开始按钮触发的事件
            abc.Children.Add(ks);//将开始按钮放到abc(canvas)中

            Button js = new Button();//创建暂停按钮,用于控制游戏的暂停
            js.Width = 100;
            js.Height = 50;
            js.FontSize = 30; //按钮中字体的大小
            js.Content = "停停停!";//按钮的文本内容
            //暂停按钮在屏幕中的位置
            Canvas.SetLeft(js, abc.Width - 200);
            Canvas.SetTop(js, abc.Height - 620);
            js.Background = new RadialGradientBrush(Colors.White, Colors.Yellow);//设置按钮的背景颜色为渐变色
            js.Click += Js_Click;//创建点击暂停按钮触发的事件
            abc.Children.Add(js);//将暂停按钮放到abc(canvas)中
            //设置下拉选项框在屏幕中的位置
            Canvas.SetLeft(xxk, abc.Width - 200);
            Canvas.SetTop(xxk, abc.Height - 460);

(4),贪吃蛇游戏计分的实现

//label控件在总体布局里面
            fs.Width = 100;
            fs.Height = 50;
            fs.Content = "得分;"+zj;//label(fs)的文本内容
            fs.FontSize = 30;//字体
            fs.Background = Brushes.Red;//颜色
            //在屏幕中的位置
            Canvas.SetLeft(fs, abc.Width - 200);
            Canvas.SetTop(fs, abc.Height - 540);
            abc.Children.Add(fs);//label添加到canvas中

(5),创建键盘触发事件

this.KeyDown += MainWindow_KeyDown;//创建键盘触发事件

(6),引用封装方法

 CreateSnake();//引用创建贪吃蛇封装的方法
 CreateSnakeer();//引用创建贪吃蛇二封装的方法
 CreateDouDou();//引用创建食物封装的方法
 CreateDouDouer();//引用创建食物二封装的方法
 CreateDouDoudu();//引用创建毒食物封装的方法
}

5,暂停按钮的触发事件

 private void Js_Click(object sender, RoutedEventArgs e)//暂停按钮事件
        {
          
            timer.Stop();//停止计时器
            
            media.Pause();//停止播放背景音乐
        }

6,开始按钮的触发事件

 private void Ks_Click(object sender, RoutedEventArgs e)//开始按钮事件
        {
            
            media.Open(new Uri("../../yy/fengliange.mp3", UriKind.Relative));//给媒体播放器添加音乐路径
            media.MediaEnded += Media_MediaEnded;//当媒体播放完成时发生事件
            timer.Start();//开启计时器
            
            media.Play();//开始播放音乐
        }

7,媒体播放完成时发生的事件

private void Media_MediaEnded(object sender, EventArgs e)
        {
            //当媒体播放完成时重新进行播放音乐
            media.Position = new TimeSpan(0);
            media.Play();
        }

8,键盘的触发事件

(1),贪吃蛇一snake集合中蛇头tag的改变

 private void MainWindow_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)//键盘事件
            {
                case Key.Up://如果键盘按下的是上
                    snake[0].Tag = "1";//则蛇头的tag改为1
                    break;//终止返回
                case Key.Down://下
                    snake[0].Tag = "2";
                    break;
                case Key.Left://左
                    snake[0].Tag = "3";
                    break;
                case Key.Right://右
                    snake[0].Tag = "4";
                    break;

(2),贪吃蛇二snakeer集合中蛇头tag的改变

 case Key.W://如果键盘按下的是W
                    snakeer[0].Tag = "a";//则蛇头的tag改为a
                    break;//终止返回
                case Key.S:
                    snakeer[0].Tag = "b";
                    break;
                case Key.A:
                    snakeer[0].Tag = "c";
                    break;
                case Key.D:
                    snakeer[0].Tag = "d";
                    break;

            }
        }

9,计时器触发事件

(1),循环遍历控制贪吃蛇一和二上下左右移动

 private void Timer_Tick(object sender, EventArgs e)
        {
            for (int i = 0; i < snake.Count; i++)//for循环遍历snake里面的数组数
            {
                if (snake[i].Tag.ToString() == "3")//如果snake数组的tag等于左(3)的话
                {
                    Canvas.SetLeft(snake[i], Canvas.GetLeft(snake[i]) - size);//则向左移动一个size
                }
                else if (snake[i].Tag.ToString() == "4")//如果snake数组的tag等于右(4)的话
                {
                    Canvas.SetLeft(snake[i], Canvas.GetLeft(snake[i]) + size);//则向右移动一个size
                }
                else if (snake[i].Tag.ToString()=="1")//如果snake数组的tag等于上(1)的话
                {
                    Canvas.SetTop(snake[i], Canvas.GetTop(snake[i]) - size);//则向上移动一个size
                }
                else if (snake[i].Tag.ToString() == "2")//如果snake数组的tag等于下(2)的话
                {
                    Canvas.SetTop(snake[i], Canvas.GetTop(snake[i]) + size);//则向下移动一个size
                }
            }
            for (int i = 0; i < snakeer.Count; i++)
            {
                if (snakeer[i].Tag.ToString() == "c")//如果snakeer数组的tag等于左(c)的话
                {
                    Canvas.SetLeft(snakeer[i], Canvas.GetLeft(snakeer[i]) - size);//则向左移动一个size
                }
                else if (snakeer[i].Tag.ToString() == "d")//如果snakeer数组的tag等于右(d)的话
                {
                    Canvas.SetLeft(snakeer[i], Canvas.GetLeft(snakeer[i]) + size);//则向右移动一个size
                }
                else if (snakeer[i].Tag.ToString() == "a")//如果snakeer数组的tag等于上(a)的话
                {
                    Canvas.SetTop(snakeer[i], Canvas.GetTop(snakeer[i]) - size);//则向上移动一个size
                }
                else if (snakeer[i].Tag.ToString() == "b")//如果snakeer数组的tag等于下(b)的话
                {
                    Canvas.SetTop(snakeer[i], Canvas.GetTop(snakeer[i]) + size);//则向下移动一个size
                }
            }

(2),循环遍历控制贪吃蛇一和二的蛇身tag随蛇头tag的改变而改变

 for (int i = snake.Count - 1; i > 0; i--)//for循环遍历snake里面的数组数,倒着遍历
            {
                snake[i].Tag = snake[i - 1].Tag;//把上一个tag的值赋给现在这个tag,由此类推,一给二,二给三,三给四.所以四个tag随着蛇头tag的变化而变化
            }
            for (int i = snakeer.Count - 1; i > 0; i--)//第二条蛇和上一条一样
            {
                snakeer[i].Tag = snakeer[i - 1].Tag;
            }

(3),当贪吃蛇一蛇头吃到食物一时

//食物一
            if (Canvas.GetLeft(snake[0]) == Canvas.GetLeft(shiwu) && Canvas.GetTop(snake[0]) == Canvas.GetTop(shiwu))//如果蛇头的left和食物的left一样并且top也一样的话
            {
                //MessageBox.Show("123");测试
                //那么原先的食物消失,蛇头和食物接触时,食物将重新进行随机定位
                Canvas.SetLeft(shiwu, ra.Next(gzsx) * size);
                Canvas.SetTop(shiwu, ra.Next(gzsy) * size);
                zj += 1;//消失一次得分加一
                fs.Content = "得分;" + zj;//label也随之改变
                //吃一口长一节
                Border newbrd = new Border();//创建一个border
                //大小颜色tag和蛇头一模一样
                newbrd.Width = newbrd.Height = size;
                newbrd.Background = Brushes.Blue;
                newbrd.Tag = "4";
                newbrd.CornerRadius = new CornerRadius(20);
                //并且让他跟在贪吃蛇的后面
                //实现吃一节长一节
                Canvas.SetLeft(newbrd, Canvas.GetLeft(snake[snake.Count - 1]) - size);
                Canvas.SetTop(newbrd, Canvas.GetTop(snake[snake.Count - 1]));
                abc.Children.Add(newbrd);//把创建的border放在canvas(abc)中
                snake.Add(newbrd);//把创建的border存入集合snake中
            }

(4),当贪吃蛇二蛇头吃到食物二时

//食物二与食物一一致,只需要改一下命名
            if (Canvas.GetLeft(snakeer[0]) == Canvas.GetLeft(shiwuer) && Canvas.GetTop(snakeer[0]) == Canvas.GetTop(shiwuer))
            {
                Canvas.SetLeft(shiwuer, ra.Next(gzsx) * size);
                Canvas.SetTop(shiwuer, ra.Next(gzsy) * size);
                zj += 1;
                fs.Content = "得分;" + zj;
                //吃一口长一节
                Border newbrder = new Border();
                newbrder.Width = newbrder.Height = size;
                newbrder.Background = Brushes.White;
                newbrder.Tag = "d";
                newbrder.CornerRadius = new CornerRadius(20);
                Canvas.SetLeft(newbrder, Canvas.GetLeft(snakeer[snakeer.Count - 1]) - size);
                Canvas.SetTop(newbrder, Canvas.GetTop(snakeer[snakeer.Count - 1]));
                abc.Children.Add(newbrder);
                snakeer.Add(newbrder);
            }

(5),当贪吃蛇一和二蛇头吃到毒食物时

//第一个蛇吃毒食物
            if (Canvas.GetLeft(snake[0]) == Canvas.GetLeft(dushiwu) && Canvas.GetTop(snake[0]) == Canvas.GetTop(dushiwu))//如果蛇头的left和毒食物的left一样并且top也一样的话
            {
                //那么原先的毒食物消失,蛇头和毒食物接触时,毒食物将重新进行随机定位
                Canvas.SetLeft(dushiwu, ra.Next(gzsx) * size);
                Canvas.SetTop(dushiwu, ra.Next(gzsy) * size);
                zj -= 1;//吃一口减一分
                fs.Content = "得分;" + zj;//label也随之改变
                //吃一口少一节
                //蛇吃毒食物以后,最后一个索引不显示,但是保留控件,然后将控件移除集合snake,真正做到蛇吃一个毒食物以后减到一个蛇身
                snake[snake.Count - 1].Visibility = Visibility.Collapsed;
                snake.RemoveAt(snake.Count - 1);
            }
            //第二个蛇吃毒食物和上一个基本一致,改一下命名就好
            if (Canvas.GetLeft(snakeer[0]) == Canvas.GetLeft(dushiwu) && Canvas.GetTop(snakeer[0]) == Canvas.GetTop(dushiwu))
            {
                Canvas.SetLeft(dushiwu, ra.Next(gzsx) * size);
                Canvas.SetTop(dushiwu, ra.Next(gzsy) * size);
                zj -= 1;
                fs.Content = "得分;" + zj;
                //吃一口少一节
                snakeer[snakeer.Count - 1].Visibility = Visibility.Collapsed;
                snakeer.RemoveAt(snakeer.Count - 1);
            }

(6),碰撞事件

<1>,碰撞墙壁
//当贪吃蛇蛇头与墙壁(屏幕)碰撞到的时候
            if (Canvas.GetLeft(snake[0])+size >= abc.Width|| Canvas.GetLeft(snake[0]) <= 0|| Canvas.GetTop(snake[0]) >= abc.Height|| Canvas.GetTop(snake[0]) <= 0)
            {
                zj = 0;//得分归零
                fs.Content = "得分;" + zj;
                zhunagqiang();//引用封装撞墙方法
            }
            //贪吃蛇二也是一样
            if (Canvas.GetLeft(snakeer[0]) + size >= abc.Width || Canvas.GetLeft(snakeer[0]) <= 0 || Canvas.GetTop(snakeer[0]) >= abc.Height || Canvas.GetTop(snakeer[0]) <= 0)
            {
                zj = 0;
                fs.Content = "得分;" + zj;
                zhunagqiang();
            }
<2>,吃到自己
for (int i = 1; i < snake.Count; i++)//for循环遍历snake中的数量
            {
                //如果蛇头的left和top和蛇身一致
                if (Canvas.GetLeft(snake[0])==Canvas.GetLeft(snake[i])&& Canvas.GetTop(snake[0]) == Canvas.GetTop(snake[i]))
                {
                    zj = 0;//那么得分归零
                    fs.Content = "得分;" + zj;
                    czj();//引用封装自食方法
                }
            }
            //贪吃蛇集合二与贪吃蛇集合一一样
            for (int i = 1; i < snakeer.Count; i++)
            {
                if (Canvas.GetLeft(snakeer[0]) == Canvas.GetLeft(snakeer[i]) && Canvas.GetTop(snakeer[0]) == Canvas.GetTop(snakeer[i]))
                {
                    zj = 0;
                    fs.Content = "得分;" + zj;
                    czj();
                }
            }

        }

10,贪吃蛇撞墙以后的封装方法

 private void zhunagqiang()//封装撞墙方法
        {
            timer.Stop();//停止计时器
            abc.Children.Clear();//移除所有元素控件
            //撞墙以后出现提示框让其选择yes或者No
            MessageBoxResult xz = MessageBox.Show("小伙子,你还太年轻,要不要再来一次?","提示;你输啦!", MessageBoxButton.YesNo,MessageBoxImage.Hand);
            if(xz==MessageBoxResult.Yes)//如果选择的是yes
            {
                //那么一切重新开始
                timer.Start();
                snake.Clear();
                snakeer.Clear();
                CreateSnake();//引用创建贪吃蛇封装的方法
                CreateSnakeer();//引用创建贪吃蛇二封装的方法
                CreateDouDou();//引用创建食物封装的方法
                CreateDouDouer();//引用创建食物二封装的方法
                CreateDouDoudu();//引用创建毒食物封装的方法
            }
            else//否则
            {
                this.Close();//关闭游戏
            }
        }

11,贪吃蛇自食(吃到自己)以后的封装方法

private void czj()//封装自食方法
        {
            timer.Stop();//停止计时器
            abc.Children.Clear();//移除所有元素控件
            //自食以后出现提示框让其选择yes或者No
            MessageBoxResult xz = MessageBox.Show("小伙子,电子游戏,菜便是原罪!", "提示;你终究还是输啦!", MessageBoxButton.YesNo, MessageBoxImage.Hand);
            if (xz == MessageBoxResult.Yes)//如果选择的是yes
            {
                //那么一切重新开始
                timer.Start();
                snake.Clear();
                snakeer.Clear();
                CreateSnake();//引用创建贪吃蛇封装的方法
                CreateSnakeer();//引用创建贪吃蛇二封装的方法
                CreateDouDou();//引用创建食物封装的方法
                CreateDouDouer();//引用创建食物二封装的方法
                CreateDouDoudu();//引用创建毒食物封装的方法
            }
            else//否则
            {
                this.Close();//关闭游戏
            }
        }

12,贪吃蛇的创建

private void CreateSnake()//创建贪吃蛇封装的方法
        {
            for (int i = 0; i < 4; i++)//for循环四次,贪吃蛇四节
            {
                Border brd = new Border();//创建一个新的控件
                brd.Background = Brushes.Red;//设置控件的颜色
                                             //设置控件的宽和高
                brd.Width = size;
                brd.Height = size;
                brd.Tag = "4";//最开始移动方向为右(4)
                if (i == 0)//如果i=0时
                {
                    brd.Background = Brushes.Yellow;//那么该小节的颜色为黄色
                }
                else//否则
                {
                    brd.Background = Brushes.Blue;//小节的颜色为绿色
                }
                Canvas.SetLeft(brd, (gzsx/2)*size- i * size);//设置贪吃蛇的四节的位置和高度
                Canvas.SetTop(brd, (gzsy/2)*size);
                brd.CornerRadius = new CornerRadius(20);//画圆
                abc.Children.Add(brd);//将创建的贪吃蛇添加到ABC就是canvas中去
                snake.Add(brd);//将创建的贪吃蛇添加到snake集合中去
            }
        }
        private void CreateSnakeer()//创建贪吃蛇二封装的方法
        {
            for (int i = 0; i < 4; i++)//for循环四次,贪吃蛇四节
            {
                Border brder = new Border();//创建一个新的控件
                brder.Background = Brushes.Black;//设置控件的颜色
                                             //设置控件的宽和高
                brder.Width = size;
                brder.Height = size;
                brder.Tag = "d";//最开始移动方向为右(d)
                if (i == 0)//如果i=0时
                {
                    brder.Background = Brushes.Black;//那么该小节的颜色为黑色
                }
                else//否则
                {
                    brder.Background = Brushes.White;//小节的颜色为白色
                }
                Canvas.SetLeft(brder, (gzsx / 2) * size - i * size-size*3);//设置贪吃蛇二的四节的位置和高度
                Canvas.SetTop(brder, (gzsy / 2) * size-size*5);
                brder.CornerRadius = new CornerRadius(20);//画圆
                abc.Children.Add(brder);//将创建的贪吃蛇二添加到ABC就是canvas中去
                snakeer.Add(brder);//将创建的贪吃蛇二添加到snake集合中去
            }
        }

13,食物的创建

private void CreateDouDou() //创建食物封装的方法
        {
            
                shiwu.Width = shiwu.Height = size;//设置食物的大小和贪吃蛇的蛇头一样大
                shiwu.Background = new RadialGradientBrush(Colors.Red, Colors.Pink);//设置食物的颜色为渐变色
                shiwu.CornerRadius = new CornerRadius(20);//食物半径为20
                 //食物的随机定位
                Canvas.SetLeft(shiwu, ra.Next(gzsx) * size);
                Canvas.SetTop(shiwu, ra.Next(gzsy) * size);
                abc.Children.Add(shiwu);//将食物添加到canvas中去
        }
        private void CreateDouDouer()//创建食物二封装的方法
        {
            shiwuer.Width = shiwuer.Height = size;
            shiwuer.Background = new RadialGradientBrush(Colors.Blue, Colors.Pink);
            shiwuer.CornerRadius = new CornerRadius(20);
            Canvas.SetLeft(shiwuer, ra.Next(gzsx) * size);
            Canvas.SetTop(shiwuer, ra.Next(gzsy) * size);
            abc.Children.Add(shiwuer);
        }
        //毒食物
        private void CreateDouDoudu()//创建毒食物封装的方法
        {
            dushiwu.Width = dushiwu.Height = size;
            dushiwu.Background = Brushes.Brown;
            dushiwu.CornerRadius = new CornerRadius(20);//毒食物半径为20
                                                      //毒食物的随机定位
            Canvas.SetLeft(dushiwu, ra.Next(gzsx) * size);
            Canvas.SetTop(dushiwu, ra.Next(gzsy) * size);
            abc.Children.Add(dushiwu);//将毒食物添加到canvas中去
        }

14,下拉列表框的创建,关卡的选择

(1),在设计界面工具箱中选择combobox,移到canvas中

在这里插入图片描述
在这里插入图片描述

(2),打开combobox的属性窗口,找到items集合,并为combobox取一个名字

在这里插入图片描述
在这里插入图片描述

(3),点卡添加comboboxitem,并且为添加的comboboxitem写上名字

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(4),点击combobox事件找到selectionchanged,双击后面选项框

在这里插入图片描述

(5),在combobox事件中写关卡条件

 private void xxk_SelectionChanged(object sender, SelectionChangedEventArgs e)//下拉列表框的触发事件
        {
            if (xxk.Text=="黄金")//当下拉列表中的文本内容为黄金时
            {
                timer.Interval = TimeSpan.FromMilliseconds(200);//计时器的频率加快
            }
            if (xxk.Text == "砖石")//当下拉列表中的文本内容为砖石时
            {
                timer.Interval = TimeSpan.FromMilliseconds(100);//计时器的频率加快
            }
            if (xxk.Text == "王者")//当下拉列表中的文本内容为王者时
            {
                timer.Interval = TimeSpan.FromMilliseconds(30);//计时器的频率加快
            }
        }

猜你喜欢

转载自blog.csdn.net/XVJINHUA954/article/details/106481997