01 概要设计

 

1、显示欢迎界面

2、提示玩家A、B输入名字(判断玩家输入的名字是否合法)

3、用户输入合法的名字后,显示给用户

4、清屏,重新绘制界面,提示游戏开始

5、显示说明和图例

6、绘制地图之前,初始化关卡

7、绘制地图

8、玩家A和B轮流掷骰子

9、关卡效果

10、一方胜利,显示提示信息,游戏结束


 

02 详细设计

 

2.1 显示欢迎界面

       用多个Console.WriteLine();  语句在屏幕上显示一个简单界面。

并将此段代码写成方法,方便多次调用。

 

2.2 提示玩家A、B输入名字(判断玩家输入的名字是否合法)

  2.2.1  定义一个int[] 来存储用户输入的玩家A和玩家B的名字

  2.2.2  判断用于输入的名字是否合法

        1、判断A的名字是否为空。

    若为用户输入为空,提示用户重新输入;若不为空,继续下一步。此处设置while循环,以便重新输入。

        2、判断B的名字是否为空,并且不能与A重名。

若用户输入为空,提示用户重新输入;若用户输入与A重名,提示用户重新输入,知道输入合法为止。此处亦设置while循环。

 

2.3 用户输入合法的名字后,显示给用户

       若用户输入的名字合法,用Console.WriteLine() 语句显示用户刚才输入的A和B的名字。

 

2.4 清屏,重新绘制界面,提示游戏开始

       由于控制台界面大小有限,所以要清屏来保持界面的清爽简洁。

       清屏之后重新绘制界面,并提示游戏开始。

2.5 显示说明和图例

       在游戏开始之前,向用户显示说明文字和图例,便于用户更好的了解。

2.6 绘制地图之前,初始化关卡

       1、初始化游戏关卡,即设置每一个格各对应什么样的规则。为了便于区分各种关卡,给每个关卡分配一种小图标。

       2、本游戏设置了4种关卡,分别是幸运轮盘、地雷、暂停一次、时空隧道。

       3、游戏关卡应显示在游戏中的每个元素中,即分配到每个小格中。

       4、在设置和分配关卡之前应该先定义一个int[] 来存储地图的各元素。游戏中定义了一个int[] Map 来存储地图的各个元素。

       在int[] Map数组中,不同元素的值表示的意义不同,如下所示:

    当元素值为1时,输出幸运轮盘 ★

                2,地雷 ●

                3,暂停 △

                4,时空隧道 卍

                0,表示普通 □

       5、在设置关卡时,定义几个新数组,其值为Map[i]的下标i,存储地图中的关卡。

       6、在绘制地图时,需要先获得关卡的值。所以这里设置循环,将这几个数组中的值分别取出,再赋给Map数组。

        此处用for循环遍历数组。

 

2.7 绘制地图

    本游戏地图共100个元素,100个小格。分为3行2列呈S型排列,每行30个元素,每列5个元素。

       1、绘制第一行(0-29格)

              ①先判断A和B是否在这一格元素上

               要想判断A和B是否在第i格上,首先要知道A和B的位置坐标(下标),       所以要定义一个数组存储A和B的下标。

         这里不在方法中直接输出要绘制的元素符号,而是通过传参的方式返  回要绘制的符号。              

       第一种情况:如果A和B都在当前小格上,则返回 < > ;

"A";

    第三种情况:如果B在当前小格上,则返回全角符号B。

       第四种情况:如果A和B都不在当前小格上,则返回关卡图标或正常图标。在此之前需要先做判断。

              ②判断每一格元素的值

       因这里要返回5种元素,故用switch语句。返回0,表示普通 □ ;返回1,表示幸运轮盘 ★;返回2,表示地雷 ●;返回3,表示暂停 △;返回4,表示时空隧道 卍 。

 

       2、此处的列地图,要绘制29个双空格(即1个全角空格) + 1个地图小格

       3、绘制第二行,方法同第1步

       4、绘制第二列

       5、绘制第三行

 

