【全栈计划 —— 编程语言之C#】 C# 实现双人飞行棋小游戏

简介: 【全栈计划 —— 编程语言之C#】 C# 实现双人飞行棋小游戏

项目结构流程图


首先要清楚项目的整体实现流程,跟着项目流程图走有助于思路上更加清晰。

微信图片_20221020131634.png项目实现


一、游戏开始界面


在编写游戏的开始界环节中,值得积累的知识点是控制台字体的背景颜色和字体颜色修改

利用枚举类 ConsoleColor来调取已经存储在其中的颜色字段。

同时使用: Console.ResetColor();来控制颜色的修改

微信图片_20221020131929.png

在利用Console类调用BackgroundColor来修改控制台中字体的背景颜色

微信图片_20221020132118.png

在利用Console类调用ForegroundColor来修改控制台中字体文本的颜色

微信图片_20221020132148.png

public static void GameShow()
        #region 画游戏头
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("*****************************");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("*****************************");
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("*******飞行棋游戏模拟********");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("*****************************");
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.WriteLine("*****************************");
        }
        #endregion

二、初始化游戏地图


初始化游戏地图的目的主要是考虑到一些固定的位置要放置一些固定的关卡。

微信图片_20221020132237.png

这个环节就没有什么值得注意的点了,常规的数组的操作,假如想玩得花一点,可以考虑用随机数来表示关卡的位置。

        public static void InitMap()
        #region 初始化游戏地图
        {
            //1 幸运轮盘
            int[] lucky = { 6, 23, 40, 55, 69, 83 };
            for(int i = 0; i < lucky.Length; i++)
                Maps[lucky[i]] = 1;
            //2 地雷
            int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };
            for (int i = 0; i < landMine.Length; i++)
                Maps[landMine[i]] = 2;
            //3 暂停
            int[] puase = { 9, 27, 60, 93 };
            for (int i = 0; i < puase.Length; i++)
                Maps[puase[i]] = 3;
            //4 时空隧道
            int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };
            for (int i = 0; i < timeTunnel.Length; i++)
                Maps[timeTunnel[i]] = 4;
        }
        #endregion

三、绘制飞行棋地图


绘制飞行棋地图这里技术含量不高,主要是for循环和switch语句的使用。只是有一个需要注意的点:

在绘制每一个关卡的时候,一定要先打印出玩家的位置,再在其他位置打印地图中各个关卡。

这种才能看起来玩家确实是在玩这个游戏。

 //环节三:切实的画游戏地图  —— 总共是100个关卡,画每个关卡之前,一定要先画玩家的位置
        public static void DrawMap()
        {
            Console.WriteLine("图例:幸运轮盘:◎ 地雷:☆ 暂停:△ 时空隧道:◆");
            //第一横行 0 ~ 30
            //绘制具体的每一个关卡 因为要重复使用绘制的逻辑,因此加载为方法
            for (int i = 0; i < 30; i++)
            {
                Console.Write(DrawEveryGrid(i));
            }
            //换行
            Console.WriteLine();
            //绘制第一竖行
            for(int i = 30;i < 35; i++)
            {
                //每行的0到29绘制空格,第30个方格绘制具体关卡
                for (int j = 0; j < 29; j++) Console.Write("  ");
                Console.Write(DrawEveryGrid(i));
                //小细节,画完每个竖行,都应该换行
                Console.WriteLine();
            }
            //绘制第二横行
            for(int i = 64;i >= 35;i--)
            {
                Console.Write(DrawEveryGrid(i));
            }
            Console.WriteLine();
            //绘制第二竖行
            for(int i = 65;i < 70;i++)
            {
                Console.WriteLine(DrawEveryGrid(i));
            }
            //绘制第三横行
            for (int i = 70; i < 100; i++)
                Console.Write(DrawEveryGrid(i));
            Console.WriteLine();
        }
        //绘制走到每个关卡的逻辑
        public static string DrawEveryGrid(int i)
        #region 绘制每个关卡的逻辑
        {
            string str = "";
            //如果玩家在同一个位置,使用<>表示
            //之前只是放了一个if ,就错了
            if (PlayPos[0] == PlayPos[1] && PlayPos[0] == i)
                str = "<>";
            //其他就单独绘制玩家A和玩家B的位置信息
            else if (PlayPos[0] == i)
                str = "A";
            else if (PlayPos[1] == i)
                str = "B";
            //获取当前位置的信息,switch匹配打印出相应的关卡
            else
            {
                switch (Maps[i])
                {
                    case 0:
                        Console.ForegroundColor = ConsoleColor.DarkYellow;
                        str = "□";
                        break;
                    case 1:
                        Console.ForegroundColor = ConsoleColor.Green;
                        str = "◎";
                        break;
                    case 2:
                        Console.ForegroundColor = ConsoleColor.Red;
                        str = "☆";
                        break;
                    case 3:
                        Console.ForegroundColor = ConsoleColor.Blue;
                        str = "△";
                        break;
                    case 4:
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        str = "◆";
                        break;
                }//switch
            }
            return str;
        }//方法
        #endregion 

