首页 > 解决方案 > 蛇。增加死亡后继续游戏的可能性

问题描述

写了一条简单的蛇。如果玩家获得一定数量的分数,我无法弄清楚如何添加死后继续游戏的可能性。单击其中一个箭头按钮后,蛇应该停止并开始移动。

碰撞

在碰撞中,出现一个关于损失的窗口,我需要继续游戏。我按下按钮,发生以下情况:

这

我不明白如何才能将蛇停在原位,如 1 张照片所示。

只有按下箭头按钮后,她才会停下来继续移动。


namespace Snake
{
    public partial class MainWindow : Window
    {
        //The field on which the snake lives
        Entity field;
        // snake head
        Head head;
        // whole snake
        List<PositionedEntity> snake;
        // apple
        Apple apple;
        //number of points
        int score;
        //time
       DispatcherTimer moveTimer;

        //constructor form
        public MainWindow()
        {
            InitializeComponent();

            snake = new List<PositionedEntity>();
            //create field 600x600pixels
            field = new Entity(600, 600, "pack://application:,,,/Resources/snake.png");

            //create a timer that runs every 300 ms
            moveTimer = new DispatcherTimer();
            moveTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);
            moveTimer.Tick += new EventHandler(moveTimer_Tick);

        }

        //redraw screen method
        private void UpdateField()
        {
            //update the position of the elements of the snake
            foreach (var p in snake)
            {
                Canvas.SetTop(p.image, p.y);
                Canvas.SetLeft(p.image, p.x);
            }

            //update the position of apple
            Canvas.SetTop(apple.image, apple.y);
            Canvas.SetLeft(apple.image, apple.x);

            //points update
            lblScore.Content = String.Format("{0}000", score);
        }

