zhyDaDa的个人站点

目录
游戏头
初始化地图
绘制地图
输入姓名
核心游戏机制
最后调整Main函数
总结

游戏头

  • 作用: 输出游戏初始界面
Console.ForegroundColor = ConsoleColor.Cyan;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine(@"
********************************************
********************************************
*******飞行棋游戏v1.0  By zhyDaDa***********
********************************************
********************************************
");

Console.ForegroundColorConsole.BackgroundColor分别用于设置控制台输出的前景色背景色
@的使用能按照原格式输出
但要实现彩虹配色, 就得每输出一行, 就设置一遍前景色

初始化地图

  • 作用: 加载地图所需要的资源, 为画地图做准备
  • 地图的数据采用int存储(string更困难一些)
  • 数字变成字符串的过程, 就是初始化地图的过程
  • 由于所有方法都需要操作Maps数组, 因此建议使用静态字段模拟全局变量
  • 定义地图的方法: 把存在特殊关卡的位置全部标出来
/// <summary>
/// 初始化地图, 修改地图数组
/// </summary>
public static void InitiateMap()
{
    int[] luckyTurn = { 6, 23, 40, 55, 69, 83 };    //幸运轮盘
    AddSpecialToMaps(luckyTurn, 1);
    int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };     //地雷
    AddSpecialToMaps(landMine, 2);
    int[] pause = { 9, 27, 60, 93 };    //暂停
    AddSpecialToMaps(pause, 3);
    int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };  //时空隧道
    AddSpecialToMaps(timeTunnel, 4);
}

/// <summary>
/// 输入一个数组, 把数组中的每个数字对应的地图位置
/// 修改为输入的数值
/// </summary>
/// <param name="array">元素是若干索引</param>
/// <param name="sign">要改为的数字</param>
public static void AddSpecialToMaps(int[] array, int sign)
{
    for (int i = 0; i < array.Length; i++)
    {
        Maps[array[i]] = sign;
    }
}

绘制地图

  • 符号最好是全角的
/// <summary>
/// 画地图
/// </summary>
public static void DrawMap()
{
    Console.ForegroundColor = ConsoleColor.White;
    //画第一行
    for (int i = 0; i < 30; i++)
    {

        //如果两位玩家位置重合, 且都在地图上画一对尖括号
        if (PlayerPos[0] == PlayerPos[1] && PlayerPos[0]==i)
        {
            Console.Write("<>");
        }
        else if (PlayerPos[0] == i)
        {
            Console.Write("A");
        }
        else if (PlayerPos[0] == i)
        {
            Console.Write("B");
        }
        else
        {
            switch (Maps[i])
            {
                case 0:
                    Console.Write("□");
                    break;
                case 1:
                    Console.Write("⨷");
                    break;
                case 2:
                    Console.Write("☆");
                    break;
                case 3:
                    Console.Write("∆");
                    break;
                case 4:
                    Console.Write("卐");
                    break;
            }
        }
    }


}//这是方法的括号
  • 这里需要将方法抽离出来
  • 值得注意的是: 方法中最好不要打印控制台! 因此采用返回值的形式
/// <summary>
/// 返回要画出的一个格子
/// </summary>
/// <param name="i">对应的位置</param>
/// <returns>对应的格子的string</returns>
public static string TheStringOfTheMap(int i)
{
    string str = "";
    //如果两位玩家位置重合, 且都在地图上画一对尖括号
    if (PlayerPos[0] == PlayerPos[1] && PlayerPos[0] == i)
    {
        str = "§";
    }
    else if (PlayerPos[0] == i)
    {
        str = "A";
    }
    else if (PlayerPos[0] == i)
    {
        str = "B";
    }
    else
    {
        switch (Maps[i])
        {
            case 0:
                //Console.ForegroundColor = ConsoleColor.White;
                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.DarkMagenta;
                str = "卐";
                break;
        }
    }

    return str;
}

p.s. 事实上, 要想让这些奇怪的符号在控制台排列整齐, 需要调整字体为黑体(win11特有)
p.s.p.s. 那些个//是原本想要变换颜色的, 不知怎么的产生了奇怪的错位, 于是乎放弃
p.s.p.s.p.s. 说不定以后自己(or读者)有可能调试成功, 我记录一下我逐步调试的发现:

就是当变色之后, 下一个要打印的字符会把之前打印的所有字符当成是半角的字符
ta就会跑到前面去, 接下来的字符就会和先前打印的重合造成重影

  • 小竖行的处理相对简单, 只要打印空格就行
  • 请注意空格数量
//换行
Console.WriteLine();

//画第一个数列(就一个)
for (int i = 30; i < 35; i++)
{
    for (int j = 0; j <= 28; j++)
    {
        Console.Write("  ");
    }
    Console.Write(TheStringOfTheMap(i));
    Console.WriteLine();
}

输入姓名

  • 经典的判断
  • 小问题: 全部输入空格的话其实应该是不被允许的(虽然这样没什么不好)
#region 输入玩家姓名
Console.WriteLine("请输入玩家A的姓名");
PlayerNames[0] = Console.ReadLine();
while (PlayerNames[0] == "")
{
    Console.WriteLine("玩家姓名不得为空, 请重新输入");
    PlayerNames[0] = Console.ReadLine();
}

Console.WriteLine("请输入玩家B的姓名");
PlayerNames[1] = Console.ReadLine();
while (PlayerNames[1] == ""|| PlayerNames[1]== PlayerNames[0])
{
    if (PlayerNames[1] == "")
    {
        Console.WriteLine("玩家姓名不得为空, 请重新输入");
    }
    else
    {
        Console.WriteLine("玩家姓名不得相同, 请重新输入");
    }
    PlayerNames[1] = Console.ReadLine();
}
#endregion

核心游戏机制