四、玩游戏具体逻辑


到了玩家具体开始在地图上掷骰子,玩这个飞行棋的游戏的时候,整体稍微变得有点复杂了,但是跟着咱们之前梳理的流程图走下去,不会出现越写越凌乱的情况的。

① 创建两个玩家角色

既然是双人游戏,那么创建两个游戏对象是必要的环节了。

这里主要是积累程序设计的思想。

程序源于生活,也用于生活。那么玩家取名为空、玩家名字重复等情况,应该避免

        public static void CreatePlayer()
        {
            Console.WriteLine("请输入第一个玩家的姓名(按回车键继续):");
            PlayNames[0] = Console.ReadLine();
            while(Enumerable.SequenceEqual(PlayNames[0]," ")) 
            {
                Console.WriteLine("玩家姓名不可以为空,请重新输入");
                PlayNames[0] = Console.ReadLine();
            }
            Console.WriteLine();
            Console.WriteLine("请输入第二个玩家的姓名(按回车键继续):");
            PlayNames[1] = Console.ReadLine();
            while (PlayNames[1] == " ")
            {
                    Console.WriteLine("玩家姓名不可以为空,请重新输入");
                    PlayNames[1] = Console.ReadLine();
            }
            while(PlayNames[1] == PlayNames[0])
            {
                Console.WriteLine("玩家2姓名不可以和玩家1姓名重复,请重新输入");
                PlayNames[1] = Console.ReadLine();
            }
        }

② 具体走到每个关卡触发的结果

这个环节是具体的去落实游戏规则。


图例:幸运轮盘:◎ 地雷:☆ 暂停:△ 时空隧道:◆

游戏规则:

如果玩家A踩到玩家B,玩家B退6格

如果玩家踩中地雷。退6格

如果玩家踩进时空隧道,进10格

如果玩家踩到幸运轮盘, 1 交换位置,2 轰炸对方(使对方退6格)

如果玩家踩到了暂停,暂停一个回合

如果玩家踩到了方块,走到当前位置,什么都不发生


值得积累的知识点

1、按下任意键继续时,要在ReadKey中加入参数true

 Console.ReadKey(true);

倘若不加参数true,在按下任意键之后,是这种效果

微信图片_20221020132548.png

