亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

基于控制臺實現貪吃蛇游戲

2019-11-14 13:51:32
字體:
來源:轉載
供稿:網友

1)、引言

  學習編程,我個人覺得最好的辦法就是根據自己的水平不斷的給自己設定一個小目標。而這個小目標就是一個有意思的項目,通過完成這個項目,對自己的成果(也包括失敗的)進行分析總結,從中提煉出對應的技術并分享出來,不斷的往復,如此,為的就是讓我們永遠保持編寫程序的興趣和熱情,完了,還提高我們的技術。而本文就是總結自己的一個小目標(基于控制臺實現的貪吃蛇游戲而寫的總結)

2)、技術實現

  大家小時候一定玩過貪吃蛇的游戲。貪吃蛇游戲的控制過程其實也不復雜。簡單的可以概括為以下4個部分。

 1.1  、組成蛇的小塊以及食物(Block)

  在本程序中,食物以及蛇的組成都用一個對象表示,因為它們的作用都是一樣,僅僅只需要一個坐標對。以及提供一個靜態方法,即可以通過在游戲的地圖內生隨機產生一個坐標對并返回Block對象。

 1.2、管理蛇的部分(Snake)

  程序的主體主要“蛇”這個對象的屬性以及方法的設計。現在我們想想在游戲中這個對象需要有哪些屬性以及行為,首先“蛇”有長度以及“蛇”的組成,這就是蛇的屬性,可以由一個相鄰的Block類型的集合snakeList來表示;其次,蛇能移動(上下左右),能吃食物,并且不能碰到邊框以及頭部不能觸碰自己的身體,這就可以抽象為蛇的三個行為,Move(),IsEatFood (),IsOver(),分別為移動,吃食物,檢測自身是否滿足游戲的規則。

  1、Move()

  //蛇移動的關鍵代碼如下。

 public void Move(Direction dir)        {            Block head = this.snakeLIst[0];//獲取蛇頭            this.snakeLIst.RemoveAt(this.snakeLIst .Count -1);//移除末尾項            Block newBlock=null;            switch (dir)//獲取蛇當前運行的方向,然后把根據蛇頭的位置計算出新的蛇頭的位置。相當于把蛇尾的坐標進行計算插入到蛇頭。            {                 case Direction.Top :                    newBlock = new Block(head.Row-1, head.Col);                    break;                case Direction .Bottom :                    newBlock = new Block(head.Row+1, head.Col);                    break;                case Direction .Left :                    newBlock = new Block(head.Row, head.Col-1);                    break;                case Direction .Right:                    newBlock = new Block(head.Row , head.Col+1);                    break;            }            this.snakeLIst.Insert(0, newBlock);//將新的位置插入到蛇頭        }

  蛇移動的程序的動態過程如下圖:(以向左走為例)

  

   2、IsEatFood ()

  //代碼如下

 /// <summary>        /// 判斷蛇是否達到食物的位置,如果到達這eat        /// </summary>        /// <param name="b">食物對象</param>        /// <returns>返回bool,好讓調用方知道是否需要產生新的食物</returns>        public bool IsEatFood(Block b)        {            Block head = this.snakeLIst[0];//獲取蛇頭            if (head.IsEqual(b))//是食物的位置一致            {                this.snakeLIst.Add(b);//添加一個block到蛇的集合中,并這下一次move中移動到蛇頭,保證有序。                return true ;            }            return false ;        }

  3、IsOver()

  //代碼如下 

 public bool IsOver()        {            Block head = this.snakeLIst[0];            if (head.Row == 0 || head.Col == 0 || head.Row == 25 || head.Col == 80)//是否遇到邊界            {                return true;            }            for (int i = 1; i < this.snakeLIst.Count; i++)//是否遇到自身            {                if (head.IsEqual(this.snakeLIst[i]))                {                    return true ;                }            }            return false;        }

 

 1.3、管理游戲界面的類(MapManager)

  我們都知道游戲都是畫面不斷變化的一個過程,所以我們必須在極短的時間內去更新游戲的畫面,所以就離不開定時器。然后就可以實時的去繪制游戲的當前的狀態,那么一系列的狀態連起來就一個動態的游戲畫面。

  • 1、我把整個游戲的地圖存儲在一個二位數組里面,如果其值為0則代表為空的,如果為1,則輸出“#”,因為這和在窗體中繪制游戲畫面不一樣,控制臺只能從左至右,從上至下的輸出。
  • 2、首先繪制邊界,實際上就是把二維數組(地圖)中的某一些值賦值為1.
  • 3、建立“對象”并初始化,遍歷組成蛇的Block集合,來獲取”蛇“在二維數組(地圖)的位置,并把對應的位置賦值為1.
  • 4、初始化食物,也即是block對象,在二維數組(地圖)中找到他的位置,和第3步一樣將對應的位置賦值為1。
  • 5、上面的4步已經把“蛇”、食物以及游戲的邊界繪制出來,接下來就是蛇的運動了。蛇的運動就是每次調用“蛇”的Move()行為,然后再蛇運行之前都要判斷下面兩個條件,第一,當前蛇頭的位置是不是在食物的位置,如果在則吃掉食物,生成新的食物,調用的方法為IsEatFood();第二,“蛇”是否滿足規則,如果不滿足則游戲結束,調用IsOver()。
  • 6、當上面的步驟都完成之后,即二維數組(地圖)都賦值好了,然后再從上之下,從左至右依次輸出(其實就是一長串字符串)。最后一步才是真正的在界面輸出,其中前面的步驟都是游戲畫面的緩存。關于計時器是使

  其中System.Threading中的Timer類,具體的用戶可以查看其它資料,也可以看后面程序中是如何使用Timer類的

 1.4、與用戶交互的設計

  程序將用戶交互的接口放在了MapManager,主要功能為,啟動計時器去管理游戲的繪制與運行,然后另外就是處理用戶的輸入去改變游戲運行狀態。

 

     其中,需要注意的是,由于是基于控制臺的實現,用戶的輸入肯定是不能按enter之后然后程序才能接受,而是實時的接受用戶的輸入且還不能將用戶的輸入顯示到控制中,還好c#提供了Console.Readkey(true),可以滿足程序的要求。

 1.5、下面是程序運行的流程圖

   

  注意:

其中需要注意的是,最后輸出賦值好的二維數組(地圖)時候,不是遍歷二維數組(地圖)遍歷一項就輸出一項,而是用StringBuilding對象去添加,直到遍歷完了,一次性輸出StringBuilding對象,達到雙緩存的效果,使得控制臺繪制不會閃爍。

3)程序編碼的實現

  本程序是基于c#控制臺實現的,開發工具為2013

  1、Block類

  public class Block    {        PRivate int x;        private int y;               public Block()        {                     }        public Block(int x, int y)        {            this.x = x;            this.y = y;        }        public int Row        {            get { return this.x; }            set { this.x = value; }        }        public int Col        {            get { return this.y; }            set { this.y = value; }        }        public bool IsEqual(Block b)        {            if (this.x == b.Row&& this.y == b.Col)            {                return true;            }            return false;        }        public static Block ProvideFood()        {             Random r=new Random ();            Block b = new Block(r.Next(1, 25), r.Next(1, 80));            return b;        }    }

 

2、Snake類

public class Snake    {        List<Block> snakeLIst = new List<Block>();//存儲蛇的結構        public List<Block> SnakeLIst        {            get { return snakeLIst; }        }        public Snake()        {            InitSnake();        }        private void InitSnake()        {            int rowStart = 2;            int colStart=5;            int lenth = 20+colStart ;            Block b;            for (int i = colStart; i < lenth; i++)            {                b = new Block(rowStart ,i);                this.snakeLIst.Insert(0, b);            }        }        /// <summary>        /// 判斷蛇是否達到食物的位置,如果到達這eat        /// </summary>        /// <param name="b">食物對象</param>        /// <returns>返回bool,好讓調用方知道是否需要產生新的食物</returns>        public bool IsEatFood(Block b)        {            Block head = this.snakeLIst[0];//獲取蛇頭            if (head.IsEqual(b))//是食物的位置一致            {                this.snakeLIst.Add(b);//添加一個block到蛇的集合中,并這下一次move中移動到蛇頭,保證有序。                return true ;            }            return false ;        }        public void Move(Direction dir)        {            Block head = this.snakeLIst[0];//獲取蛇頭            this.snakeLIst.RemoveAt(this.snakeLIst .Count -1);//移除末尾項            Block newBlock=null;            switch (dir)//獲取蛇當前運行的方向,然后把根據蛇頭的位置計算出新的蛇頭的位置。相當于把蛇尾的坐標進行計算插入到蛇頭。            {                 case Direction.Top :                    newBlock = new Block(head.Row-1, head.Col);                    break;                case Direction .Bottom :                    newBlock = new Block(head.Row+1, head.Col);                    break;                case Direction .Left :                    newBlock = new Block(head.Row, head.Col-1);                    break;                case Direction .Right:                    newBlock = new Block(head.Row , head.Col+1);                    break;            }            this.snakeLIst.Insert(0, newBlock);//將新的位置插入到蛇頭        }        public bool IsOver()        {            Block head = this.snakeLIst[0];            if (head.Row == 0 || head.Col == 0 || head.Row == 25 || head.Col == 80)//是否遇到邊界            {                return true;            }            for (int i = 1; i < this.snakeLIst.Count; i++)//是否遇到自身            {                if (head.IsEqual(this.snakeLIst[i]))                {                    return true ;                }            }            return false;        }    }

 

  3、MapManager類(包括與用戶的交互)

 public class MapManager    {        const int row = 25;        const int col = 80;        Snake snake;//        Block b;//食物        Timer t;//定時器        int[,] gameMap = new int[row, col];//地圖        int count=0;        StringBuilder mapBuffer;//緩存區        bool isNormal = true;        //初始化地圖+繪制邊界        private void InitMap()        {                        for (int i = 0; i < row; i++)            {                if (i == row - 1 || i == 0)                {                    for (int j = 0; j < col; j++)                    {                        this.gameMap[i, j] = 1;                    }                }                else                {                    for (int j = 0; j < col; j++)                    {                        if (j == col - 1 || j == 0)                        {                            this.gameMap[i, j] = 1;                        }                        else                        {                            this.gameMap[i, j] = 0;                        }                    }                }            }        }        //繪制蛇        private void InitSnake()        {            foreach (var s in snake.SnakeLIst)            {                gameMap[s.Row, s.Col] = 1;            }        }        //繪制食物        private void InitFood()        {            gameMap[this.b.Row, this.b.Col] = 1;        }        //輸出控制臺(游戲畫面)        private void DrawMap()        {                       mapBuffer.Clear();            Console.Clear();            for (int i = 0; i < row; i++)            {                for (int j = 0; j < col; j++)                {                    if (gameMap[i, j] == 1)                    {                        mapBuffer.Append("*");                    }                    else                    {                        mapBuffer.Append(" ");                    }                }                mapBuffer.Append("/n");            }            Console.WriteLine("/n-----------------------------當前得分{0}------------------------/n", count);            Console .Write(mapBuffer .ToString ());//從緩存區中輸出整個游戲畫面        }        //游戲運行管理        private void GameRun(object o)        {            InitMap();            InitSnake();            InitFood();            if (snake.IsEatFood(b))            {                b = Block.ProvideFood();//產生新的食物                count++;//得分            }            snake.Move(GlobalVar.dir);            if (snake.IsOver())            {                GameOver();            }            DrawMap();        }        private void GameOver()        {            Console.Clear();            Console.WriteLine("Game Over");            isNormal = false;            t.Dispose();        }        private void GameInit()        {            Console.WriteLine("按[w,s.a.d]作為上下左右,按[q]退出游戲?。?!");            Console.WriteLine("按任何鍵進入游戲");            Console.ReadKey(true);        }        //程序開始,該方法包括啟動定時器,以及與用戶的交互        public void Start()        {            GameInit();            snake = new Snake();            b = Block.ProvideFood();            mapBuffer = new StringBuilder();            //GameRun(null);            t = new Timer(GameRun, null, 200, 100);            char c;            while (isNormal)            {                c=Console .ReadKey(true ).KeyChar ;                switch (c)                {                     case 's':                        if (GlobalVar.dir != Direction.Top)                        {                            GlobalVar.dir = Direction.Bottom;                        }                        break;                    case 'w':                        if (GlobalVar.dir != Direction.Bottom)                        {                            GlobalVar.dir = Direction.Top;                        }                        break;                    case 'a':                        if (GlobalVar.dir != Direction.Right)                        {                            GlobalVar.dir = Direction.Left;                        }                        break;                    case 'd':                        if (GlobalVar.dir != Direction.Left)                        {                            GlobalVar.dir = Direction.Right;                        }                        break;                    case 'q':                        GameOver();                        break;                }            }            Console.ReadLine();        }    }

 

 

  4、方向枚舉(Direction)

    public enum Direction    {         Left,Right,Top,Bottom    }

 

  5、main(程序入口)

static void Main(string[] args)        {            MapManager mm = new MapManager();            mm.Start();        }

  6、程序效果

   本來想插入視頻,但是不可以直接上傳,就截幾個圖吧。

  

4)結論

其實程序的最重要的部分是設計思路而不是編碼,就這個程序也可以使用c、python等語言實現,都不是很那難。一旦程序的流程清晰了,編碼的過程自然也會浮現出來啦。

  源碼:http://download.csdn.net/detail/mingge38/9220243 。


上一篇:重構

下一篇:C#字符串的不變性

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美在线影院在线视频| 亚洲视频一区二区| 在线免费看av不卡| 伊人成人开心激情综合网| 57pao国产成人免费| 成人黄色生活片| 九九热r在线视频精品| 狠狠干狠狠久久| 欧美大成色www永久网站婷| 久久精品91久久香蕉加勒比| 欧美精品电影免费在线观看| www.99久久热国产日韩欧美.com| 亚洲精品国产suv| 97免费在线视频| 日韩美女视频免费看| 欧美性生交大片免网| 国产精品影院在线观看| 国产欧美一区二区| 91成人性视频| 日本a级片电影一区二区| 91精品久久久久久久久久| 欧美性感美女h网站在线观看免费| 丁香五六月婷婷久久激情| 国产精品444| 国产精品久久久久久久久借妻| 精品偷拍各种wc美女嘘嘘| 亚洲精品999| 国产精品久久久久久av福利软件| 亚洲欧美精品在线| 久久精品成人一区二区三区| 午夜精品久久久99热福利| 蜜臀久久99精品久久久无需会员| 欧美一区二区大胆人体摄影专业网站| 国产精品美女av| 亚洲精品天天看| 国产日韩视频在线观看| 国产精品扒开腿做爽爽爽男男| 国语自产精品视频在线看| 国产日韩欧美在线视频观看| 久久在线免费观看视频| 亚洲福利精品在线| 久久综合久中文字幕青草| 九色91av视频| 51久久精品夜色国产麻豆| 久久精品视频导航| 狠狠躁天天躁日日躁欧美| 日韩性xxxx爱| 成人xvideos免费视频| 亚洲精品www| 久久91亚洲人成电影网站| 欧美极品美女电影一区| 欧美精品videossex88| 中文字幕欧美国内| 97精品视频在线播放| 亚洲女同性videos| 91久久精品国产91久久| 国产精欧美一区二区三区| 久久在线免费观看视频| 久久视频在线免费观看| 亚洲美女福利视频网站| 国产精品中文字幕在线| 国产剧情日韩欧美| 亚洲成人久久电影| 日本韩国欧美精品大片卡二| 午夜精品久久久久久久99热| 插插插亚洲综合网| 国产欧美日韩高清| 国产精品美乳在线观看| 国产精品久久9| 亚洲乱亚洲乱妇无码| 日韩久久免费视频| 2025国产精品视频| 日韩成人在线视频网站| 久久国产天堂福利天堂| 97香蕉超级碰碰久久免费软件| 国产精品成av人在线视午夜片| 久久91亚洲精品中文字幕奶水| 久久久久久中文字幕| 国产欧美一区二区三区视频| 国内成人精品一区| 91久久嫩草影院一区二区| 国产精品爽爽爽爽爽爽在线观看| 久久这里只有精品视频首页| 亚洲精品美女久久久| 亚洲国产精品999| 久久免费少妇高潮久久精品99| 第一福利永久视频精品| 欧美电影在线播放| 精品国模在线视频| 精品国产欧美一区二区三区成人| 欧美激情免费看| 日本亚洲欧美三级| 久久综合电影一区| 91九色蝌蚪国产| 亚洲国产私拍精品国模在线观看| 国产精品中文字幕久久久| 色阁综合伊人av| 国产精品一区二区三区成人| 色综合色综合久久综合频道88| 夜夜嗨av色综合久久久综合网| 亚洲free性xxxx护士hd| 欧美日韩亚洲网| 欧美性xxxx极品hd欧美风情| 欧美性在线观看| 欧美精品激情blacked18| 欧美一级视频一区二区| 国产亚洲精品日韩| 国产精品一区二区久久| 国产美女直播视频一区| 日韩一区在线视频| 精品国产精品自拍| 亚洲一区二区三区毛片| 亚洲精品美女在线观看播放| 中日韩美女免费视频网站在线观看| 精品亚洲永久免费精品| 亚洲人成电影网站色xx| 91日本视频在线| 久久av红桃一区二区小说| 5252色成人免费视频| 国产99久久精品一区二区永久免费| 欧美一区二区三区精品电影| 91精品在线国产| 欧美第一淫aaasss性| 2019中文字幕在线免费观看| 91久久久久久久久久| 性色av一区二区三区| 亚洲欧美999| 日韩欧美福利视频| 午夜精品99久久免费| 欧美极品美女视频网站在线观看免费| 欧美极品美女视频网站在线观看免费| 欧美精品18videosex性欧美| 亚洲人成在线电影| 亚洲男人天天操| 日韩欧美在线视频免费观看| 欧美一级在线播放| 亚洲欧洲中文天堂| 伊人久久久久久久久久久久久| 欧美精品18videosex性欧美| 亚洲在线一区二区| 中文字幕日韩在线观看| 久久久最新网址| 91九色国产视频| 欧美性在线视频| 国产香蕉一区二区三区在线视频| 91爱爱小视频k| 亚洲欧洲在线播放| 日韩av电影在线播放| 97国产suv精品一区二区62| 欧美亚洲国产成人精品| 欧美国产精品人人做人人爱| 91精品国产一区| 日本成人黄色片| 日韩最新在线视频| 午夜精品一区二区三区在线视| 一区二区成人精品| 亚洲国语精品自产拍在线观看| 国产精品吹潮在线观看| 全球成人中文在线| 日韩69视频在线观看| 亚洲一区二区三区乱码aⅴ蜜桃女| 国产精品美女网站| 国产午夜精品视频免费不卡69堂| 国产精品欧美激情|