WPF砖块消除

2 篇文章 0 订阅

WPF的砖块消除,基本实现砖块消除公共

  • 实现效果:

初始界面
砖块初始化
在这里插入图片描述
在这里插入图片描述
消灭成功提示

  • 使用方式:
    第一步:设置砖块数量
    第二步:点击刷新界面
    第三步:按住键盘的 “A” 或点击 “启动”按钮启动游戏
    移动方式:在橘黄色区域按住鼠标左键即可移动挡板,或者移动挡板左右坐标即可

  • 前台代码:

<Window x:Class="打砖块.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:打砖块"
        mc:Ignorable="d"
        Title="打砖块V0.0.1" Height="600" Width="600"  MinHeight="600" MinWidth="600" Loaded="Window_Loaded" Closing="Window_Closing" SizeChanged="Window_SizeChanged" >
    <Window.Resources>
        <RoutedUICommand x:Key="Start_Game" Text="Start game" />
    </Window.Resources>
    <Window.InputBindings>
        <KeyBinding Key="A" Command="{StaticResource Start_Game}"/>
    </Window.InputBindings>
    <Window.CommandBindings>
        <CommandBinding x:Name="cb_start_game" Command="{StaticResource Start_Game}" CanExecute="cb_start_game_CanExecute" Executed="cb_start_game_Executed"/>
    </Window.CommandBindings>
    <Grid x:Name="gd_min">
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF3B41CF" Offset="0"/>
                <GradientStop Color="#FFB82274" Offset="0.992"/>
                <GradientStop Color="#FF4A4A4A" Offset="0.229"/>
                <GradientStop Color="#FF7AD65E" Offset="0.562"/>
            </LinearGradientBrush>
        </Grid.Background>
        <Grid.RowDefinitions>
            <RowDefinition Height="80"/>
            <RowDefinition Height="9*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="210"/>
        </Grid.ColumnDefinitions>

        <Grid Grid.Row="0" Grid.Column="0">
            <Grid.RowDefinitions >
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition Width="0.1*"/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Label Grid.Row="0" Grid.Column="0" Content="砖块总数:" Foreground="Azure"/>
            <Label Grid.Row="1" Grid.Column="0" Content="已消除总数:" Foreground="Azure"/>
            <Label Grid.Row="2" Grid.Column="0" Content="当前用时:" Foreground="Azure"/>
            <Label x:Name="lb_brick_count" Grid.Row="0" Grid.Column="1" Content="-" Foreground="Azure"/>
            <Label x:Name="lb_re_count" Grid.Row="1" Grid.Column="1" Content="-" Foreground="Azure"/>
            <Label x:Name="lb_time" Grid.Row="2" Grid.Column="1" Content="-" Foreground="Azure"/>

            <Label Grid.Row="0" Grid.Column="3" Content="剩余砖块:" Foreground="Azure"/>
            <Label Grid.Row="1" Grid.Column="3" Content="弹起数:" Foreground="Azure"/>
            <Label Grid.Row="2" Grid.Column="3" Content="-" Foreground="Azure"/>
            <Label x:Name="lb_lost_count" Grid.Row="0" Grid.Column="4" Content="-" Foreground="Azure"/>
            <Label x:Name="lb_run_stpe" Grid.Row="1" Grid.Column="4" Content="-" Foreground="Azure"/>
            <Label  Grid.Row="2" Grid.Column="4" Content="-" Foreground="Azure"/>

        </Grid>
        <TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"  TextWrapping="Wrap"  Text="第①步:设置砖块数量和小球速度&#13;第②步:点击刷新界面生成砖块&#13;第③步:点击启动(或单击“a”开始)开始消除砖块&#13;移动方式:按住鼠标左键即可移动挡板" Foreground="Red" Grid.ColumnSpan="2" />
        <Grid Grid.Row="1" Grid.Column="0" Background="BlanchedAlmond"  MouseMove="gd_ball_MouseMove">
            <Grid.RowDefinitions>
                <RowDefinition Height="2*"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20"/>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="20"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="20"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid Grid.Row="1" Grid.Column="1" x:Name="gd_table" Background="AliceBlue"/>
            </Grid>
        </Grid>
        <Grid Grid.Row="1" Grid.Column="0" x:Name="gd_ball" Background="{x:Null}" >
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="10"/>
            </Grid.RowDefinitions>
            <Ellipse x:Name="ep_boll" Grid.Row="0"  Grid.RowSpan="3" Width="10" Height="10"  VerticalAlignment="Bottom" HorizontalAlignment="Center">
                <Ellipse.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FFF7642C" Offset="0"/>
                        <GradientStop Color="#FF4058A8" Offset="1"/>
                        <GradientStop Color="#FFA66147" Offset="0.402"/>
                        <GradientStop Color="#FF6E4739" Offset="0.546"/>
                    </LinearGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
            <Rectangle Visibility="Collapsed" x:Name="rt_wb"  Grid.Row="1" Width="100" Height="10" VerticalAlignment="Bottom" HorizontalAlignment="Center"
                       RadiusY="5" RadiusX="5">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF787878" Offset="0"/>
                        <GradientStop Color="Black" Offset="1"/>
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>

            <Rectangle Grid.Row="1" x:Name="rt_rect" Height="10" Width="100" Fill="#CCCD2C2C"/>

        </Grid>

        <Grid Grid.Row="1" Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="100"/>
                <RowDefinition/>
                <RowDefinition Height="40"/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0" Orientation="Vertical" Background="Aqua">

                <Label Content="球坐标:"/>
                <Label Name="lb_ball_addr" Content="0:0" HorizontalAlignment="Center"/>
                <Label Content="距离:"/>
                <Label Name="lb_leng" Content="-" HorizontalAlignment="Center" />

            </StackPanel>
            <StackPanel Grid.Row="1" VerticalAlignment="Center">
                <Label Content="砖块数量:"/>
                <Slider Margin="2" Width="50" x:Name="sd_brick_num" MinWidth="150" IsSnapToTickEnabled="True" Minimum="10" Maximum="500" Value="40"  Orientation="Horizontal"/>
                <Label Content="{Binding Path=Value,ElementName=sd_brick_num}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <Label Content="速度比:"/>
                <Slider Margin="2" Width="50" x:Name="sd_bool_speed" MinWidth="150" IsSnapToTickEnabled="True" Minimum="0" Maximum="50" Value="45"  Orientation="Horizontal"  ValueChanged="sd_bool_speed_ValueChanged"/>
                <Label Content="{Binding Path=Value,ElementName=sd_bool_speed}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <Button x:Name="bt_crt"  Margin="3" Height="40" Content="刷新界面" Click="bt_crt_Click"/>
                <Button Content="启动"  Margin="3" Height="40" x:Name="bt_start" Click="bt_start_Click"/>
                <Label Content="挡板中心坐标:"/>
                <Slider Margin="2" Width="50" x:Name="sd_x" MinWidth="150" ValueChanged="sd_x_ValueChanged" IsSnapToTickEnabled="True" Minimum="-200" Maximum="200" Value="0"  Orientation="Horizontal"/>
                <Label Content="{Binding Path=Value,ElementName=sd_x}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </StackPanel>
            <TextBlock Grid.Row="2" Text="Power By Bilibili-火狐鞥&#13;2021-01-14" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" FontSize="15"  Foreground="Gray"/>
        </Grid>
        
    </Grid>