2.8 玩家A和B轮流掷骰子

       2.8.1 掷骰子的流程分析

       A和B轮流掷骰子需要重复操作,故写成循环。循环条件是,A和B的坐标同时小于99。

       由于A和B轮流掷骰子,即A先掷一次,B掷再一次,循环往复。但是当A或B其中一个走到暂停时,就停一次,对方连掷两次。所以此处设置一个标志位来标记玩家是否走到暂停。

       定义一个数组bool[] isStop 来存储这个标志的两个值。默认情况下都为false,即A和B都没有走到暂停。

       ①如果任意一方走到暂停,就将其isStop[i]设为true;

       ②在循环中需要先判断isStop[i]的值,如果为false,就掷骰子,如果为true, 就停止掷骰子一次(即不执行掷骰子的代码),随后立即将其标志的值设为false。

       由于一开始是A先掷骰子,B再掷骰子,故在循环中应先判断A是否掷骰子的,后判断B是否掷骰子。

       还应注意,如果A掷完骰子后的坐标大于99,证明A已经走到地图终点,此时应break跳出循环。

       2.8.2  A或B掷骰子的方法

              1、掷骰子要产生一个[1,6] 的随机数

              2、用一个变量step来存放产生的随机数

              3、当玩家移动坐标改变时,及时更新step。

              4、当坐标改变时,要检测玩家是否踩到了对方或踩到了关卡。

                     这里将检测的代码写成方法,方便多次调用。

                     ①检测当前玩家是否踩到对方,若踩到对方,对方退起点。

           ②若没有踩到对方,则检测当前玩家是否走到某关卡。

             这里用switch语句做判断。

              5、当玩家踩到对方或处于关卡时,输出提示信息。

                     这里定义一个变量string msg 来存储提示信息。

              6、当玩家走到幸运轮盘时,提示让玩家按1或2键选择运气。此时玩家只能按1键或2键。这里增加了一个方法staticvoid ReadInput(int min, int max),检测玩家输入的数字是否在规定范围内。

 

2.9  关卡效果

       1、一方踩到另一方,被踩的一方退回到起点。

       2、幸运轮盘,可以按1或2键选择运气。按1键,与对方交换位置,按2键,轰炸对方,对方退6格。

       3、踩到地雷,退6格。

       4、走到暂停,暂停一次掷骰子。

       5、时空隧道,前进10格。

       6、开辟的隐藏功能键,轮到用户掷骰子时,用户按下ctrl+Tab组合键,然后再按A键,这是程序会默默等待用户输入合法的数字,若用户输入某个数字后回车,就会提示用户掷出了这个数字,对应的玩家会前进相应的格数;若用户未输入任何数字直接回车,则会按正常掷骰子的方法产生一个随机数。

 

2.10  一方胜利,显示提示信息,游戏结束

       在游戏运行的任何阶段,若某个玩家的坐标 >= 99,则该玩家走到终点,提示该玩家胜利,游戏结束。

 

 

03 代码

 

Program.cs 文件

 

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
 
namespace
{
class  Program
    {
///<summary>
///高昌绪制作2014年6月-----
///2014年11月5日整理 
///</summary>
///<param name="args"></param>
static  voidMain(string[] args)
        {
ClassMethod cm= new ClassMethod();
 
//显示欢迎界面
 
//提示用户A、B输入名字
Console.WriteLine("请输入玩家A的名字:");     
ClassMethod.names[0]= Console.ReadLine();
 
//设置一个while循环,判断用户A输入的玩家名字是否为空,若为空重新输入
while (ClassMethod.names[0]== "")
            {
Console.WriteLine("玩家A的名字不能为空,请重新输入!");
ClassMethod.names[0]= Console.ReadLine();
            }
//提示用户A输入名字
Console.WriteLine("请输入玩家B的名字:");
ClassMethod.names[1]= Console.ReadLine();
//设置while循环,并判断玩家B名字是否为空或是否与玩家A重名,若为空或与A重名则提示重新输入
while (ClassMethod.names[1]== "" ||  ClassMethod.names[1] == ClassMethod.names[0] || ClassMethod.names[1] ==  "")
            {
if (ClassMethod.names[1]== "")
                {
Console.WriteLine("玩家B的名字不能为空,请重新输入!");
                }
else
                {
Console.WriteLine("该名字已被占用,请重新输入!");
                }
ClassMethod.names[1]= Console.ReadLine();
            }
 
//显示给用户刚才输入的名字
Console.WriteLine("玩家A的名字为 {0} ,玩家B的名字为 {1} ,欢迎进入游戏!", ClassMethod.names[0],  ClassMethod.names[1]);  //显示玩家名字
Console.WriteLine("按任意键继续……");
Console.ReadKey();
            
//清屏,重新绘制界面,提示游戏开始
Console.Clear();     //清屏,重新绘制界面
           cm.ShowUI();
Console.WriteLine("{0}用A表示    {1}用B表示   如果A和B在同一位置,用<>表示。", ClassMethod.names[0],  ClassMethod.names[1]);
            
//初始化地图关卡
//绘制地图
Console.WriteLine("按任意键游戏开始...");
Console.ReadLine();
 
 
 
//A和B轮流掷骰子(设置循环)
//当A或B的值>=99时,结束循环。    循环条件:A和B的坐标同时小于99。
while (ClassMethod.playerPos[0]< 99 && ClassMethod.playerPos[1] < 99)
            {
//判断A是否应该掷骰子
if(ClassMethod.isStop[0]== false)
                {
//掷骰子
                }
else
                {
ClassMethod.isStop[0] = false;
                }
if (ClassMethod.playerPos[0]>= 99)
                {
break;
                }
//判断B是否掷骰子
if (ClassMethod.isStop[1]== false)
                {
//掷骰子
                }
else
                {
ClassMethod.isStop[1] = false;
                }
            }
 
 
Console.Clear();
           cm.DrawMap();
if (ClassMethod.playerPos[0] >= 99)
            {
Console.WriteLine("{0}先走到了终点,获得了胜利!", ClassMethod.names[0]);
            }
else  if(ClassMethod.playerPos[1]>= 99)
            {
Console.WriteLine("{0}先走到了终点,获得了胜利!", ClassMethod.names[1]);
            }
 
Console.WriteLine("游戏结束...     --- Tonyc制作 2014.11.05 ---");
Console.WriteLine("按任意键退出...");
            
 
Console.ReadKey();
        }
    }
}

 

 

 

 

 

 

 

