目录
– 游戏头
– 初始化地图
– 绘制地图
– 输入姓名
– 核心游戏机制
– 最后调整Main函数
– 总结
游戏头
- 作用: 输出游戏初始界面
Console.ForegroundColor = ConsoleColor.Cyan;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine(@"
********************************************
********************************************
*******飞行棋游戏v1.0 By zhyDaDa***********
********************************************
********************************************
");
Console.ForegroundColor
和Console.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();
}
总结
- 除了字符无法设置前景和后景色, 其他都不错
- 优化的话可以考虑更多的选项
- 以及, *在可以通关的前提下”的随机地图(防止一整排的地雷的出现)