</Window>

  • 后台代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace 打砖块
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.ep_boll.RenderTransform=new TranslateTransform();
            this.rt_rect.RenderTransform=new TranslateTransform();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            timer_init();
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
            Max_leng = Math.Sqrt(Math.Pow(rect_info.Width / 2, 2) + Math.Pow(rect_info.Height / 2, 2)) + ball_info.Radius;
            sd_x.Maximum = gd_ball.ActualWidth / 2;
            sd_x.Minimum = -gd_ball.ActualWidth / 2;
        }

        #region 申明类

        public struct Ball
        {
            public Point Addr;  //位置
            public Point Speed; //运行速度
            public Point Dir; //运行方向
            public int Radius; //球半径
        }
        //public struct Rect
        //{
        //    public Point Addr;  //位置
        //    public double Width;
        //    public double Height;
        //    public int Stat;
        //}
        public class Rect
        {
            private Point _addr = new Point(0, 0);
            private double _width = 0;
            private double _height = 0;
            private int _stat = 0;
            private int _index = 0;

            public Point Addr
            {
                set { _addr = value; }
                get { return _addr; }
            }

            public double Width
            {
                set { _width = value; }
                get { return _width; }
            }

            public double Height
            {
                set { _height = value; }
                get { return _height; }
            }

            public int Stat
            {
                set { _stat = value; }
                get { return _stat; }
            }

            public int Index
            {
                set { _index = value; }
                get { return _index; }
            }
        }
        #endregion

        #region///全局变量
        private ProcessCount processCount;//统计运行时间
        private int brick_run_stpe = 0; //运行步数
        private int re_brick_count = 0;
        private Ball ball_info = new Ball() { Addr = new Point(0, -10), Speed = new Point(0, 0), Dir = new Point(0, -1), Radius = 5 };
        private Rect rect_info = new Rect() { Addr = new Point(0, 0), Height = 10, Width = 100, Stat = 99 };
        private List<Rect> brick_list = new List<Rect>();//砖块列表
        private Point brick_info = new Point(20, 18); //生成砖的大小
        private int brick_num = 40; //生成砖的数量
        private List<int> brick_addr = new List<int>();
        double Max_leng = 0;
        #endregion

        #region 定时器

        MillisecondTimer aTimer;
        private int timer_count=0;
        void timer_init()
        {
 
            aTimer = new MillisecondTimer();
            aTimer.Tick += timedo; ;
            aTimer.Interval = 1; //每秒执行
            processCount = new ProcessCount(0);
            //aTimer.Start();
            aTimer.Stop();
        }

        
        private void timedo(object sender, EventArgs e) //定时中断
        {
            this.Dispatcher.Invoke(new Action(delegate
            {
                ball_move();
                timer_count++;
                if (timer_count > 1000)
                {
                    timer_count = 0;
                    processCount.ProcessCountUp();
                    lb_time.Content = processCount.GetHour() + ":" + processCount.GetMinute() + ":" + processCount.GetSecond();
                }
                
            }));
        }
        #endregion


       

        #region //功能函数

       [DllImport("kernel32.dll")]
        private static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);

        /// <summary>
        /// 内存回收
        /// </summary>
        private void ClearMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }


        /// <summary>
        /// 产生指定随机数 且不重复
        /// </summary>
        /// <param name="Number">产生随机数个数</param>
        /// <param name="minNum">最小值</param>
        /// <param name="maxNum">最大值</param>
        /// <returns></returns>
        public List<int> GetRandomArray(int Number, int minNum, int maxNum)
        {
            int j;
            int[] b = new int[Number];
            List<int> buf = new List<int>();
            Random r = new Random();

            while (buf.Count < Number)
            {
                int i = r.Next(minNum, maxNum);
                int num = 0;
                for (int k = 0; k < buf.Count; k++) //判断是否和以前的数据重复
                {
                    if (buf[k] == i)   //新生成的数据和原来的数据重复
                    {
                        num = num + 1;
                        break;
                    }
                }
                if (num == 0)
                {
                    //b[j] = i;
                    buf.Add(i);
                }
            }
            //for (j = 0; j < Number; j++)
            //{
            //    int i = r.Next(minNum, maxNum + 1);
            //    int num = 0;
            //    for (int k = 0; k < j; k++) //判断是否和以前的数据重复
            //    {
            //        if (b[k] == i)   //新生成的数据和原来的数据重复
            //        {
            //            num = num + 1;
            //        }
            //    }
            //    if (num == 0)
            //    {
            //        b[j] = i;
            //    }
            //    else
            //    {
            //        j = j - 1;
            //    }
            //}
            //Array.Sort(buf);
            buf.Sort();
            return buf;
        }

        /// <summary>
        /// WPF控件查找
        /// </summary>
        /// <typeparam name="T">空间类型</typeparam>
        /// <param name="parent">父控件</param>
        /// <param name="childName">查找空间名称</param>
        /// <returns></returns>
        public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
        {
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // 如果bai子控件不是需查找的控件类型
                T childType = child as T;
                if (childType == null)
                {
                    // 在下一级控件中递归查找
                    foundChild = FindChild<T>(child, childName);

                    // 找到控件就可以中断递归操作 
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // 如果控件名称符合参数条件
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        foundChild = (T)child;
                        break;
                    }
                }
                else
                {
                    // 查找到了控件
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }

        #endregion
        
        #region ///界面刷新
        private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            TranslateTransform bool_translate = (TranslateTransform)ep_boll.RenderTransform;
            TranslateTransform rect_translate = (TranslateTransform)rt_rect.RenderTransform;
            bool_translate.X = ball_info.Addr.X;
            bool_translate.Y = ball_info.Addr.Y;
            rect_translate.X = rect_info.Addr.X;
            rect_translate.Y = rect_info.Addr.Y;
            lb_ball_addr.Content = ball_info.Addr.X.ToString("0.00") + ":" + ball_info.Addr.Y.ToString("0.00");
            lb_leng.Content=check_leng(rect_info, ball_info)[1].ToString("0.00");
        }

        #endregion

        #region ///核心算法

        /// <summary>
        /// 获取距离最近的点的距离
        /// </summary>
        /// <param name="p">矩形信息</param>
        /// <param name="b">圆信息</param>
        /// <returns>
        ///     re[0]  -1 错误(内部) 0 X轴方向距离最短 1 Y轴距离最短
        ///     re[1]  -1 错误  其他:最短距离
        /// </returns>
        private double[] check_leng(Rect p, Ball b)
        {
            double leng = Math.Sqrt(Math.Pow(p.Addr.X - b.Addr.X, 2) + Math.Pow(p.Addr.Y - b.Addr.Y, 2));
            double max_len = Math.Sqrt(Math.Pow(p.Width / 2, 2) + Math.Pow(p.Height / 2, 2)) + b.Radius;
            double min_len = Math.Min(Math.Min(p.Height / 2, p.Width / 2), b.Radius);
            double min_x = -1;
            double min_y = -1;
            double min_1 = -1;
            double min_2 = -1;
            double min_3 = -1;
            double min_4 = -1;
            double[] re = new double[2];
            re[0] = -1;
            re[1] = -1;
            if (leng < min_len) //小于最小距离,两物体相交 或位于内部
            {
                //逻辑上不允许出现此种情况
                return re;
            }
            else
            {
                //根据中心坐标位置确定需要判断的边界(有可能交互的边界)
                if ((b.Addr.X >= p.Addr.X - p.Width / 2 + b.Radius) && (b.Addr.X <= p.Addr.X + p.Width / 2 - b.Radius))  //位于Y轴方向区域类 
                {
                    if (b.Addr.Y <= p.Addr.Y - p.Height / 2 - b.Radius) //圆心位于矩形的下边沿
                    {
                        min_y = Math.Abs(b.Addr.Y + b.Radius - (p.Addr.Y - p.Height / 2));
                    }
                    else if (b.Addr.Y >= p.Addr.Y + p.Height / 2 + b.Radius) //圆心位于的上边沿
                    {
                        min_y = Math.Abs(b.Addr.Y - b.Radius - (p.Addr.Y + p.Height / 2));

                    }
                    else //圆心位于矩形内
                    {

                        min_y = -1;
                    }
                    re[0] = 1;
                    re[1] = min_y;
                    return re;
                }
                else if ((b.Addr.Y >= p.Addr.Y - p.Height / 2 + b.Radius) && (b.Addr.Y <= p.Addr.Y + p.Height / 2 - b.Radius))//位于矩形X轴方向区域类 
                {
                    if (b.Addr.X <= p.Addr.X - p.Width / 2 - b.Radius) //圆心位于矩形的左边沿
                    {
                        min_x = Math.Abs(b.Addr.X + b.Radius - (p.Addr.X - p.Width / 2));
                    }
                    else if (b.Addr.X >= p.Addr.X + p.Width / 2 + b.Radius) //圆心位于矩形的右边沿
                    {
                        min_x = Math.Abs(b.Addr.X - b.Radius - (p.Addr.X + p.Width / 2));
                    }
                    else  //圆心位于矩形内
                    {
                        min_x = -1;
                    }
                    re[0] = 0;
                    re[1] = min_x;
                    return re;
                }
                else if ((b.Addr.X <= p.Addr.X - p.Width / 2 + b.Radius) && (b.Addr.Y <= p.Addr.Y - p.Height / 2 + b.Radius)) //第四象域
                {
                    for (int rad_t = 270; rad_t <= 360; rad_t++)
                    {
                        double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
                        double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180);  //算出球边沿的坐标
                        double m = p.Addr.X - p.Width / 2;
                        double n = p.Addr.Y - p.Height / 2;
                        double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
                        re[0] = 1;
                        if (b.Addr.X > m)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(y - n));
                            re[0] = 1;

                        }
                        else if (b.Addr.Y > n)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(x - m));
                            re[0] = 1;
                        }
                        if (min_4 != -1)
                        {
                            if ((x > p.Addr.X - p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
                            {
                                min_4 = -1;
                                break;
                            }
                            else
                            {
                                if (mint_t < min_4)
                                {
                                    min_4 = mint_t;
                                }
                            }

                        }
                        else
                        {
                            if ((x > p.Addr.X - p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
                            {
                                min_4 = -1;
                                break;
                            }
                            else
                            {
                                min_4 = mint_t;
                            }

                        }
                    }
                    
                    re[1] = min_4;
                    return re;
                    //return min_4;
                }
                else if ((b.Addr.X > p.Addr.X + p.Width / 2 - b.Radius) && (b.Addr.Y <= p.Addr.Y - p.Height / 2 + b.Radius)) //第三象域
                {

                    for (int rad_t = 180; rad_t <= 270; rad_t++)
                    {
                        double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
                        double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180);  //算出球边沿的坐标
                        double m = p.Addr.X + p.Width / 2;
                        double n = p.Addr.Y - p.Height / 2;
                        double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
                        re[0] = 1;
                        if (b.Addr.X < m)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(y - n));
                            re[0] = 1;
                        }
                        else if (b.Addr.Y > n)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(x - m));
                            re[0] = 0;
                        }
                        //double mint_t = Math.Sqrt(Math.Pow(p.Addr.X + p.Width / 2 - x, 2) + Math.Pow(p.Addr.Y - p.Height / 2 - y, 2));
                        if (min_3 != -1)
                        {
                            if ((x < p.Addr.X + p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
                            {
                                min_3 = -1;
                                break;
                            }
                            else

                            if (mint_t < min_3)
                            {
                                min_3 = mint_t;
                            }
                        }
                        else
                        {
                            if ((x < p.Addr.X + p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
                            {
                                min_3 = -1;
                                break;
                            }
                            else
                            {

                            }
                            min_3 = mint_t;
                        }
                    }
                    re[1] = min_3;
                    return re;
                    //return min_3;
                }
                else if ((b.Addr.X > p.Addr.X + p.Width / 2 - b.Radius) && (b.Addr.Y > p.Addr.Y + p.Height / 2 - b.Radius))//第二象域
                {
                    for (int rad_t = 90; rad_t <= 180; rad_t++)
                    {
                        double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
                        double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180);  //算出球边沿的坐标
                        double m = p.Addr.X + p.Width / 2;
                        double n = p.Addr.Y + p.Height / 2;
                        double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
                        re[0] = 0;
                        if (b.Addr.X < m)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(y - n));
                            re[0] = 1;
                        }
                        else if (b.Addr.Y < n)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(x - m));
                            re[0] = 0;
                        }
                        if (min_2 != -1)
                        {
                            if ((x < p.Addr.X + p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
                            {
                                min_2 = -1;
                                break;
                            }
                            else
                            {
                                if (mint_t < min_2)
                                {
                                    min_2 = mint_t;
                                }
                            }

                        }
                        else
                        {
                            if ((x < p.Addr.X + p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
                            {
                                min_2 = -1;
                                break;
                            }
                            else
                            {
                                min_2 = mint_t;
                            }
                        }
                    }
                    re[1] = min_2;
                    return re;
                    
                }
                else if ((b.Addr.X <= p.Addr.X - p.Width / 2 + b.Radius) && (b.Addr.Y > p.Addr.Y + p.Height / 2 - b.Radius)) //第一象域
                {

                    for (int rad_t = 0; rad_t <= 90; rad_t++)
                    {
                        double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
                        double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180);  //算出球边沿的坐标
                        double m = p.Addr.X - p.Width / 2;
                        double n = p.Addr.Y + p.Height / 2;
                        double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
                        re[0] = 0;
                        if (b.Addr.X > m)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(y - n));
                            re[0] = 1;
                        }
                        else if (b.Addr.Y < n)
                        {
                            mint_t = Math.Min(mint_t, Math.Abs(x - m));
                            re[0] = 0;
                        }

                        if (min_1 != -1)
                        {
                            if ((x > p.Addr.X - p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
                            {
                                min_1 = -1;
                                break;
                            }
                            else
                            {
                                if (mint_t < min_1)
                                {
                                    min_1 = mint_t;
                                }
                            }
                        }
                        else
                        {
                            if ((x > p.Addr.X - p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
                            {
                                min_1 = -1;
                                break;
                            }
                            else
                            {
                                min_1 = mint_t;
                            }

                        }
                    }
                    re[1] = min_1;
                    return re;
                }
                return re;
                //return -98;
            }

        }


        private double wb_val = 0;
        private int time_count = 0;
      
        /// <summary>
        /// 球体移动判断
        /// </summary>
        private void ball_move()
        {
            try
            {
                time_count++;

                double max_x = (gd_ball.ActualWidth - ep_boll.ActualWidth) / 2;
                double max_y = gd_ball.ActualHeight - ep_boll.ActualHeight;
                
                wb_val = rect_info.Addr.X;

                if (time_count >= 20)
                {
                    time_count = 0;
                }

                if ((int)(51 - ball_info.Speed.X) != 0 && ball_info.Speed.X != 0)
                {
                    if (time_count % ((int)(51 - ball_info.Speed.X)) == 0)
                    {
                        ball_info.Addr.X += ball_info.Dir.X;
                    }
                }
                
                if ((int)(51 - ball_info.Speed.Y) != 0 && ball_info.Speed.Y != 0)
                {
                    if (time_count % ((int)(51 - ball_info.Speed.Y)) == 0)
                    {
                        ball_info.Addr.Y += ball_info.Dir.Y;
                    }

                }
               
                if (ball_info.Addr.X >= (max_x))
                {
                    ball_info.Dir.X = -1;
                    ball_info.Addr.X = max_x;
                }
                else if (ball_info.Addr.X <= -max_x)
                {
                    ball_info.Dir.X = 1;
                    ball_info.Addr.X = -max_x;
                }

                if (ball_info.Addr.Y <= (-max_y))
                {
                    ball_info.Dir.Y = 1;
                    ball_info.Addr.Y = -max_y;
                }
                else if (ball_info.Addr.Y > 0)
                {
                    ball_info.Addr.X = 0;
                    ball_info.Addr.Y = -10;
                    ball_info.Speed.X = 0;
                    ball_info.Speed.Y = 0;
                    ball_info.Dir.X = 0;
                    ball_info.Dir.Y = -1;
                    brick_run_stpe++;
                    lb_run_stpe.Content = brick_run_stpe;
                    Debug.WriteLine("重置");
                }
                else if (ball_info.Addr.Y > -5)
                {
                    if (System.Math.Abs(ball_info.Addr.X - wb_val) > 50)
                    {
                        Debug.WriteLine("掉了");
                    }
                    else if (System.Math.Abs(ball_info.Addr.X - wb_val) > 45)
                    {
                 
                        if (ball_info.Dir.Y != -1)
                        {
                            ball_info.Dir.Y = -1;
                            brick_run_stpe++;
                            lb_run_stpe.Content = brick_run_stpe;
                        }
                        if (ball_info.Addr.X - wb_val < 0)
                        {
                            if (ball_info.Dir.X != -1)
                            {
                                ball_info.Dir.X = -1;
                                
                            }
                            
                        }
                        else
                        {
                            if (ball_info.Dir.X != 1)
                            {
                                ball_info.Dir.X = 1;
                            }
                            
                        }
                        ball_info.Speed.X = (Math.Abs((ball_info.Addr.X - wb_val)));
                        
                        Debug.WriteLine("起飞1");
                    }
                    else  //0~45理论还是输了。
                    {

                    }
                }
                else if (ball_info.Addr.Y > -10)
                {
                    if (System.Math.Abs(ball_info.Addr.X - wb_val) > 50)
                    {
                        //   Debug.WriteLine("掉了");
                    }
                    else
                    {
                        if (ball_info.Dir.Y != -1)
                        {
                            ball_info.Dir.Y = -1;
                            brick_run_stpe++;
                            lb_run_stpe.Content = brick_run_stpe;
                        }
                        
                        if (ball_info.Addr.X - wb_val < 0)
                        {
                            if (ball_info.Dir.X != -1)
                            {
                                ball_info.Dir.X = -1;
                                
                            }
                        }
                        else
                        {
                            if (ball_info.Dir.X != 1)
                            {
                                ball_info.Dir.X = 1;
                                
                            }
                        }
                        ball_info.Speed.X = (Math.Abs((ball_info.Addr.X - wb_val)));
                        Debug.WriteLine("起飞2");
                    }
                }

                if (brick_list != null && brick_list.Count != 0)
                {
                    for (int i = 0; i < brick_list.Count; i++) //判断砖块与球的距离
                    {
                        if (brick_list[i].Stat != 0)
                        {
                            if ((Math.Abs(brick_list[i].Addr.X - ball_info.Addr.X) < Max_leng)&&(Math.Abs(brick_list[i].Addr.Y - ball_info.Addr.Y) < Max_leng))
                            {
                                double[] leng = check_leng(brick_list[i], ball_info);
                                if (leng[1] <= 0)
                                {
                                    if (leng[0] == 0)
                                    {
                                        ball_info.Dir.X = -ball_info.Dir.X;
                                    }
                                    else
                                    {
                                        ball_info.Dir.Y = -ball_info.Dir.Y;
                                    }
                                    //触发移除操作
                                    if (brick_list[i].Stat != 99)
                                    {
                                        brick_list[i].Stat--;
                                        if (brick_list[i].Stat <= 0)
                                        {
                                            //移除砖块
                                            brick_list[i].Stat = 0;
                                            //界面移除
                                            Rectangle ret_t = null;
                                            string name = "rect_" + brick_list[i].Index.ToString();
                                            ret_t = FindChild<Rectangle>(gd_table, name);
                                            if (ret_t != null)
                                            {
                                                BrushConverter conv = new BrushConverter();
                                                Brush bru;
                                                bru = conv.ConvertFromInvariantString("#000000FF") as Brush;
                                                ret_t.Fill = bru;
                                                ret_t.Stroke = bru;
                                                re_brick_count++;
                                                lb_re_count.Content =re_brick_count;
                                                lb_lost_count.Content = brick_num - re_brick_count;
                                                if (brick_num <= re_brick_count)
                                                {
                                                    aTimer.Stop();
                                                    MessageBox.Show("恭喜,已完成拆除\r\n" + "拆除砖块:" + re_brick_count.ToString() + " 总共用时:" + processCount.TotalSecond.ToString()+"s") ; ;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                           
                        }
                    }
                }

            }
            catch
            { 
            
            }
           
        }

        /// <summary>
        /// 生成砖块
        /// </summary>
        /// <param name="brick_info">砖块信息</param>
        /// <param name="num">砖块数量</param>
        private void crt_zhuan(Point brick_info,int num)
        {
            int widght_num = (int)((gd_ball.ActualWidth - 40) / brick_info.X);
            int height_num = (int)(((gd_ball.ActualHeight) / 3 * 2 - 20) / brick_info.Y);

            int max_num = widght_num * height_num;
            if (max_num < num)
            {
                MessageBox.Show("砖过大或数量过多,请重新生成\r\n" + "最多生成 " + max_num.ToString() + " 块");
                return;
            }
            Point point_start = new Point();
            point_start.X = 20 - (gd_ball.ActualWidth / 2);
            point_start.Y = 20 - gd_ball.ActualHeight; ;
            brick_addr = GetRandomArray(num, 0, max_num);
           

            int count = 0;
            brick_list.Clear();
            brick_list = new List<Rect>();
           
            gd_table.Children.Clear();
            gd_table.RowDefinitions.Clear();
            gd_table.ColumnDefinitions.Clear();
            for (int i = 0; i < height_num; i++)
            {

                RowDefinition rowDefinition = new RowDefinition();
                rowDefinition.MinHeight = brick_info.Y;
                rowDefinition.MaxHeight = brick_info.Y;
                gd_table.RowDefinitions.Add(rowDefinition);
            }
            for (int j = 0; j < widght_num; j++)
            {
                ColumnDefinition columnDefinition = new ColumnDefinition();
                columnDefinition.MinWidth = brick_info.X;
                columnDefinition.MaxWidth = brick_info.X;
                gd_table.ColumnDefinitions.Add(columnDefinition);
            }
            for (int i = 0; i < height_num; i++)
            {
                for (int j = 0; j < widght_num; j++)
                {
                    for (int k = 0; k < num; k++)
                    {

                        //if (count == addr[k])
                        if (count == brick_addr[k])
                        {
                            //添加砖
                            Rect rect_t = new Rect();
                            Point p = new Point(0, 0);
                            p.X= point_start.X + j * brick_info.X + brick_info.X / 2;
                            p.Y= point_start.Y + i * brick_info.Y + brick_info.Y / 2;

                            //rect_t.Addr.X = point_start.X + j * brick_info.X + brick_info.X / 2;
                            //rect_t.Addr.Y = point_start.Y + i * brick_info.Y + brick_info.Y / 2;
                            rect_t.Addr = p;
                            rect_t.Width = brick_info.X;
                            rect_t.Height = brick_info.Y;
                            rect_t.Stat = 1;
                            rect_t.Index = count;
                            brick_list.Add(rect_t);
                            //显示
                            BrushConverter conv = new BrushConverter();
                            Brush bru;
                            bru = conv.ConvertFromInvariantString("#FFB6BFBF") as Brush;
                            Brush back;
                            back = conv.ConvertFromInvariantString("#FF00BFBF") as Brush;
                            //Rectangle ret_t = new Rectangle() { Width = rect_t.Width, Name= "rect_"+count.ToString(), Height = rect_t.Height, Fill = bru, Stroke = back };
                            Rectangle ret_t = new Rectangle() { Width = rect_t.Width, Name = "rect_" + count.ToString(), Height = rect_t.Height, Fill = bru, Stroke = back };
                            ret_t.SetValue(Grid.RowProperty, i);
                            ret_t.SetValue(Grid.ColumnProperty, j);
                            gd_table.Children.Add(ret_t);
                            break;

                        }
                    }
                    count++;
                }
            }


        }
       
        #endregion


        #region///控件事件
        /// <summary>
        /// 速度更改按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sd_bool_speed_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            //  bool_speed = (int)(sd_bool_speed.Value);
            ball_info.Speed.Y = (int)(sd_bool_speed.Value);
        }

        /// <summary>
        /// 底板移动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gd_ball_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point p = e.GetPosition((IInputElement)sender);
                Point d = new Point(0, 0);
                double max_leng = (gd_ball.ActualWidth - rt_wb.ActualWidth - rt_rect.ActualWidth) / 2;
                d.X= p.X - max_leng;
                d.Y = rect_info.Addr.Y;

                //rect_info.Addr.X = p.X - max_leng;
                if (d.X < -max_leng)
                {
                    d.X = -max_leng;
                }
                if (d.X > max_leng)
                {
                    d.X = max_leng;
                }
                rect_info.Addr = d;
                sd_x.Value = rect_info.Addr.X;

            }
        }


        /// <summary>
        /// 更改挡板坐标
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sd_x_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            Point d = new Point(0, 0);
            d.X= sd_x.Value;
            d.Y = rect_info.Addr.Y;
            //rect_info.Addr.X = sd_x.Value;
            double max_leng = (gd_ball.ActualWidth - rt_wb.ActualWidth - rt_rect.ActualWidth) / 2;
            if (d.X < -max_leng)
            {
                d.X = -max_leng;
            }
            if (d.X > max_leng)
            {
                d.X = max_leng;
            }
            rect_info.Addr = d;
            sd_x.Value = rect_info.Addr.X;
        }

        /// <summary>
        /// 重新开始游戏 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bt_crt_Click(object sender, RoutedEventArgs e)
        {
            aTimer.Stop();
            System.Threading.Thread.Sleep(100);
            ball_info.Speed.X = 0;
            ball_info.Addr.X = 0;
            ball_info.Addr.Y = -10;
            brick_num = (int)sd_brick_num.Value;
            brick_run_stpe = 0;
            re_brick_count = 0;
            processCount.TotalSecond = 0;
            processCount.Stpe = 0;
            crt_zhuan(brick_info, brick_num);

            lb_brick_count.Content = brick_num;
            lb_re_count.Content = 0;
            lb_lost_count.Content = brick_list.Count - re_brick_count;
            lb_run_stpe.Content = brick_run_stpe;
            lb_time.Content = processCount.GetHour() + ":" + processCount.GetMinute() + ":" + processCount.GetSecond();
            
            
        }

        /// <summary>
        /// 启动运行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bt_start_Click(object sender, RoutedEventArgs e)
        {
            ball_info.Speed.X = 0;
            ball_info.Speed.Y = sd_bool_speed.Value;
            brick_num = (int)sd_brick_num.Value;
           
            aTimer.Start();
        }

  

        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            aTimer.Stop();
        }

        /// <summary>
        /// 关联A键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb_start_game_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            bt_start_Click(null, null);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb_start_game_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        /// <summary>
        /// 窗体大小改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {

            sd_x.Maximum = gd_ball.ActualWidth / 2;
            sd_x.Minimum = -gd_ball.ActualWidth / 2;

        }

        #endregion


    }

    /// <summary>
    /// 实现倒计时功能的类
    /// </summary>
    public class ProcessCount
    {
        private Int32 _TotalSecond;

        private int _stpe = 0;

        public Int32 TotalSecond
        {
            get { return _TotalSecond; }
            set { _TotalSecond = value; }
        }
        public int Stpe
        {
            get { return _stpe; }
            set { _stpe = value; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public ProcessCount(Int32 totalSecond, int s = 0)
        {
            this._TotalSecond = totalSecond;
            this.Stpe = s;
        }


        /// <summary>
        /// 减秒
        /// </summary>
        /// <returns></returns>
        public bool ProcessCountDown()
        {
            if (_TotalSecond == 0)
                return false;
            else
            {
                _TotalSecond--;
                return true;
            }
        }


        /// <summary>
        /// 加秒
        /// </summary>
        /// <returns></returns>
        public bool ProcessCountUp()
        {
            _TotalSecond++;
            return true;
        }


        /// <summary>
        /// 获取小时显示值
        /// </summary>
        /// <returns></returns>
        public string GetHour()
        {
            return String.Format("{0:D2}", (_TotalSecond / 3600));
        }


        /// <summary>
        /// 获取分钟显示值
        /// </summary>
        /// <returns></returns>
        public string GetMinute()
        {
            return String.Format("{0:D2}", (_TotalSecond % 3600) / 60);
        }


        /// <summary>
        /// 获取秒显示值
        /// </summary>
        /// <returns></returns>
        public string GetSecond()
        {
            return String.Format("{0:D2}", _TotalSecond % 60);
        }
    }
    public sealed class MillisecondTimer : IComponent, IDisposable
    {

        private static TimerCaps caps;
        private int interval;
        private bool isRunning;
        private int resolution;
        private TimerCallback timerCallback;
        private int timerID;

        public int Interval
        {
            get
            {
                return this.interval;
            }
            set
            {
                if ((value < caps.periodMin) || (value > caps.periodMax))
                {
                    throw new Exception("超出计时范围!");
                }
                this.interval = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsRunning
        {
            get
            {
                return this.isRunning;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ISite Site
        {
            set;
            get;
        }

        public event EventHandler Disposed;  // 这个事件实现了IComponet接口
        public event EventHandler Tick;

        static MillisecondTimer()
        {
            timeGetDevCaps(ref caps, Marshal.SizeOf(caps));
        }

        public MillisecondTimer()
        {
            this.interval = caps.periodMin;    // 
            this.resolution = caps.periodMin;  //

            this.isRunning = false;
            this.timerCallback = new TimerCallback(this.TimerEventCallback);

        }

        public MillisecondTimer(IContainer container)
            : this()
        {
            container.Add(this);
        }

        ~MillisecondTimer()
        {
            timeKillEvent(this.timerID);
        }

        public void Start()
        {
            if (!this.isRunning)
            {
                this.timerID = timeSetEvent(this.interval, this.resolution, this.timerCallback, 0, 1); // 间隔性地运行

                if (this.timerID == 0)
                {
                    throw new Exception("无法启动计时器");
                }
                this.isRunning = true;
            }
        }

        public void Stop()
        {
            if (this.isRunning)
            {
                timeKillEvent(this.timerID);
                this.isRunning = false;
            }
        }

        /// <summary>
        /// 实现IDisposable接口
        /// </summary>
        public void Dispose()
        {
            timeKillEvent(this.timerID);
            GC.SuppressFinalize(this);
            EventHandler disposed = this.Disposed;
            if (disposed != null)
            {
                disposed(this, EventArgs.Empty);
            }
        }


        //***************************************************  内部函数  ******************************************************************
        [DllImport("winmm.dll")]
        private static extern int timeSetEvent(int delay, int resolution, TimerCallback callback, int user, int mode);


        [DllImport("winmm.dll")]
        private static extern int timeKillEvent(int id);


        [DllImport("winmm.dll")]
        private static extern int timeGetDevCaps(ref TimerCaps caps, int sizeOfTimerCaps);
        //  The timeGetDevCaps function queries the timer device to determine its resolution. 



        private void TimerEventCallback(int id, int msg, int user, int param1, int param2)
        {
            if (this.Tick != null)
            {
                this.Tick(this, null);  // 引发事件
            }
        }


        //***************************************************  内部类型  ******************************************************************

        private delegate void TimerCallback(int id, int msg, int user, int param1, int param2); // timeSetEvent所对应的回调函数的签名


        /// <summary>
        /// 定时器的分辨率(resolution)。单位是ms,毫秒
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct TimerCaps
        {
            public int periodMin;
            public int periodMax;
        }

    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火狐鞥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值