ClassMethod.cs 文件

 

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
 
namespace
{
class  ClassMethod
    {
 
//定义int[]Map,存储地图各元素
/*数组的下表为0的元素对应地图上的第1格,下标为1的元素对应第2格……下标为n的元素
          对应第(n+1)格。 */
 
/* 在int[]Map数组中,不同元素的值表示的意义不同,如下:
           元素值为1时,输出幸运轮盘 ★
                    2,地雷 ●
                    3,暂停 △
                    4,时空隧道 卍
                    0,表示普通 □
       */
public  static int[]Map =  new int[100];        //定义int[]Map,存储地图各元素
 
public  static string[]names =  new string[2];     //定义string[],存储玩家A和玩家B的名字
//names[0]存储玩家A的名字,names[1]存储玩家B的名字
 
public  static int[]playerPos = { 0, 0 };    //定义一个数组,存储A和B的坐标(下标),playerPos[0]表示A,playerPos[1]表示B。
// 初始化A和B的下标为0,都在第1格。
//static int[]playerPos = { 1, 5 };   //测试
 
public  static bool[]isStop = {  false, false };//isStop[0]=true表示A上次走到了暂停,isStop[1]=true表示B上次走到了暂停。如果走到了暂停,则设置其值为true。
 
 
 
 
 
 
///<summary>
///显示飞行棋欢迎界面
///</summary>
public  voidShowUI()
        {
Console.WriteLine("************************************************************");
Console.WriteLine("*                                                         *");
Console.WriteLine("*               欢迎来到     骑 士 飞 行 棋               *");
Console.WriteLine("*                                                         *");
Console.WriteLine("************************************************************");
        }
 
 
///<summary>
///初始化地图关卡
///定义几个新数组,其值为Map[i]的下标i,存储地图中的关卡
///</summary>
public  voidInitialMap()
        {
int[]luckTurn = { 6, 23, 40, 55, 69, 83 };//幸运轮盘★ Map[i] = 1
int[]landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };//地雷●  Map[i] = 2
int[]pause = { 9, 27, 60, 93 };//暂停坐标△ Map[i] = 3
int[]timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };//时空隧道卍  Map[i] = 4
 
//设置循环,将各关卡的坐标取出,再赋给Map数组
for (int
            {
int
 //Map[pos]存储地图元素;  这里的pos为其下标   
            }
for (int
            {
               Map[landMine[i]] = 2;
            }
for (int
            {
               Map[pause[i]] = 3;
            }
for (int
            {
               Map[timeTunnel[i]] = 4;
            }
        }
 
 
///<summary>
///绘制地图
///</summary>
///说明:地图为100个元素,100小格。分为3行2列呈S型排列,每行30个元素,每列5个元素。
public  voidDrawMap()
        {
//图例
Console.WriteLine("图例: 幸运轮盘:★   地雷:●   暂停:△   时空隧道:卍   ");
 
//1、绘制第一行(0-29格):①先判断A和B是否在这一格元素上②考虑每一格元素的值
for (int
            {
Console.Write(GetMapString(i));
            }
//第一行绘制完毕
Console.WriteLine();  //换行
 
//2、绘制第一列
for (int
            {
//这里的列地图,要绘制29个双空格(即1个全角空格) + 1个地图小格
//绘制29个双空格
for (int
                {
Console.Write("  ");      //因在行中绘制空格,所以不换行
                }
//第一列绘制完毕
//Console.WriteLine(GetMapString(i));
string
Console.WriteLine(str);
            }
//3、绘制第二行
for (int
            {
Console.Write(GetMapString(i));
            }
Console.WriteLine();    //第二行绘制完毕
//4、绘制第二列
for (int
            {
Console.WriteLine(GetMapString(i));    //第二列绘制完毕
            }
//5、绘制第三行
for (int
            {
Console.Write(GetMapString(i));
            }
Console.WriteLine();                  //第三行绘制完毕
Console.ResetColor();                 //重置前景色,恢复正常
        }
 
 
 
///<summary>
///获得第pos坐标上应该绘制的图案,即判断A、B和关卡是否在当前坐标上
///</summary>
///<param name="pos">要绘制的坐标</param>
///<returns>result</returns>
static  stringGetMapString(int
        {
stringresult =  "";
 
/*①先判断A和B是否在当前要画的第i格上
              ②再判断每一格的值
            */
//要想判断A和B是否在第i格上,首先要知道A和B的位置坐标(下标),所以要定义一个数组存储A和B的下标
//这里不在方法中直接输出,而是通过传参的方式返回要绘制的符号
if(playerPos[0] == pos && playerPos[1] == pos)
            {
//Console.ForegroundColor 属性用来设置前景色
Console.ForegroundColor= ConsoleColor.Red;
"<>";
            }
else  if(playerPos[0] == pos)  //判断A在当前要绘制的格上
            {
Console.ForegroundColor= ConsoleColor.Red;
"A";  //此处用全角符号。
            }
else  if(playerPos[1] == pos)  //判断B在当前要绘制的格上
            {
Console.ForegroundColor= ConsoleColor.Red;
"B";
            }
//②再判断每一格的值
//这里用switch,因为有多个值对应多个元素
else
            {
switch(Map[pos])
                {
case
Console.ForegroundColor = ConsoleColor.White;
 "□";
break;
case
Console.ForegroundColor = ConsoleColor.Yellow;;
 "★";
break;
case
Console.ForegroundColor = ConsoleColor.Blue;
 "●";
break;
case
Console.ForegroundColor = ConsoleColor.DarkCyan;
 "△";
break;
case
Console.ForegroundColor = ConsoleColor.Green;
 "卍";
break;
                }
            }
returnresult;
        }

 

 

 

 

///<summary>
/// A或B掷骰子的方法
///</summary>
///<param name="playerNumber">A掷骰子传过来0,B掷骰子传过来1。</param>
public  voidAction(int
        {
//playerNumber中存的是当前玩家的姓名、坐标、是否暂停 这三个数组的下标(此三个坐标相同)
 
Random r =new Random();    //产生一个Random类型的变量 r, r用于产生随机数
intstep = 0;              //用于存放产生的随机数
string msg=  "";           //用于存储用户踩到某关卡所要输出的话
            
Console.WriteLine();
Console.WriteLine("玩家{0}按任意键开始掷骰子...",names[playerNumber]);
ConsoleKeyInfo rec= Console.ReadKey(true);    //获取用户按下的下一个字符或功能键。 按下的键可以选择显示在控制台窗口中。
//如果为true,则不显示按下的键;否则为 false。 
 //产生一个1—6的随机数 (此数大于等于最小值,小于最大值)
 
 
//此处开辟了一个隐藏功能组合按键
//当用户掷骰子前按下ctrl+Tab组合键,再按A键,之后就可以输入1-100中的数字,就是掷骰子出来的数字。
if(rec.Key==ConsoleKey.Tab&& rec.Modifiers==(ConsoleModifiers
            {
ConsoleKeyInfo cc=Console.ReadKey(true);
if(cc.Key==ConsoleKey.A)
                {
                   step=ReadInput(1,100);
                }
            }
 
/*
            //三键同按代码
            if(rec.Key == ConsoleKey.Tab && rec.Modifiers ==(ConsoleModifiers.Control| ConsoleModifiers.Shift))
            {
               ConsoleKeyInfo cc = Console.ReadKey(true);
                if(cc.Key == ConsoleKey.A)
                {
                   step =ReadInt (1,100);
                }
 
            }
             
            */

 

 

 

Console.WriteLine("{0}掷出了{1}",names[playerNumber], step);
Console.WriteLine("按任意键开始行动...");
Console.ReadKey(true);
//玩家行动之后坐标发生改变
 
//一旦坐标发生改变,就要判断是否越界
//检测坐标是否越界
 
//玩家行动之后,要判断是否踩到对方
if(playerPos[0] == playerPos[1])
            {
//被踩到的一方退回起点
string.Format("{0}踩到了{1},{1}退回到起点!",names[playerNumber], names[1 - playerNumber]);
            }
else
            {
//没踩到对方,则要判断玩家现在的位置是否处于某关卡
switch(Map[playerPos[playerNumber]])
                {
case
//普通,没有效果
"";
break;
case
//走到了幸运轮盘
Console.Clear();
                       DrawMap();
Console.WriteLine("玩家{0}掷出了{1}",names[playerNumber ],step);
Console.WriteLine("{0}走到了幸运轮盘,请选择运气...",names[playerNumber]);
Console.WriteLine("--->1 交换位置     ---> 2 轰炸对方");
int
if
                       {
inttemp = playerPos[0];
                            playerPos[0] =playerPos[1];
                            playerPos[1] =temp;
string.Format("{0}选择了与对方交换位置",names[playerNumber]);
Console.WriteLine(msg);
Console.WriteLine("按任意键确认...");
Console.ReadKey(true);
                       }
else
                       {
//轰炸对方
                            playerPos[1 - playerNumber]-= 6;
                            CheckPos();
string.Format("{0}轰炸了{1},{1}退6格。",names[playerNumber],names[playerNumber]);
Console.WriteLine(msg);
Console.WriteLine("按任意键确认...");
Console.ReadKey(true);
                       }
break;
case
//踩到了地雷
Console.Clear();
                       DrawMap();
                       playerPos[playerNumber] -= 6;
                       CheckPos();
Console.WriteLine("玩家{0}掷出了{1}", names[playerNumber], step);
string.Format("{0}前进{1}踩到了地雷,退了6格!",names[playerNumber],step);
Console.WriteLine(msg);
Console.WriteLine("按任意键确认...");
Console.ReadKey(true);
break;
case
//走到了暂停
 true;
string.Format("{0}走到了暂停,暂停掷骰子一次!",names[playerNumber]);
Console.WriteLine(msg);
Console.WriteLine("按任意键确认...");
Console.ReadKey(true);
break;
case
//走到了时空隧道
                       playerPos[playerNumber] += 10;
                       CheckPos();
Console.Clear();
                       DrawMap();
Console.WriteLine("玩家{0}掷出了{1}", names[playerNumber], step);
string.Format("{0}走到了时空隧道,前进10格!",names[playerNumber]);
Console.WriteLine(msg);
Console.WriteLine("按任意键确认...");
Console.ReadKey(true);
break;
                }
 
            }
 
 
Console.Clear();
           DrawMap();
Console.WriteLine();
Console.WriteLine("{0}掷出了{1},行动完成。",names[playerNumber],step);
Console.WriteLine("****** 玩家 {0 }的位置为{1}   玩家 {2} 的位置为{3} ******",names[0],playerPos[0]+1,names[1],playerPos[1]+1);
        }
 
 
 
///<summary>
///检测输入的数字是否在一定范围内
///</summary>
///<returns></returns>
static  intReadInput()
        {
int i =ReadInput(int.MinValue, int.MaxValue);
return
        }
static  intReadInput(int min,  int
        {
while (true)
            {
try
                {
int number =  Convert.ToInt32(Console.ReadLine());
if
                   {
Console.WriteLine("只能输入{0}-{1}之间的数,请重新输入!",min,max);
continue;
                   }
return
                }
catch(Exception
                {
Console.WriteLine("只能输入数字,请重新输入!"+e.Message);
                }
            }
        }
 
 
 
 
///<summary>
///检测是否越界
///</summary>
static  voidCheckPos()
        {
for (int
            {
if(playerPos[i] > 99)
                {
                   playerPos[i] = 99;
Console.WriteLine("玩家{i}赢得了比赛!");
break;
                }
else  if(playerPos[i]< 0)
                {
                   playerPos[i] = 0;
                }
            }
        }
 
    }
}