2、获取随机数需要通过Random类造对象实例,随机数的范围用Next函数确定,其区间左闭右开

      Random random = new Random();
            int ResultNum = random.Next(1, 7);
 //具体玩游戏的逻辑
        public static void PlayGame(int PlayID)
        {
            Console.ResetColor();
            Console.WriteLine("玩家{0}按下任意键掷骰子:", PlayNames[PlayID]);
            Console.ReadKey(true);//加了这个参数之后,会不显示出任意键的值
            Random random = new Random();
            int ResultNum = random.Next(1, 7);
            Console.WriteLine("玩家{0}掷出的结果是{1}", PlayNames[PlayID], ResultNum);
            Console.WriteLine("按下任意键,玩家{0}开始在棋盘上移动",PlayNames[PlayID]);
            Console.ReadKey(true);
            //处理掷骰子后玩家的移动
            PlayPos[PlayID] += ResultNum;
            TurnRight();
            Console.WriteLine("玩家{0}移动完啦,按任意键继续游戏",PlayNames[PlayID]);
            //处理移动之后,在地图之后触发的关卡
            //玩家可以踩到 另一个玩家、普通方块、幸运轮盘、地雷、暂停、时空隧道
            //踩到另一个玩家,另一个玩家退后6格
            if(PlayPos[PlayID] == PlayPos[1 - PlayID])
            {
                Console.WriteLine("玩家{0}踩到了玩家{1},玩家{2}退回6格", PlayNames[0], PlayNames[1],PlayNames[1]);
                PlayPos[1] -= 6;
                //这里存在一步异常处理的矫正,玩家不能退出地图,也不能超出地图
                TurnRight();
                Console.ReadKey(true);
            }
            else //踩到关卡
            {
                switch (Maps[PlayPos[PlayID]])
                {
                    case 0://踩到普通方块
                        Console.WriteLine("玩家{0}猜中的普通方块,正常到达该位置",PlayNames[PlayID]);
                        Console.ReadKey(true);
                        break;
                    case 1://踩到幸运盘
                        Console.WriteLine("玩家{0}踩到了幸运轮盘,请选择:1 - 交换位置  2 - 轰炸对方(对手退回6格)",PlayNames[PlayID]);
                        Console.ReadKey(true);
                        string choice = Console.ReadLine();
                        if (choice == "1")
                        {
                            Console.WriteLine("玩家{0}选择与玩家{1}交换位置", PlayNames[PlayID], PlayNames[1 - PlayID]);
                            Console.WriteLine("按下任意键执行操作");
                            Console.ReadKey(true);
                            int temp = PlayPos[PlayID];
                            PlayPos[PlayID] = PlayPos[1 - PlayID];
                            PlayPos[1 - PlayID] = temp;
                            Console.WriteLine("操作执行完成,按任意键继续游戏");
                            Console.ReadKey(true);
                            break;
                        }
                        else if (choice == "2")
                        {
                            Console.WriteLine("玩家{0}选择轰炸玩家{1}", PlayNames[PlayID], PlayNames[1 - PlayID]);
                            Console.WriteLine("按下任意键执行操作");
                            PlayPos[1 - PlayID] -= 6;
                            TurnRight();
                            Console.WriteLine("操作执行完成,按任意键继续游戏");
                            Console.ReadKey(true);
                            break;
                        }
                        else
                        {
                            Console.WriteLine("请遵守游戏规则,在1和2之间进行选择");
                            Console.ReadKey(true);
                            break;
                        }
                    case 2://踩到地雷
                        Console.WriteLine("玩家{0}踩到地雷,倒退6格", PlayNames[PlayID]) ;
                        Console.ReadKey(true);
                        PlayPos[PlayID] -= 6;
                        TurnRight();
                        Console.WriteLine("玩家倒退完毕。按任意键继续游戏");
                        Console.ReadKey(true);
                        break;
                    case 3://踩到暂停
                        Console.WriteLine("玩家{0}踩到暂停,暂停一个回合", PlayNames[PlayID]);
                        Flags[PlayID] = true;
                        Console.ReadKey(true);
                        break;
                    case 4://踩到时空隧道
                        Console.WriteLine("玩家{0}踩到时空隧道,前进10格", PlayNames[PlayID]);
                        PlayPos[PlayID] += 10;
                        TurnRight();
                        Console.WriteLine("玩家前进完毕,按任意键继续游戏");
                        Console.ReadKey(true);
                        break;
                }//switch
            }//if - else
            //当前轮的关卡处理完成之后。清屏,重新打印
            Console.Clear();
            DrawMap();//重新画地图

③ 判断胜利

两个玩家是放在一个长度为100的数组表示的飞行棋棋盘进行游戏的。那么当有玩家的索引变成100的时候,TA就获得了最终的胜利。

需要注意的点是:因为关卡中有暂停关卡,当玩家踩到暂停了,他就不能够参与当前轮的掷骰子

      while(PlayPos[0] < 100 && PlayPos[1] < 100)
            {
                if (!Flags[0])PlayGame(0);
                else Flags[0] = false;
                //判断胜利的条件
                if (PlayPos[0] == 100)
                {
                    Console.WriteLine("恭喜玩家{0}获得胜利", PlayNames[0]);
                    break;
                }
                if (!Flags[1]) PlayGame(1);
                else Flags[1] = false;
                    if (PlayPos[1] == 100)
                {
                    Console.WriteLine("恭喜玩家{0}获得胜利", PlayNames[1]);
                    break;
                }
            }

④ 回首调优

无论如何,玩家在棋盘中移动的时候,是不能到棋盘之外的位置,因此在玩家进行位置移动的代码后方,都应该判断新出现的位置是否合法。

  //异常处理,矫正玩家位置
        public static void TurnRight()
        {
            if (PlayPos[0] < 0) PlayPos[0] = 0;
            if (PlayPos[0] >= 99) PlayPos[0] = 99;
            if(PlayPos[1] < 0) PlayPos[1] = 0;
            if (PlayPos[1] >= 99) PlayPos[1] = 99;
        }

总结


整个飞行棋项目的gitee地址

1、写项目流程图蛮重要的吧,跟着自己梳理好的流程板块去逐一落实代码,不会出现迷失在项目中的情况

2、积累修改字体背景颜色、字体文本颜色

3、按任意键后在控制台无显示依赖于ReadKey函数中传入参数true

相关文章
|
人工智能 开发框架 物联网
为什么 C# 可能是最好的第一编程语言
C# 是一个全面领域的全能型语言,结合新时代的 .NET 平台,与时俱进的发展创新,未来无限可期!对于带着有色眼镜看待的人们,是否该刮目相看了呢?下面看看行业大佬关于 .NET 的解说。
1235 2
为什么 C# 可能是最好的第一编程语言
|
7月前
|
Java Go C#
编程语言C#、C++、Java、Python、go 选择哪个好?
我想说的是,不论选择哪种编程语言,决定选择的都是你最终的目的,做选择之前,先充分调研每一个选择项,再做选择思路就会非常清晰了。
144 3
|
7月前
|
人工智能 缓存 Java
技术经验解读:【转】详细解析用C#写的小游戏《彩色连珠》(附源代码)
技术经验解读:【转】详细解析用C#写的小游戏《彩色连珠》(附源代码)
31 0
|
8月前
|
人工智能 Java 物联网
C# 成为 2023 年度编程语言之王!
2023 年 TIOBE 年度编程语言已经正式公布,C# 在稳居前 10 名 20 多年之久后,首次摘下年度编程语言桂冠。TIOBE 数据显示,C# 在 2023 年的涨幅达 1.43%,远超过竞争对手 Scratch 的 0.83% 和 Fortran 的 0.64%。
496 1
C# 成为 2023 年度编程语言之王!
|
8月前
|
开发框架 Java .NET
C#编程语言的优势与C++对比
C#编程语言的优势与C++对比
203 0
|
8月前
|
搜索推荐 Java C#
C#有望成为2023年的编程语言之王
C#有望成为2023年的编程语言之王
127 1
C#有望成为2023年的编程语言之王
|
8月前
|
关系型数据库 C# 数据库
2023 年度数据库 PostgreSQL 遇到年度编程语言 C# 会发生什么样的火花?
2023 年度数据库 PostgreSQL 遇到年度编程语言 C# 会发生什么样的火花?分析这俩的发展趋势,技术生态,社区活跃度,特别是国产化信创领域的支持度?
90 1
|
8月前
|
人工智能 搜索推荐 Java
C# 最有可能摘得“年度编程语言”,Python、Java 正在让位,TIOBE 12 月编程语言榜单最新预测来了!
C# 最有可能摘得“年度编程语言”,Python、Java 正在让位,TIOBE 12 月编程语言榜单最新预测来了!
63 1
|
8月前
|
物联网 Linux 编译器
C#成为2023年年度编程语言之王
C#成为2023年年度编程语言之王
|
机器学习/深度学习 Java C#
C# 编程语言简介
C# 是一种通用的、静态类型的编程语言,由 Microsoft 开发。它是为了构建 .NET 应用程序而设计的,同时也可以用于开发跨平台应用、游戏和桌面应用。C# 具有简洁、现代化的语法以及强大的面向对象编程特性,使得开发者能够快速高效地构建各种类型的应用。
122 0