        //timer tick handler. All movement takes place here.
        void moveTimer_Tick(object sender, EventArgs e)
        {
            //in the reverse order we move all the elements of the snake
            foreach (var p in Enumerable.Reverse(snake))
            {
                p.move();
            }

            //we check that the head of the snake did not crash into the body
            foreach (var p in snake.Where(x => x != head))
            {
                if (p.x == head.x && p.y == head.y)
                {
                    //we lose
                    moveTimer.Stop();
                    GameOver.Visibility = Visibility.Visible;
                    btnRestart.Visibility = Visibility.Visible;
                    tbScore.Text = String.Format("SCORE: {0}000", score);
                    return;
                }
            }

            //check that the head of the snake did not go out of the field
            if (head.x < 40 || head.x >= 540 || head.y < 40 || head.y >= 540)
            {
                //we lose
                moveTimer.Stop();
                GameOver.Visibility = Visibility.Visible;
                btnRestart.Visibility = Visibility.Visible;
                tbScore.Text = String.Format("SCORE: {0}000", score);
                return;
            }

            //check that the head of the snake crashed into an apple
            if (head.x == apple.x && head.y == apple.y)
            {
                //increase the score
                score++;
                //move the apple to a new place
                apple.move();
                var part = new BodyPart(snake.Last());
                canvas1.Children.Add(part.image);
                snake.Add(part);
            }
            UpdateField();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Up:
                    head.direction = Head.Direction.UP;
                    break;
                case Key.Down:
                    head.direction = Head.Direction.DOWN;
                    break;
                case Key.Left:
                    head.direction = Head.Direction.LEFT;
                    break;
                case Key.Right:
                    head.direction = Head.Direction.RIGHT;
                    break;
            }
        }

        // "Start"
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            btnStart.Visibility = Visibility.Hidden;
            btnRestart.Visibility = Visibility.Hidden;
            tBNotEnoughPoints.Visibility = Visibility.Hidden;
            score = 0;
            snake.Clear();
            canvas1.Children.Clear();
            // "Game Over"
            GameOver.Visibility = Visibility.Hidden;

            canvas1.Children.Add(field.image);
            apple = new Apple(snake);
            canvas1.Children.Add(apple.image);
            head = new Head();
            snake.Add(head);
            canvas1.Children.Add(head.image);

            moveTimer.Start();
            UpdateField();

        }
        private void btnContinue_Click(object sender, RoutedEventArgs e)
        {
            if (score >= 2)
            {
                GameOver.Visibility = Visibility.Hidden;
                btnRestart.Visibility = Visibility.Hidden;
                score -= 2;

                moveTimer.Start();
                UpdateField();
            }
            else
            {
                tBNotEnoughPoints.Visibility = Visibility.Visible;
            }
        }

        public class Entity
        {
            protected int m_width;
            protected int m_height;

            Image m_image;
            public Entity(int w, int h, string image)
            {
                m_width = w;
                m_height = h;
                m_image = new Image();
                m_image.Source = (new ImageSourceConverter()).ConvertFromString(image) as ImageSource;
                m_image.Width = w;
                m_image.Height = h;

            }

            public Image image
            {
                get
                {
                    return m_image;
                }
            }
        }

        public class PositionedEntity : Entity
        {
            protected int m_x;
            protected int m_y;
            public PositionedEntity(int x, int y, int w, int h, string image)
                : base(w, h, image)
            {
                m_x = x;
                m_y = y;
            }

            public virtual void move() { }

            public int x
            {
                get
                {
                    return m_x;
                }
                set
                {
                    m_x = value;
                }
            }

            public int y
            {
                get
                {
                    return m_y;
                }
                set
                {
                    m_y = value;
                }
            }
        }

        public class Apple : PositionedEntity
        {
            List<PositionedEntity> m_snake;
            public Apple(List<PositionedEntity> s)
                : base(0, 0, 40, 40, "pack://application:,,,/Resources/fruit.png")
            {
                m_snake = s;
                move();
            }

            public override void move()
            {
                Random rand = new Random();
                do
                {
                    x = rand.Next(13) * 40 + 40 ;
                    y = rand.Next(13) * 40 + 40 ;
                    bool overlap = false;
                    foreach (var p in m_snake)
                    {
                        if (p.x == x && p.y == y)
                        {
                            overlap = true;
                            break;
                        }
                    }
                    if (!overlap)
                        break;
                } while (true);

            }
        }

        public class Head : PositionedEntity
        {
            public enum Direction
            {
                RIGHT, DOWN, LEFT, UP, NONE
            };

            Direction m_direction;

            public Direction direction {
                set
                {
                    m_direction = value;
                    RotateTransform rotateTransform = new RotateTransform(90 * (int)value);
                    image.RenderTransform = rotateTransform;
                }
            }

            public Head()
                : base(280, 280, 40, 40, "pack://application:,,,/Resources/head.png")
            {
                image.RenderTransformOrigin = new Point(0.5, 0.5);
                m_direction = Direction.NONE;
            }

            public override void move()
            {
                switch (m_direction)
                {
                    case Direction.DOWN:
                        y += 40;
                        break;
                    case Direction.UP:
                        y -= 40;
                        break;
                    case Direction.LEFT:
                        x -= 40;
                        break;
                    case Direction.RIGHT:
                        x += 40;
                        break;
                }
            }
        }

        public class BodyPart : PositionedEntity
        {
            PositionedEntity m_next;
            public BodyPart(PositionedEntity next)
                : base(next.x, next.y, 40, 40, "pack://application:,,,/Resources/body.png")
            {
                m_next = next;
            }

            public override void move()
            {
                x = m_next.x;
                y = m_next.y;
            }
        }


    }
}

标签: c#wpf

解决方案


您可以添加一个字段来确定蛇在moveTimer_Tick被调用时是否应该移动

// Is movement paused
bool paused;

Continue然后在按下按钮时设置此条件。

private void btnContinue_Click(object sender, RoutedEventArgs e)
{
    if (score >= 2)
    {
        GameOver.Visibility = Visibility.Hidden;
        btnRestart.Visibility = Visibility.Hidden;
        score -= 2;

        // Pause movement
        paused = true;

        moveTimer.Start();
        UpdateField();
    }
    else
    {
        tBNotEnoughPoints.Visibility = Visibility.Visible;
    }
}

moveTimer_Tick然后在你的方法中检查这个。

//timer tick handler. All movement takes place here.
void moveTimer_Tick(object sender, EventArgs e)
{
    // Do not update if movement is paused
    if(paused) {
       return;
    }
    ...
}

然后可以在按下某个键时更改此条件。

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    // Unpause movement when any key is pressed
    if(paused) {
        paused = false;
    }
    switch (e.Key)
    {
        case Key.Up:
            head.direction = Head.Direction.UP;
            break;
        case Key.Down:
            head.direction = Head.Direction.DOWN;
            break;
        case Key.Left:
            head.direction = Head.Direction.LEFT;
            break;
        case Key.Right:
            head.direction = Head.Direction.RIGHT;
            break;
    }
}

您也可以扩展它以暂停游戏。

您还应该考虑@Ron Beyer 在他的评论中提到的内容:

当蛇撞到墙或自己时游戏结束,除非你“撤消”结束游戏的事情,否则当你重新启动它时它会立即结束。

我希望这有帮助。


推荐阅读