用之前学习的内容做一个飞行棋游戏


java 模拟飞行棋 规则 飞行棋游戏编程_初始化

 当我们打开程序,显示出飞行棋游戏1.0这一部分内容,然后是要求用户输入玩家姓名

java 模拟飞行棋 规则 飞行棋游戏编程_学习_02

当玩家姓名输入无误之后,显示如上界面。这一部分为玩家棋子和地图。

可以看到输入的玩家姓名并不在控制台上,要想实现这样的效果,我们就需要清空控制台,并重新将游戏头打印在上面。

输入这样一行代码就能清空控制台:Console.Clear();

 所以我们要把游戏头封装成一个方法。

public static void GameShow()
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            //给文字上色,前景色,ConsoleColor是一个枚举
            Console.WriteLine("**************************");
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("**************************");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("******飞行棋游戏1.0 ******");
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("**************************");
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("**************************");
        }

然后处理如何输入玩家姓名的问题。

因为是两个玩家玩,所以考虑几个问题。首先是玩家A姓名不能为空,如果为空,要求用户重新输入。玩家A的姓名输入好之后,输入玩家B姓名,玩家B姓名不能为空,并且不能为空,如果为空或者和玩家A相同,则要求用户重新输入。

在class中声明一个静态字段,用来存储两个玩家的姓名,这样我们就可以在全局使用这两个玩家的姓名。

public static string[] PlayNames = new string[2];

然后我们用两个while语句来判断输入的内容

static void Main(string[] args)
        {
            GameShow();
            #region 输入玩家姓名
            Console.WriteLine("请输入玩家A的姓名");
            PlayNames[0] = Console.ReadLine();
            while (PlayNames[0] == "")
            {
                Console.WriteLine("玩家A的姓名不能为空,请重新输入");
                PlayNames[0] = Console.ReadLine();
            }
            Console.WriteLine("请输入玩家B的姓名");
            PlayNames[1] = Console.ReadLine();
            while (PlayNames[1] == "" || PlayNames[1] == PlayNames[0])
            {
                if (PlayNames[1] == "")
                {
                    Console.WriteLine("玩家B的姓名不能为空,请重新输入");
                    PlayNames[1] = Console.ReadLine();
                }
                else
                {
                    Console.WriteLine("玩家B的姓名不能和玩家A相同,请重新输入");
                    PlayNames[1] = Console.ReadLine();
                }
            }
            #endregion
        }

好了,现在输入玩家姓名ok,首先清屏,然后画地图。

声明一个静态字段来存储地图,一共100格

public static int[] Maps = new int[100];

现在这个数组中,存储的元素默认都是0,所以需要初始化地图,也就是给数组中固定的位置赋值。初始化之后,有五种值,0 1 2 3 4

写一个方法:

public static void InitailMap()
        {
            int[] luckyturn = { 6, 23, 40, 55, 69, 83 };//幸运轮盘,这个数组中元素是地图元素的下标
            for (int i = 0; i < luckyturn.Length; i++)
            {
                Maps[luckyturn[i]] = 1;
            }
            int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };//地雷
            for (int i = 0; i < landMine.Length; i++)
            {
                Maps[landMine[i]] = 2;
            }
            int[] pause = { 9, 27, 60, 93 };//暂停
            for (int i = 0; i < pause.Length; i++)
            {
                Maps[pause[i]] = 3;
            }
            int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };//时空跳跃
            for (int i = 0; i < timeTunnel.Length; i++)
            {
                Maps[timeTunnel[i]] = 4;
            }
        }

地图已经初始化完成了,现在需要的是给地图中不同值的地方画上图案。

在画图案之前先判断A和B的位置,如果相同就画两个半角的<>.

为了定位A和B,声明一个静态字段,标记玩家坐标

public static int[] PlayerPos = new int[2];
//PlayPos[0]玩家a的位置,PlayPos[1]玩家b的位置

但是只有这样的话,条件不严谨,当AB在地图两端的时候可能会超出地图范围,需要限制,限制的方法后面再写。所以AB还必须在坐标上,这里的i是就是地图坐标。

先写第一行的地图

public static void DrawMap()
{
    Console.WriteLine("图例:幸运轮盘:◎  地雷:★  暂停:▲  时空隧道:卐 ");
    #region 第一横行0-29
    for (int i = 0; i < 30; i++)
    {
        if ((PlayerPos[0] == PlayerPos[1]) && PlayerPos[1] == i)
        {
            Console。Write("<>");
        }
        else if (PlayerPos[0] == i)
        {
         //shift+空格全角
            Console.Write("A");
        }
        else if (PlayerPos[1] == i)
        {
            Console.Write("B");
        }
            else
            {
                switch (Maps[i])
                {
                    case 0:
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write("□");//普通
                        break;
                    case 1:
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write("◎");//幸运
                        break;
                    case 2:
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.Write("★");//地雷
                        break;
                    case 3:
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.Write("▲");//暂停
                        break;
                    case 4:
                        Console.ForegroundColor = ConsoleColor.Blue;
                        Console.Write("卐");//时空
                        break;
            }//switch
        }//else
    }
    Console.WriteLine();//换行
    #endregion
            
}

其实这里可以把这个画图案的步骤抽象出一个方法,这样在写后面地图的时候只需要调用这个方法就可以了,会减少很多代码数量。

public static string DrawStringMap(int i)
        {
            string str = "";
            //如果玩家a和b坐标相同,并且都在地图上,画一个<>
            if ((PlayerPos[0] == PlayerPos[1]) && PlayerPos[1] == i)
            {
                str = "<>";
            }
            else if (PlayerPos[0] == i)
            {
                //shift+空格全角
                str = "A";
            }
            else if (PlayerPos[1] == i)
            {
                str = "B";
            }
            else
            {
                switch (Maps[i])
                {
                    case 0:
                        Console.ForegroundColor = ConsoleColor.White;
                        str = "□";//普通
                        break;
                    case 1:
                        Console.ForegroundColor = ConsoleColor.Red;
                        str = "◎";//幸运
                        break;
                    case 2:
                        Console.ForegroundColor = ConsoleColor.Green;
                        str = "★";//地雷
                        break;
                    case 3:
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        str = "▲";//暂停
                        break;
                    case 4:
                        Console.ForegroundColor = ConsoleColor.Blue;
                        str = "卐";//时空
                        break;
                }//switch
            }//else
            return str;
        }

 然后写地图的其他部分

public static void DrawMap()
        {
            Console.WriteLine("图例:幸运轮盘:◎  地雷:★  暂停:▲  时空隧道:卐 ");
            #region 第一横行0-29
            for (int i = 0; i < 30; i++)
            {
                Console.Write(DrawStringMap(i));
            }
            Console.WriteLine();//换行
            #endregion
            #region 第一竖列30-34
            for (int i = 30; i < 35; i++)
            {
                //画空格
                for (int j = 0; j < 29; j++)
                {
                    Console.Write("  ");
                }
                Console.WriteLine(DrawStringMap(i));
            }
            #endregion
            #region 第二横行35-64
            for (int i = 64 ; i >= 35; i--)
            {
                Console.Write(DrawStringMap(i));
            }
            Console.WriteLine();//换行
            #endregion
            #region 第二竖列65-69
            for (int i = 65; i < 70; i++)
            {
                Console.WriteLine(DrawStringMap(i));
            }
            #endregion
            #region 第三横行70-99
            for (int i = 70; i < 100; i++)
            {
                Console.Write(DrawStringMap(i));
            }
            #endregion
            Console.WriteLine();
        }

写一个方法来表示A和B的棋子

public static void Players()
        {
            Console.WriteLine("玩家{0}的士兵用A表示", PlayerNames[0]);
            Console.WriteLine("玩家{0}的士兵用B表示", PlayerNames[1]);
        }

现在可以写玩游戏的部分了。

因为是两个人玩游戏,所以要让一个人玩完之后,让另一个人玩,并且当两个人没有人在终点的时候,游戏一直进行。

用一个while循环来写

while (PlayerPos[0] < 100 && PlayerPos[1] < 100)
            {
                
                    PlayGame(0);

                    PlayGame(1);

            }

把玩游戏抽象成方法

游戏分为这样几个部分,玩家掷骰子,根据掷出的数字,玩家行动,玩家行动完。

玩家行动有踩到玩家和踩到关卡两种情况。

踩到关卡有5种情况。

每个人玩完之后,清屏,重新打印游戏头,玩家,地图。

