1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace 骑士飞行棋
8 {
9 class Program
10 {
11
12 //在下面的数组存储我们游戏地图各个关卡
13 //数组的小标为0的元素对应地图上的第一格 下标为1的元素对应第二格。。。下标为n的元素对应n+1格
14 //在数组中用 1.表格幸运轮盘◎
15 // 2.地雷☆
16 // 3.暂停▲
17 // 4.时空隧道※
18 // 0.表示普通□
19 static int[] Map = new int[100];//设置地图格数并为每格赋值初始值为0
20 static int[] playerPos = { 0, 0 };//playerPos[0]存玩家A的坐标,playerPos[1]存玩家B的坐标 ps:注意这里等于号后面的是{},并不是[],只表示数组长度为2,分别都为零→ static int[] playerPos = new int[1];
21
22 #region//主程序
23 static void Main(string[] args)
24 {
25 Random r = new Random();//r是产生随机数用的
26 bool[] isStop = { false, false };//isStop[0]表示A是否上一次走到了暂停,isStop[1]表示B上一次是否走到了暂停,如果走到暂停则设置其值为true
27 int step = 0;//用于存放临时产生的随机数
28 string[] names = new string[2]; //names[0]存玩家A的姓名,names[1]存玩家B的姓名
29 string input = "";//存储用户的输入
30 string msg = "";//用于存储用户踩到某关卡,输出的话
31
32 ShowUI();//显示游戏名称
33 Console.WriteLine("请输入玩家A的姓名:");//输出提示
34 names[0] = Console.ReadLine();//把玩家A的姓名赋值给names[0]
35 //判断用户输入的内容是否为空,如果为空,则让用户重新输入
36 while (names[0] == "")//只要用户输入为空则执行下面的循环
37 {
38 Console.WriteLine("姓名不能为空,请重新输入玩家A的姓名:");//提示不能输入空值
39 names[0] = Console.ReadLine();//把玩家A的姓名赋值给names[0]
40
41 }
42 Console.WriteLine("请输入玩家B的姓名:"); //输出提示
43 names[1] = Console.ReadLine();//把玩家B的姓名赋值给names[1]
44 while ((names[1] == "") || (names[0] == names[1]))//只要用户输入空值或者与玩家A的姓名重复则执行下面的循环
45 {
46 if (names[1] == "")//如果玩家B的姓名为空则
47 {
48 Console.WriteLine("姓名不能为空,请重新输入玩家B的姓名:");
49 }
50 else//如果玩家B的姓名与玩家A的姓名重复则
51 {
52 Console.WriteLine("姓名不能重复,请重新输入玩家B的姓名:");
53 }
54 names[1] = Console.ReadLine();//把玩家B的姓名赋值给names[1]
55 }
56 Console.Clear();//清屏
57 ShowUI();//显示游戏名称
58 Console.WriteLine("对战开始......");//输出提示
59 Console.WriteLine("{0}用A来表示", names[0]);//输出玩家A的姓名
60 Console.WriteLine("{0}用B来表示", names[1]);//输出玩家B的姓名
61 Console.WriteLine("如果AB同一位置,用<>来表示");//输出提示
62 InitialMap();//初始化地图
63 DrawMap();//绘制地图
64 Console.WriteLine("开始游戏......");
65
66 //这个循环中让玩家A和玩家B轮流掷骰子 当玩家A或者玩家B的坐标>=99时,则结束循环
67 //那循环条件就是
68 //产生一个m到n之间的随机数
69 //Random r = new Random();
70 //int i = r.Next(m,n+1);
71 while (playerPos[0] < 99 && playerPos[1] < 99)//判断胜利条件,如果没有胜利,程序继续循环运行
72 {
73 if (isStop[0] == false)
74 {
75
76 #region 玩家A掷骰子
77 Console.WriteLine("{0}按任意键开始掷骰子......", names[0]);
78 //Console.ReadKey(true);//不显示输入的按键并等待
79 //step = r.Next(1, 7);//产生一个1-6之间的随机整数(掷骰子结果)
80 //取消上面的正常代码,改作弊代码:
81 ConsoleKeyInfo rec = Console.ReadKey(true);//ConsoleKeyInfo类似于类型(即int,string等等的类型),这里是ReadKey的类型,此行代码意思:把键盘动作赋值给rec
82 step = r.Next(1, 7);//产生一个1-6之间的随机整数(掷骰子结果)
83 if (rec.Key == ConsoleKey.Tab)//如果键盘动作为Tab
84 {
85 ConsoleKeyInfo cc = Console.ReadKey();//ConsoleKeyInfo类似于类型(即int,string等等的类型),这里是ReadKey的类型,此行代码意思:把键盘动作赋值给cc
86 if (cc.Key == ConsoleKey.F1)//如果键盘动作为F1
87 {
88 step = ReadInt(1, 100);//选择1至100间的数为掷骰子结果
89 }
90 }
91 else
92 {
93
94 }
95
96 Console.WriteLine("{0}掷出了:{1}", names[0], step);//输出玩家A(names[0])掷骰子结果(随机数step)
97 Console.WriteLine("按任意键开始行动......");
98 Console.ReadKey(true);//不显示输入的按键并等待
99 playerPos[0] = playerPos[0] + step;//注意,一旦坐标发生改变,就要判断,坐标值是否>99或者<0
100 CheckPos();// 进行玩家A和玩家B坐标越界的判断
101
102 if (playerPos[0] == playerPos[1])//玩家A踩到玩家B
103 {
104 playerPos[1] = 0;//玩家B坐标归零
105 msg = string.Format("{0}踩到了{1},{1}退回原点", names[0], names[1]);//string.Format方法提供了不需即时输出又能实现占位符功能
106 }
107 else
108 {
109 //没踩到,要判断玩家A现在所在的位置是否有其他关卡
110 switch (Map[playerPos[0]])
111 {
112 case 0:
113 //普通,没有效果
114 msg = "";
115 break;
116 case 1:
117 //走到了幸运轮盘关卡
118 Console.Clear();//清屏
119 DrawMap();//绘制地图
120 Console.WriteLine("{0}走到了幸运轮盘,请选择运气?", names[0]);
121 Console.WriteLine("1--交换位置 2--轰炸对方");
122 int userSelect = ReadInt(1, 2);
123 if (userSelect == 1)//选择1,要与对方交换位置
124 {
125 int temp = playerPos[0];
126 playerPos[0] = playerPos[1];
127 playerPos[1] = temp;
128 msg = string.Format("{0}选择了与对方交换位置!", names[0]);//string.Format方法提供了不需即时输出又能实现占位符功能
129 }
130 else//选择2,轰炸对方
131 {
132 playerPos[1] = playerPos[1] - 6;//B坐标退6格
133 CheckPos();//检测退六格后有没有坐标越界,有则纠正
134 msg = string.Format("{0}轰炸了{1},{1}退6格!", names[0], names[1]);//string.Format方法提供了不需即时输出又能实现占位符功能
135 }
136 break;
137 case 2:
138 //踩到了地雷
139 playerPos[0] = playerPos[0] - 6;//退六格
140 CheckPos();//检测退六格后有没有坐标越界,有则纠正
141 msg = string.Format("{0}踩到了地雷,退六格", names[0]);//string.Format方法提供了不需即时输出又能实现占位符功能
142 break;
143 case 3:
144 //暂停一次
145 isStop[0] = true;//赋值给isStop[0]为true,让下回合暂停
146 msg = string.Format("{0}走到红灯,下次暂停一次!",names[0]);//string.Format方法提供了不需即时输出又能实现占位符功能
147 break;
148 case 4:
149 //时空隧道
150 playerPos[0] = playerPos[0] + 10;//前进10格
151 CheckPos();//检测前进10格后有没有坐标越界,有则纠正
152 msg = string.Format("{0}进入时空隧道,爽死了,进10步!", names[0]);//string.Format方法提供了不需即时输出又能实现占位符功能
153 break;
154 }
155 }
156
157 Console.Clear();//清屏
158 DrawMap();//绘制地图
159 if (msg != "")//如果msg不为空,则输出msg
160 {
161 Console.WriteLine(msg);
162 }
163 Console.WriteLine("{0}掷出了{1},行动完成!", names[0], step);//step掷骰子结果
164 Console.WriteLine("****************玩家A和玩家B的位置如下****************");
165 Console.WriteLine("{0}的位置为:{1}", names[0], playerPos[0] + 1);
166 Console.WriteLine("{0}的位置为:{1}", names[1], playerPos[1] + 1);
167 Console.ReadKey();
168 #endregion
169 }
170 else
171 {
172 //说明 isStop == true
173 isStop[0] = false;
174 }
175
176 if (playerPos[0] >= 99)//如果玩家A坐标为最后一格,则退出循环,胜利
177 {
178 break; //退出循环
179 }
180
181 if (isStop[1] == false)
182 {
183 #region 玩家B掷骰子
184 Console.WriteLine("{0}按任意键开始掷骰子......", names[1]);
185 Console.ReadKey(true);//不显示输入的按键并等待
186 step = r.Next(1, 7);//产生一个1-6之间的随机整数(掷骰子结果)
187 Console.WriteLine("{0}掷出了:{1}", names[1], step);//输出玩家B(names[1])掷骰子结果(随机数step)
188 Console.WriteLine("按任意键开始行动......");
189 Console.ReadKey(true);//不显示输入的按键并等待
190 playerPos[1] = playerPos[1] + step;//注意,一旦坐标发生改变,就要判断,坐标值是否>99或者<0
191 CheckPos();// 进行玩家A和玩家B坐标越界的判断
192
193 if (playerPos[0] == playerPos[1])//玩家B踩到玩家A
194 {
195 playerPos[0] = 0;
196 msg = string.Format("{0}踩到了{1},{1}退回原点", names[1], names[0]);//string.Format方法提供了不需即时输出又能实现占位符功能
197 }
198 else
199 {
200 //没踩到,要判断玩家B现在所在的位置是否有其他关卡
201 switch (Map[playerPos[1]])
202 {
203 case 0:
204 //普通,没有效果
205 msg = "";
206 break;
207 case 1:
208 //走到了幸运轮盘关卡
209 Console.Clear();//清屏
210 DrawMap();//绘制地图
211 Console.WriteLine("{0}走到了幸运轮盘,请选择运气?", names[1]);
212 Console.WriteLine("1--交换位置 2--轰炸对方");
213 int userSelect = ReadInt(1, 2);
214 if (userSelect == 1)//选择1,要与对方交换位置
215 {
216 int temp = playerPos[0];
217 playerPos[0] = playerPos[1];
218 playerPos[1] = temp;
219 msg = string.Format("{0}选择了与对方交换位置!", names[1]);//string.Format方法提供了不需即时输出又能实现占位符功能
220 }
221 else//选择2,轰炸对方
222 {
223 playerPos[0] = playerPos[0] - 6;//A坐标退6格
224 CheckPos();//检测退六格后有没有坐标越界,有则纠正
225 msg = string.Format("{0}轰炸了{1},{1}退6格!", names[1], names[0]);//string.Format方法提供了不需即时输出又能实现占位符功能
226 }
227 break;
228 case 2:
229 //踩到了地雷
230 playerPos[1] = playerPos[1] - 6;//退六格
231 CheckPos();//检测退六格后有没有坐标越界,有则纠正
232 msg = string.Format("{0}踩到了地雷,退六格", names[1]);//string.Format方法提供了不需即时输出又能实现占位符功能
233 break;
234 case 3:
235 //暂停一次
236 isStop[1] = true;//赋值给isStop[1]为true,让下回合暂停
237 msg = string.Format("{0}走到红灯,下次暂停一次!",names[1]);//string.Format方法提供了不需即时输出又能实现占位符功能
238 break;
239 case 4:
240 //时空隧道
241 playerPos[1] = playerPos[1] + 10;//前进10格
242 CheckPos();//检测前进10格后有没有坐标越界,有则纠正
243 msg = string.Format("{0}进入时空隧道,爽死了,进10步!", names[1]);//string.Format方法提供了不需即时输出又能实现占位符功能
244 break;
245 }
246 }
247
248 Console.Clear();//清屏
249 DrawMap();//绘制地图
250 if (msg != "")//如果msg不为空,则输出msg
251 {
252 Console.WriteLine(msg);
253 }
254 Console.WriteLine("{0}掷出了{1},行动完成!", names[1], step);//step掷骰子结果
255 Console.WriteLine("****************玩家A和玩家B的位置如下****************");
256 Console.WriteLine("{0}的位置为:{1}", names[0], playerPos[0] + 1);
257 Console.WriteLine("{0}的位置为:{1}", names[1], playerPos[1] + 1);
258 Console.ReadKey();
259 #endregion
260 }
261 else
262 {
263 //说明 isStop == true
264 isStop[1] = false;
265 }
266
267 }
268
269 //判断谁胜利,谁失败
270 Console.Clear();//清屏
271 ShowUI();//绘制游戏开头画面
272 if (playerPos[0] >= 99)
273 {
274 Console.WriteLine("{0}胜利了!!!!!", names[0]);//提示玩家A胜利
275 }
276 else
277 {
278 Console.WriteLine("{0}胜利了!!!!!", names[1]);//提示玩家B胜利
279 }
280
281 Console.ReadKey();//等待
282 }
283 #endregion
284 #region//绘制飞行棋的开头画面
285 /// <summary>
286 /// 用于绘制飞行棋的名称
287 /// </summary>
288 static void ShowUI()//显示游戏名称的方法
289 {
290 Console.WriteLine();
291 Console.WriteLine("******************************************");
292 Console.WriteLine("* *");
293 Console.WriteLine("* 骑 士 飞 行 棋 *");
294 Console.WriteLine("* *");
295 Console.WriteLine("******************************************");
296 }
297 #endregion
298
299 /// <summary>
300 /// 进行玩家A和玩家B坐标越界的判断
301 /// </summary>
302 static void CheckPos()//进行玩家A和玩家B坐标越界的判断
303 {
304 for (int i = 0; i <= 1; i++)
305 {
306 if (playerPos[i] > 99)
307 {
308 playerPos[i] = 99;
309 }
310 if (playerPos[i] < 0)
311 {
312 playerPos[i] = 0;
313 }
314 }
315 }
316
317 #region//对地图中的关卡进行初始化
318 /// <summary>
319 /// 对地图中的关卡进行初始化
320 /// </summary>
321 static void InitialMap()
322 {
323 //用于存储在地图中为地雷的下标
324 int[] luckyTurn = { 6, 23, 40, 55, 69, 83, 98 };//幸运轮盘1
325 int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };//地雷2
326 int[] pause = { 9, 27, 60, 93 };//暂停的坐标3
327 int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };//时空隧道※4
328
329 for (int i = 0; i < luckyTurn.Length; i++)//循环,从零开始/到luckyTurn的数组长度结束/每循环运行一次i增加1
330 {
331 int pos = luckyTurn[i];//赋值给pos
332 Map[pos] = 1;// 地图数组[下标]=1,把地雷的下标赋值给地图
333 }
334 for (int i = 0; i < landMine.Length; i++)//循环,从零开始/到landMine的数组长度结束/每循环运行一次i增加1
335 {
336 Map[landMine[i]] = 2;//把地雷的下标赋值给地图
337 }
338 for (int i = 0; i < pause.Length; i++)//循环,从零开始/到pause的数组长度结束/每循环运行一次i增加1
339 {
340 Map[pause[i]] = 3;//把暂停的下标赋值给地图
341 }
342 for (int i = 0; i < timeTunnel.Length; i++)//循环,从零开始/到timeTunnel的数组长度结束/每循环运行一次i增加1
343 {
344 Map[timeTunnel[i]] = 4;//把时空隧道的下标赋值给地图
345 }
346 }
347 #endregion
348
349 /// <summary>
350 /// 获得第pos坐标上应该绘制的图案
351 /// </summary>
352 /// <param name="pos">要绘制的坐标</param>
353 /// <returns></returns>
354 static string GetMapString(int pos)//获得第pos坐标上应该绘制的图案 ps:DrawMap()方法需要用到该方法来判断并输出图案
355 {
356 string result = "";
357 //判断A和B是否在当前要画的第i格上,是则先绘制A和B的位置
358 if (playerPos[0] == pos && playerPos[1] == pos)
359 {
360 Console.ForegroundColor = ConsoleColor.Yellow;//更改输出的字符颜色为黄色
361 result = "<>";
362 }
363 else if (playerPos[0] == pos)//判断A在当前画的格上
364 {
365 Console.ForegroundColor = ConsoleColor.Yellow;//更改输出的字符颜色为黄色
366 result = "A";
367 }
368 else if (playerPos[1] == pos)//判断B在当前画的格上
369 {
370 Console.ForegroundColor = ConsoleColor.Yellow;//更改输出的字符颜色为黄色
371 result = "B";
372 }
373 else
374 {
375 //绘制除开A和B位置的地图
376 switch (Map[pos])//以外层循环到的地图格数为判定
377 {
378 case 0:
379 Console.ForegroundColor = ConsoleColor.White;
380 result = "□";//如果为0则绘制□,正常地图格
381 break;//退出循环
382 case 1:
383 Console.ForegroundColor = ConsoleColor.Red;
384 result = "◎";//如果为1则绘制◎,幸运轮盘
385 break;//退出循环
386 case 2:
387 Console.ForegroundColor = ConsoleColor.Green;
388 result = "☆";//如果为2则绘制☆,地雷
389 break;//退出循环
390 case 3:
391 Console.ForegroundColor = ConsoleColor.Blue;
392 result = "▲";//如果为3则绘制▲,暂停
393 break;//退出循环
394 case 4:
395 Console.ForegroundColor = ConsoleColor.Magenta;
396 result = "※";//如果为4则绘制※,时空隧道
397 break;//退出循环
398 }
399 }
400 return result;
401 }
402
403 static void DrawMap()
404 {
405 Console.WriteLine("图例: 幸运轮盘:◎ 地雷:☆ 暂停:▲ 时空隧道:※");
406 //画第一行 绘制下标从0-29格的地图
407 for (int i = 0; i <= 29; i++)
408 {
409 //判断A和B是否在当前要画的第i格上,是则先绘制A和B的位置
410 Console.Write(GetMapString(i));
411 }
412 //绘制第一行完毕
413 Console.Write("\n");//换行
414 //绘制第一列
415 for (int i = 30; i <= 34; i++)
416 {
417 //绘制29个双空格
418 for (int j = 0; j < 29; j++)
419 {
420 Console.Write(" ");
421 }
422 Console.WriteLine(GetMapString(i));
423 }
424 //绘制第二行
425 for (int i = 64; i >= 35; i--)
426 {
427 Console.Write(GetMapString(i));
428 }
429 Console.Write("\n");//换行
430 //绘制第二列
431 for (int i = 65; i <= 69; i++)
432 {
433 Console.WriteLine(GetMapString(i));
434 }
435 //绘制第三行
436 for (int i = 70; i <= 99; i++)
437 {
438 Console.Write(GetMapString(i));
439 }
440 Console.WriteLine();
441 Console.ResetColor();
442 }
443
444 #region//产生随机数方法???判断是否为一或者二的整数
445 static int ReadInt()//产生一个整数
446 {
447 int i = ReadInt(int.MaxValue, int.MinValue);
448 return i;
449 }
450
451 static int ReadInt(int min, int max)//产生min--max 之间的数
452 {
453 while (true)
454 {
455 try
456 {
457 int number = Convert.ToInt32(Console.ReadLine());
458 if (number < min || number > max)
459 {
460 Console.WriteLine("只能输入{0}--{1}之间的数字,请重新输入", min, max);
461 continue;//跳出本次循环,继续下次循环
462 }
463 return number;//退出循环,并返回number值
464 }
465 catch
466 {
467 Console.WriteLine("只能输入数字,请重新输入!");
468 }
469 }
470 }
471 #endregion
472
473 }
474 }