public static void PlayGame(int playerNumber)
{
    Console.WriteLine("{0}按任意键开始投掷骰子", PlayerNames[playerNumber]);
    Console.ReadKey(true);
    Random r = new Random();
    int rNumber = r.Next(1, 7);
    Console.WriteLine("{0}投出了点数{1}, 并向前移动{1}格, 按任意键行动", PlayerNames[playerNumber], rNumber);
    PlayerPos[playerNumber] += rNumber;
    ChangePos();
    Console.ReadKey(true);
    //判断踩到的格子的情况
    if (PlayerPos[0] == PlayerPos[1])
    {
        Console.WriteLine("玩家{0}踩到了玩家{1}, 玩家{2}退6格", PlayerNames[playerNumber], PlayerNames[1 - playerNumber], PlayerNames[1 - playerNumber]);
        PlayerPos[1 - playerNumber] -= 6;
        ChangePos();
        Console.ReadKey(true);
    }
    else
    {
        switch (Maps[PlayerPos[playerNumber]])
        {
            case 0:
                Console.WriteLine("玩家{0}踩到了普通方块, 安全", PlayerNames[playerNumber]);
                Console.ReadKey(true);
                break;
            case 1:
                Console.WriteLine("玩家{0}踩到了幸运轮盘, 请选择:\n1---交换位置\t2---轰炸对方", PlayerNames[playerNumber]);
                string input = Console.ReadLine();
                while (true)
                {
                    if (input == "1")
                    {
                        Console.WriteLine("玩家{0}和玩家{1}互换位置", PlayerNames[playerNumber], PlayerNames[1 - playerNumber]);
                        Console.ReadKey(true);
                        int temp = PlayerPos[0];
                        PlayerPos[0] = PlayerPos[1];
                        PlayerPos[1] = temp;
                        Console.WriteLine("交换成功! 按任意键继续");
                        Console.ReadKey(true);
                        break;
                    }
                    else if (input == "2")
                    {
                        Console.WriteLine("玩家{0}轰炸了玩家{1}", PlayerNames[playerNumber], PlayerNames[1 - playerNumber]);
                        Console.ReadKey(true);
                        PlayerPos[1-playerNumber] -= 6;
                        ChangePos();
                        Console.WriteLine("玩家{0}退了6格! 按任意键继续", PlayerNames[1 - playerNumber]);
                        Console.ReadKey(true);
                        break;
                    }
                    Console.WriteLine("只允许输入1或2, 1---交换位置\t2---轰炸对方");
                    input = Console.ReadLine();
                }
                break;
            case 2:
                Console.WriteLine("玩家{0}踩到了地雷, 退六格", PlayerNames[playerNumber]);
                PlayerPos[playerNumber] -= 6;
                ChangePos();
                Console.ReadKey(true);
                break;
            case 3:
                Console.WriteLine("玩家{0}踩到了暂停, 下一回合跳过", PlayerNames[playerNumber]);
                Flags[playerNumber] = true;
                Console.ReadKey(true);
                break;
            case 4:
                Console.WriteLine("玩家{0}踩到了时空隧道, 前进10格", PlayerNames[playerNumber]);
                PlayerPos[playerNumber] += 10;
                ChangePos();
                Console.ReadKey(true);
                break;
        }//switch的end
    }//判断的end

    ChangePos();
    Console.Clear();
    DrawMap();
}

为了防止出现被干出地图的情况发生
需要采用一个修正的机制

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

最后调整Main函数

static void Main()
{
    GameShow();
    Console.WriteLine();
    #region 输入玩家姓名
    Console.WriteLine("请输入玩家A的姓名");
    PlayerNames[0] = Console.ReadLine();
    while (PlayerNames[0] == "")
    {
        Console.WriteLine("玩家姓名不得为空, 请重新输入");
        PlayerNames[0] = Console.ReadLine();
    }

    Console.WriteLine("请输入玩家B的姓名");
    PlayerNames[1] = Console.ReadLine();
    while (PlayerNames[1] == "" || PlayerNames[1] == PlayerNames[0])
    {
        if (PlayerNames[1] == "")
        {
            Console.WriteLine("玩家姓名不得为空, 请重新输入");
        }
        else
        {
            Console.WriteLine("玩家姓名不得相同, 请重新输入");
        }
        PlayerNames[1] = Console.ReadLine();
    }
    #endregion
    //输入完姓名, 清屏
    Console.Clear();


    GameShow();
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("{0}的位置用A表示", PlayerNames[0]);
    Console.WriteLine("{0}的位置用B表示", PlayerNames[1]);
    Console.WriteLine("两人重合的位置用§表示");


    InitiateMap();
    DrawMap();

    //只要没到终点一直循环
    while (PlayerPos[0] < 99 && PlayerPos[1] < 99)
    {
        if (!Flags[0])
        {
            PlayGame(0);
        }
        else { Flags[0] = false; }
        if (PlayerPos[0] >= 99)
        {
            Console.BackgroundColor = ConsoleColor.Red;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("玩家{0}获胜!!!", PlayerNames[0]);
            break;
        }
        if (!Flags[1])
        {
            PlayGame(1);
        }
        else { Flags[1] = false; }
        if (PlayerPos[1] >= 99)
        {
            Console.BackgroundColor = ConsoleColor.Red;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("玩家{0}获胜!!!", PlayerNames[1]);
            break;
        }
    }

    Console.ReadKey();


}

总结

  • 除了字符无法设置前景和后景色, 其他都不错
  • 优化的话可以考虑更多的选项
  • 以及, *在可以通关的前提下”的随机地图(防止一整排的地雷的出现)
Avatar photo
我是 zhyDaDa

前端/UI/交互/独立游戏/JPOP/电吉他/游戏配乐/网球/纸牌魔术

发表回复