public static void PlayGame(int playNumber)
        {
            Random r = new Random();
            int rNumber = r.Next(1, 7);//随机数
            Console.WriteLine("玩家{0}按任意键开始掷骰子", PlayerNames[playNumber]);
            Console.ReadKey(true);
            Console.WriteLine("玩家{0}掷出了{1}", PlayerNames[playNumber], rNumber);
            PlayerPos[playNumber] += rNumber;
            Console.ReadKey(true);
            Console.WriteLine("玩家{0}按任意键开始行动", PlayerNames[playNumber]);
            Console.ReadKey(true);
            Console.WriteLine("玩家{0}行动完了", PlayerNames[playNumber]);
            Console.ReadKey(true);
            if (PlayerPos[playNumber] == PlayerPos[1-playNumber])//玩家a踩到玩家b,b退6格
            {
                Console.WriteLine("玩家{0}踩到了玩家{1},玩家{2}倒退6格", PlayerNames[playNumber], PlayerNames[1-playNumber], PlayerNames[1 - playNumber]);
                PlayerPos[1 - playNumber] -= 6;
                Console.ReadKey(true);
            }
            else//踩到关卡
            {
                switch (Maps[PlayerPos[playNumber]])//01234
                {
                    case 0://踩到空格安全
                        Console.WriteLine("玩家{0}踩到了方块,安全", PlayerNames[playNumber]);
                        Console.ReadKey(true);
                        break;
                    case 1://踩到幸运,1--交换位置 2--轰炸对手
                        Console.WriteLine("玩家{0}踩到了幸运轮盘,请选择 1--交换位置 2--轰炸对手", PlayerNames[playNumber]);
                        string s = Console.ReadLine();
                        while (true)
                        {
                            if (s == "1")
                            {
                                Console.WriteLine("玩家{0}选择了交换位置",PlayerNames[playNumber]);
                                int temp = PlayerPos[playNumber];
                                PlayerPos[playNumber] = PlayerPos[1 - playNumber];
                                PlayerPos[1 - playNumber] = temp;
                                Console.ReadKey(true);
                                Console.WriteLine("交换完成");
                                Console.ReadKey(true);
                                break;
                            }
                            else if (s == "2")
                            {
                                Console.WriteLine("玩家{0}选择了轰炸对手,玩家{1}倒退6格", PlayerNames[playNumber], PlayerNames[1 - playNumber]);
                                PlayerPos[1 - playNumber] -= 6;
                                Console.ReadKey(true);
                                break;
                            }
                            else
                            {
                                Console.WriteLine("只能输入1--交换位置 2--轰炸对手,请重新输入");
                                s = Console.ReadLine();
                                break;
                            }
                        }
                        break;
                    case 2://踩到地雷,后退6格
                        Console.WriteLine("玩家{0}踩到了地雷,倒退6格", PlayerNames[playNumber]);
                        PlayerPos[playNumber] -= 6;
                        Console.ReadKey(true);
                        break;
                    case 3://踩到暂停,停一回合
                        Console.WriteLine("玩家{0}踩到了暂停,暂停一回合", PlayerNames[playNumber]);
                        ??
                        Console.ReadKey(true);
                        break;
                    case 4://踩到时空,前进10格
                        Console.WriteLine("玩家{0}踩到了时空穿梭,前进10格", PlayerNames[playNumber]);
                        PlayerPos[playNumber] += 10;
                        Console.ReadKey(true);
                        break;
                }//switch
            }//else
            Console.Clear();
            GameShow();
            Players();
            DrawMap();
        }

这里的暂停我们稍后来写。


再写一个方法,来限制玩家出现在地图中

public static void ChangePos()
        {
            if (PlayerPos[0] < 0)
            {
                PlayerPos[0] = 0;
            }
            if (PlayerPos[1] < 0)
            {
                PlayerPos[1] = 0;
            }
            if (PlayerPos[0] > 99)
            {
                PlayerPos[0] = 99;
            }
            if (PlayerPos[1] > 99)
            {
                PlayerPos[1] = 99;
            }
        }

在玩游戏这个方法中调用,只要玩家的坐标发生变化,就调用一次。

java 模拟飞行棋 规则 飞行棋游戏编程_i++_03


 最后一个问题,如何让玩家轮流去玩?

声明一个bool类型的静态字段来标记玩家

public static bool[] Flags = new bool[2]; //默认是false;
while (PlayerPos[0] < 100 && PlayerPos[1] < 100)
            {
                if (Flags[0] == false)
                {
                    PlayGame(0);
                }

                if (Flags[1] == false)
                {
                    PlayGame(1);
                }
            }

现在,可以写之前没写的暂停了。

case 3://踩到暂停,停一回合
    Console.WriteLine("玩家{0}踩到了暂停,暂停一回合", PlayerNames[playNumber]);
    Flags[playNumber] = true;
    Console.ReadKey(true);

但是这样的话,虽然暂停实现了,但是轮流玩游戏却依然没实现。

我们需要把标记玩家从新赋值false。

while (PlayerPos[0] < 100 && PlayerPos[1] < 100)
            {
                if (Flags[0] == false)
                {
                    PlayGame(0);
                }
                else
                {
                    Flags[0] = false;
                }
                if (PlayerPos[0] == 99)
                {
                    Console.WriteLine("玩家{0}战胜了玩家{1}", PlayerNames[0], PlayerNames[1]);
                }
                if (Flags[1] == false)
                {
                    PlayGame(1);
                }
                else
                {
                    Flags[1] = false;
                }
                if (PlayerPos[1] == 99)
                {
                    Console.WriteLine("玩家{0}战胜了玩家{1}", PlayerNames[1], PlayerNames[0]);
                }
            }

这样所有的流程就都实现了!