人生就像一條加速奔向死亡的貪吃蛇【winform版】


群里聊天的時候,一個學妹說她在做貪吃蛇的小作業,於是昨晚(5.20無聊只好擼代碼/(ㄒoㄒ)/~~)花了2個小時擼了一個出來,早上又花了些時間完善功能,就有了這個還算比較完善的版本,當然代碼結構比較混亂,沒有抽像成類,后來搜索了博客園以前的,發現都只是實現了基本的功能,根本不能愉快的玩耍。

 

整個程序只定義了一個Pos類來保存點的x,y坐標值

    //位置類
    class Pos  
    {
        public int X;
        public int Y;
        public Pos(int x, int y)
        {
            X = x;
            Y = y;
        }
    }

蛇身體用一個隊列來保存Pos信息,使用隊列雖然方便了蛇尾移出和蛇頭添加,卻不能直接得到蛇頭信息,所以獨立變量保存,食物也是一個獨立的Pos變量記錄其位置

        Pos food;        //食物位置
        Queue<Pos> snake;//蛇身體隊列
        Pos head;       //蛇頭位置
        int x,y;        //橫豎線條數
        int cubeL = 22; //格子大小

整個游戲節奏由定時器驅動,當蛇長度到達預定長度,定時器將會縮短時間間隔,加快游戲進度(到100毫秒的時候,已經喪病了)

        private void Speed()
        {
            if (snake.Count == 7)
            {
                timer1.Interval = 450;
                level = 2;
            }

         ........

            else if (snake.Count == 60)
            {
                timer1.Interval = 100;
                level = 8;
            }
        }
    

繪制代碼就不詳細解釋了,有點亂,如果您有耐心可以把它們抽離出來寫到一個Snake類里面

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.TranslateTransform(20, 50);
    Pen pen = new Pen(Color.Green,1);
    //繪制網格
    for (int i = 0; i < x+1; i++)
    {
        e.Graphics.DrawLine(pen, i * cubeL, 0, i * cubeL, y * cubeL);
    }
    for (int j = 0; j < y+1; j++)
    {
        e.Graphics.DrawLine(pen, 0, j * cubeL, x * cubeL, j * cubeL);
    }
    SolidBrush brush = new SolidBrush(Color.Orange);
    //繪制蛇
    if (state != GameState.Init)
    {
        e.Graphics.FillRectangle(brush, food.X * cubeL, food.Y * cubeL, cubeL, cubeL);
        brush.Color = Color.DeepSkyBlue;
        foreach (var p in snake)
        {
            e.Graphics.FillRectangle(brush, p.X * cubeL, p.Y * cubeL, cubeL, cubeL);
        }
        brush.Color = Color.Blue;
        e.Graphics.FillRectangle(brush, head.X * cubeL, head.Y * cubeL, cubeL, cubeL);
        brush.Color = Color.Red;
    }
    //繪制狀態提示
    if(state == GameState.Init)
    {
        brush.Color = Color.Red;
        e.Graphics.DrawString("S 開始游戲,空格 暫停/繼續游戲 \n\r奔向死亡吧,騷年!", new Font("微軟雅黑", 20), brush, 150, 120);
    }
    else if (state == GameState.Start)
    {
        if (!timer1.Enabled)
            e.Graphics.DrawString("游戲暫停,空格繼續!", new Font("微軟雅黑", 20), brush, 150, 120);
    }
    else
    {
        brush.Color = Color.Red;
        e.Graphics.DrawString("游戲結束,S 開始游戲!", new Font("微軟雅黑", 20), brush, 150, 120);
    }
    e.Graphics.ResetTransform();
    string tip = "level:"+level.ToString()+" 長度: "+snake.Count.ToString()+ "  分數:"+(snake.Count*level*10).ToString();
    brush.Color = Color.Black;
    e.Graphics.DrawString(tip, new Font("微軟雅黑", 15), brush, 360, 10);
}

鍵盤輸入處理,輸入的鍵被暫時保存在一個Direction枚舉變量中,直到移動之后才確定為當前移動方向(否則會出現bug,比如先其他方向,再反方向就會出錯)

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch(e.KeyCode)
            {
                case Keys.Up:
                    if(Dir != Direction.Down)    //不能向當前方向的反方向移動
                        tmpDir = Direction.Up;   //臨時保存,移動之后才確定為當前方向
                    break;
          .......

         case Keys.Space: if(state == GameState.Start) { timer1.Enabled = !timer1.Enabled; Invalidate(); } break; case Keys.S: if (state == GameState.Start) { timer1.Enabled = false; if (MessageBox.Show("確定重新開始游戲?", "提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { timer1.Enabled = true; break; } } StartGame(); break; } } }

蛇的移動,食物,游戲是否結束判斷

            switch (Dir) //使用策略模式來替代switch
            {
                case Direction.Up:
                    {
                        if (head.Y <= 0)   //撞牆
                        {
                            GameOver();
                        }
                        foreach (var po in snake)   
                        {
                            if (po.Y + 1 == head.Y && po.X == head.X) //吃掉自己
                            {
                                GameOver();
                                break;
                            }
                        }
                        if (state == GameState.Over)
                            break;

                        if (food.Y + 1 == head.Y && food.X == head.X) //吃掉食物
                        {
                            snake.Enqueue(food);
                            head = food;
                            GenerateFood();
                        }
                        else   //向前移動一格
                        {
                            snake.Dequeue();
                            head = new Pos(head.X, head.Y - 1);
                            snake.Enqueue(head);
                        }
                    }
                    break;
                case Direction.Down:

整個程序的結構到此介紹完畢,總的來說是一個比較完整的小游戲了,當然有很多地方可以優化,但個人也就沒那個興趣和精力了(笑)

下載地址:GreedySnake

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM