黑马程序员——.NET笔记6 飞行棋思路总结

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------

飞行棋的例子是对基础知识的一次很好很全面的训练,这篇笔记里我尝试对制作飞行棋程序的整体思路做一次回顾。

首先是要显示游戏名称、欢迎信息、游戏说明等,这部分固定不变,可以做写成一个ShowUI()

第二步是要获得玩家名字,用string[] names=new string[2] 存放两个玩家的名字,这样后面只需要改变数组下标就可以选中不同玩家,比较方便。需要验证字符串和检测重名,写一个GetNames(),用while(){try-catch}来处理错误的输入。再写一个GetNames(string name0)重载方法,传入玩家A的名字,验证并获得玩家B的名字。

然后是最重要的部分,绘制地图。

用int[] Map=new int[100] 来存放地图中100个格的状态。状态有5种,用int数值0-4来表示,分别是普通格和幸运轮盘、地雷、暂停一次、时空隧道。后4种特殊格分别用4个数组来存放它们在Map[] 中的下标,于是Map[pause[0]]就代表地图中第一处暂停一次的格子,依此类推。此外,一个格子还可能有3种状态,被玩家A占据、被玩家B占据、被玩家AB同时占据。这只需要一个数组int playerPos[]两个元素分别存放两个玩家在Map[]中的下标就可以了,这两个下标是可以变化的。这部分地图数据初始化可以独立出来写进InitialMap()

然后是把地图输出到屏幕,根据Map[]的元素中存放的状态数字判断是哪种格子,从而选定要显示的符号,用 GetMapString(int i)和switch得到Map[i]对应的符号,在DrawMap()中的Write()或WriteLine()中调用GetMapString()输入符号。 在GetMapString()中通过 Console.ForegroundColor 和ConsoleColor改变符号显示的颜色,并不DrawMap()中Console.ResetColor()重置地图绘完后后面字符的颜色。

地图有4次转折把地图分隔成左右翻转的‘S’形的5部分,关键是第二和第三部分。第二部分是Map[]下标从30到34的5格,输出符号时要在前面补29个全角空格,使它们在视觉上显示从上向下对齐排列。第三部分是Map[]下标从35到64的30格,方向是从右向左,for循环的三个表达式这样写for (int i = 64; i >=35; i--)。

---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ----------------------

(之前写的时候没写完,过了段时间再来看果然对后面的内容记忆不清了,重新看了下代码才理清思路。)


地图绘好之后,接下来该开始游戏了。这部分是程序中要不断重复执行的部分,要用循环语句来处理,用while(){}循环就可以了。
一开始A和B都在Map[0]的位置上,AB在Map中的下标是变动的,用一个数组playerPos[]来表示,Map[playerPos[0]]就代表A所在的关卡。
游戏的视觉表现就是改变Map[playerPos[0]]的图案符号为代表A的符号,以及playerPos[0]的变动。
前者清屏重绘地图就行了。后者是游戏的核心,依据玩家掷出的骰子点数(Random()),决定playerPos增加量,然后根据Map[playerPos[0]]的图案(对应的值)判断玩家走到何种关卡执行奖励或是惩罚,即加或减playerPos的值。
玩家playerPos变动完成后就是清屏重绘地图,并移交操作权(改变playerPos[0]为playerPos[1]或相反)。再重复写一遍playerPos[1]的代码就太麻烦了,有简单的办法来解决。把playerPos写成playerPos[c],playerPos[t],c代表当前玩家,t代表另一个玩家,代码里只写playerPos[c]的代码,执行完一次代码后就交换c和t的值,即0和1,这样就实现了同一段代码玩家AB轮流执行。
这里又有一个问题,关卡中存在一种叫“暂停一次”,当于家走到这种关卡时,就必须中断一次交换,即让对方执行两次。需要设置一个标志isStop来判断要不要交换c和 t 的值。这里需要注意的是,“不交换”是发生在下一次对方执行完一次循环代码后,本次仍然要交换,这就要保证isStop是在下一次被识别为要交换。办法是对isStop设置3个值,默认0(在循环外定义)表示正常交换,当遇到“暂停一次”关卡时isStop=1,然后在执行完主要代码后判断if(isStop==1),则交换c和 t 并把isStop赋值为2,这样当下一次执行完主要代码后判断进入else if(isStop==2),这时不交换c和 t ,同时把isStop重置为0。这样这个问题就解决了。
这部分看着代码更便于理解,以下是Main()部分的代码:

        static void Main(string[] args)
        {
            //控制台窗口初始化,指定标题和高度
            Console.Title = "飞行棋";
            Console.WindowHeight = 35;
            
            //显示游戏名称
            ShowUI();

            //获取玩家名字
            names[0] = GetNames();
            names[1] = GetNames(names[0]);

            //游戏开始
            Console.WriteLine("开始游戏。。。");
            ShowUI();

            //初始化地图
            InitialMap();
            //绘制地图
            DrawMap();
            Console.WriteLine("游戏开始......");

            //产生随机数并存放
            Random r = new Random();
            int step = 0;

            //设置标记,交换AB行动次序
            //isStop = 0 正常交换,isStop = 1 下次不交换(暂停一次),isStop = 2 ,不交换
            int a = 0, b = 1, ctemp = 0;
            int isStop = 0;

            //AB轮流掷骰子,当坐标>=99,结束循环
            while (playerPos[0] < 99 && playerPos[1] < 99)
            {
                #region 玩家掷骰子
                Console.WriteLine("{0}按任意键开始掷骰子......", names[a]);
                Console.ReadKey(true);
                step = r.Next(1, 7);
                Console.WriteLine("{0}掷出了{1},前进{1}步,按任意键开始行动......", names[a], step);
                Console.ReadKey(true);
                playerPos[a] = playerPos[a] + step;
                CheckPos();

                if (playerPos[a] == playerPos[b])
                {
                    Console.WriteLine("踩到对方,把TA踢回起点!");
                    playerPos[b] = 0;
                }
                else
                {
                    switch (Map[playerPos[a]])
                    {
                        case 0:
                            Console.WriteLine("一路畅通,前进!");
                            Console.ReadKey(true);
                            break;
                        case 1://幸运轮盘
                            DrawMap();
                            Console.WriteLine("你走到了幸运轮盘,请选择:");
                            Console.WriteLine("1--交换位置  2--轰炸对方");
                            int userSelect = ReadInt(1, 2);
                            if (userSelect == 1)
                            {
                                Console.WriteLine("交换位置");
                                int temp = playerPos[a];
                                playerPos[a] = playerPos[b];
                                playerPos[b] = temp;
                            }
                            else
                            {
                                Console.WriteLine("轰炸对方,对方被炸退6格");
                                playerPos[b] -= 6;
                                CheckPos();
                            }
                            Console.ReadKey(true);
                            break;
                        case 2:
                            Console.WriteLine("踩到地雷,炸退6格");
                            playerPos[a] -= 6;
                            CheckPos();
                            Console.ReadKey(true);
                            break;
                        case 3:
                            Console.WriteLine("前方暴风雨,暂停一次。");
                            isStop = 1;
                            Console.ReadKey(true);
                            break;
                        case 4:
                            Console.WriteLine("进入时空隧道,穿越10格!");
                            playerPos[a] += 10;
                            CheckPos();
                            Console.ReadKey(true);
                            break;
                    }
                }
                Console.WriteLine("{0}掷出了{1},行动完成!", names[a], step);
                Console.ReadKey(true);
                DrawMap();
                    
                Console.WriteLine("**********玩家A和玩家B的位置**************");
                Console.WriteLine("{0}当前位置是第{1}格", names[0], playerPos[0] + 1);
                Console.WriteLine("{0}当前位置是第{1}格", names[1], playerPos[1] + 1);
                Console.WriteLine("**********  游  戏  继  续  **************");

                //交换AB行动次序标记
                if (isStop==0)
                {
                    ctemp = a;
                    a = b;
                    b = ctemp;
                }
                else if (isStop == 1)
                {
                    ctemp = a;
                    a = b;
                    b = ctemp;
                    isStop = 2;
                }
                else
                {
                    isStop = 0;
                }
                #endregion
            }
            if (a == 1)//因为发生了AB次序交换,a==1说明刚刚行动的是 names[0]
            {
                Console.WriteLine("\n*********** 恭喜!{0} 获胜!  ***********\n", names[0]);
                Console.WriteLine("请按任意键退出游戏...");
            }
            else //a==0
            {
                Console.WriteLine("\n*********** 恭喜!{0} 获胜!  ***********\n", names[1]);
                Console.WriteLine("请按任意键退出游戏...");
            }
            Console.ReadKey();
        }

最后,是玩家胜利游戏中止,也就是循环中止,条件是playerPos[]< 99写进循环条件里就好了。

这样整个游戏就写完了。


最后吐槽下,.NET的平台依赖性太坑人了。对游戏做了些修改后我发布成安装包给朋友玩,结果朋友电脑上没有装.Net Framework 4.5 ,于是就不能玩。。。



---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值