刚入坑之C#《方法》解说
说好的用一周时间学方法,我都快耽误成两周了。原因就是跟着传智播客的课程做了个飞行棋项目,想要梳理其中的方法却把自己绕晕了。那接下来我先说一下我学到方法的内容,在最后献上飞行器项目的代码,当然是传智播客老师的成果,我只是代码的搬运工。
一、方法(函数)概念:将一堆代码进行重用的一种机制。调用它需要我们提供数据(参数),执行后它可能会返回执行结果(返回值)。
语法:
[public] static 返回值类型 方法名 ([参数列表])
{
方法体;
}
二、方法的形参和实参:
形参:在定义函数中指定的参数,值类型存储在内存的堆栈中。只有在调用函数的时候,形参才会被分配内存单元。当调用结束时,所占用的内存单元被释放。
实参:有确定值得常量、变量或表达式,值类型存储在内存堆中。调用函数时,将实参的值赋给形参。该数据需要.Net FrameWork 自己的内存清理机制进行回收。
三、方法的调用:类名.方法名();
在同一个类中,调用方法可以省略类名
如果被调用者想要的到调用者的值,可以:1)使用参数;2)使用静态字段模拟全局变量
四、方法参数类型:
1、值参数:是方法默认的参数类型,采用值拷贝的方式,没有修饰符。总的来说,如果你把将一个变量带进方法中修改,方法中该变量的值可以改变,但传递回给变量时,却不会保留更改的值。
例如:
class Program
{
//交换i、j的值
static void Swap(int i, int j)
{
int temp = i;
i = j;
j = temp;
}
static void Main()
{
int i = 1, j = 2;
Swap(i, j);
Console.WriteLine("i = {0}, j = {1}", i, j);
}
}
//输出结果:i=1,j=2 两个值并没有改变
2、输出型参数:用out修饰符声明。帮助在方法中返回多个不同类型的值,要求在方法内部必须为其赋值。
例如:
class Program
{
//将两数值求和
static double Plus(out int i, out double j)
{
i = 1;
j = 2.2;
double sum = i;
sum = i + j;
return sum;
}
static void Main()
{
int i=0 ;
double j=0 ;
double sum =Plus(out i, out j);
Console.WriteLine("sum={0}", sum);
}
}//输出结果:sum=3.2
3、引用型参数:用ref修饰符声明。能够将将一个变量带入一个方法中进行改变,改变完成后再将改变的值带出方法。要求在方法外必须赋值,而方法内可以不赋值
例如:
class Program
{
//将两数值求和
static double Plus(ref int i, ref double j)
{
double sum = i;
sum = i + j;
return sum;
}
static void Main()
{
int i=1 ;
double j= 2.2;
double sum =Plus(ref i, ref j);
Console.WriteLine("sum={0}", sum);
Console.ReadKey();
}
}//输出结果:sum=3.2
4、数组型参数(可变参数):用params修饰符声明,将实参列表中跟可变参数类型一致的元素都当作数组的元素去处理。其要求可变参数必须是参数列表中最后一个参数。
例如:
class Program
{
public static void output(int i, params string[] list)
{
//打印出整数类型i的数值跟字符串数组list的数值
Console.WriteLine("i={0}", i);
for (int j = 0; j < list.Length; j++)
{
Console.WriteLine(list[j]);
}
}
static void Main()
{
int i = 22;
string[] arr = new string[3] { "Jme","zaozao","love"};
output(i,arr);
Console.ReadKey();
}
}//输出结果:换行打印出22、Jme、zaozao和love
五、方法的重载:方法名称相同,但参数不同。重载跟返回值的类型没关系。
参数不同分为:个数不同和类型不同。
例如:
Console.WriteLine(1);//输出数字1
Console.WriteLine('c');//输出字符c
Console.WriteLine("string");//输出字符串string
六、方法的递归:方法自己调用自己。调用了该方法几次,就应该返回该方法几次(类似你穿越几个门到达目的地,就要穿越几个门回到出发地点)。
例如:
//斐波那契数列:第N(N > 2)个数等于第(N - 1)个数和(N - 2)个数的和 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,......
public static int Fibonacci(int n)
{
if (n < 0) return -1;
if (n == 0) return 0;
if (n == 1) return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
最后献上传智播客老师的飞行棋项目代码供大家参考练习,我有做一些注释还有微小的改动,希望不会出现bug。
游戏规则:
如果玩家A踩到了玩家B ,玩家B退6格
踩到了地雷,退6格
踩到了时空隧道,前进10格
踩到了幸运轮盘,可选择:1交换位置;2 轰炸对方 使对方退6格
踩到了暂停,暂停一回合
踩到了方块,安全
1、幸运轮盘,显示组用户就◎
2、地雷,显示给用户就是 ☆
3、暂停,显示给用户就是 ▲
4、时空隧道,显示组用户就 卐
成果图:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Flight_Chess 8 { 9 class Program 10 { 11 //用静态字段来模拟全局变量 12 //存储地图 13 static int[] Maps = new int[100]; 14 //声明一个静态数组来存储玩家A、B的坐标 15 static int[] PlayerPos = new int[2]; 16 //存储两个玩家的姓名 17 static string[] PlayerNames = new string[2]; 18 //两个玩家的标记,都默认为false 19 static bool[] Flags = new bool[2]; //跳到暂停的时候把玩家的标记变成true 20 21 22 static void Main(string[] args) 23 { 24 GameShow();//画出游戏头 25 #region 输入玩家的名字 26 Console.WriteLine("请输入玩家A的姓名:"); 27 PlayerNames[0] = Console.ReadLine(); 28 while (PlayerNames[0] == "") 29 { 30 Console.WriteLine("玩家A的姓名不能为空,请重新输入!"); 31 PlayerNames[0] = Console.ReadLine(); 32 } 33 Console.WriteLine("请输入玩家B的姓名:"); 34 PlayerNames[1] = Console.ReadLine(); 35 while (PlayerNames[1] == "" || PlayerNames[1] == PlayerNames[0]) 36 { 37 if (PlayerNames[1] == "") 38 { 39 Console.WriteLine("玩家B的姓名不能为空,请重新输入!"); 40 PlayerNames[1] = Console.ReadLine(); 41 } 42 else 43 { 44 Console.WriteLine("姓名已存在,请重新输入!"); 45 PlayerNames[1] = Console.ReadLine(); 46 } 47 } 48 #endregion 49 //玩家姓名输入完毕,开始清屏 50 Console.Clear();//清屏,刷新页面 51 GameShow(); 52 Console.WriteLine("{0}的士兵用A表示", PlayerNames[0]); 53 Console.WriteLine("{0}的士兵用B表示", PlayerNames[1]); 54 //初始化地图 55 InitailMap(); 56 DrawMap();//画出地图 57 58 //当玩家A、B没人到达终点时,游戏继续 59 while (PlayerPos[0] < 99 && PlayerPos[1] < 99) 60 { 61 //第一个玩家 62 if (Flags[0] == false) 63 { 64 PlayGame(0); 65 } 66 //跳到暂停时Flags[0]=true,暂停玩一局,然后把true改成false,下一局再开始 67 else 68 { 69 Flags[0] = false; 70 } 71 if (PlayerPos[0] >= 99) 72 { 73 Console.WriteLine("玩家{0}无耻地战胜了玩家{1}", PlayerNames[0], PlayerNames[1]); 74 break; 75 } 76 //第二个玩家 77 if (Flags[1] == false) 78 { 79 PlayGame(1); 80 } 81 else 82 { 83 Flags[1] = false; 84 } 85 if (PlayerPos[1] >= 99) 86 { 87 Console.WriteLine("玩家{0}无耻地战胜了玩家{1}", PlayerNames[1], PlayerNames[0]); 88 break; 89 } 90 } 91 92 93 Win(); 94 Console.ReadKey(); 95 } 96 97 public static void Win() 98 { 99 100 Console.ForegroundColor = ConsoleColor.Red; 101 Console.WriteLine(" ◆ "); 102 Console.WriteLine(" ■ ◆ ■ ■"); 103 Console.WriteLine(" ■■■■ ■ ■ ◆■ ■ ■ ■"); 104 Console.WriteLine(" ■ ■ ■ ■ ◆ ■ ■ ■ ■"); 105 Console.WriteLine(" ■ ■ ■■■■■■ ■■■■■■■ ■ ■ ■"); 106 Console.WriteLine(" ■■■■ ■ ■ ●■● ■ ■ ■"); 107 Console.WriteLine(" ■ ■ ■ ● ■ ● ■ ■ ■"); 108 Console.WriteLine(" ■ ■ ■■■■■■ ● ■ ● ■ ■ ■"); 109 Console.WriteLine(" ■■■■ ■ ● ■ ■ ■ ■ ■"); 110 Console.WriteLine(" ■ ■ ■ ■ ■ ■ ■ ■"); 111 Console.WriteLine(" ■ ■ ■ ■ ■ ■ "); 112 Console.WriteLine(" ■ ■ ■ ■ ● ■ "); 113 Console.WriteLine(" ■ ■■ ■■■■■■ ■ ● ●"); 114 Console.ResetColor(); 115 } 116 /// <summary> 117 /// 画游戏头 118 /// </summary> 119 public static void GameShow() 120 { 121 Console.ForegroundColor = ConsoleColor.Yellow; 122 Console.WriteLine("**************************"); 123 Console.ForegroundColor = ConsoleColor.Red; 124 Console.WriteLine("**************************"); 125 Console.ForegroundColor = ConsoleColor.Green; 126 Console.WriteLine("**************************"); 127 Console.ForegroundColor = ConsoleColor.White; 128 Console.WriteLine("***飞行棋***"); 129 Console.ForegroundColor = ConsoleColor.Cyan; 130 Console.WriteLine("**************************"); 131 Console.ForegroundColor = ConsoleColor.Green; 132 Console.WriteLine("**************************"); 133 } 134 135 /// <summary> 136 /// 初始化地图 137 /// </summary> 138 public static void InitailMap() 139 { 140 int[] luckyturn = { 6, 23, 40, 55, 69, 83 };//幸运转盘◎ 141 for (int i = 0; i < luckyturn.Length; i++) 142 { 143 Maps[luckyturn[i]] = 1; 144 } 145 146 int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };//地雷☆ 147 for (int i = 0; i < landMine.Length; i++) 148 { 149 Maps[landMine[i]] = 2; 150 } 151 152 int[] pause = { 9, 27, 60, 93 };//暂停▲ 153 for (int i = 0; i < pause.Length; i++) 154 { 155 Maps[pause[i]] = 3; 156 } 157 158 int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };//时空隧道卐 159 for (int i = 0; i < timeTunnel.Length; i++) 160 { 161 Maps[timeTunnel[i]] = 4; 162 } 163 } 164 165 166 /// <summary> 167 /// 画地图 168 /// </summary> 169 public static void DrawMap() 170 { 171 Console.WriteLine("图例:幸运转盘:◎ 地雷:☆ 暂停:▲ 时空隧道:卐"); 172 #region 第一横行 173 for (int i = 0; i < 30; i++) 174 { 175 Console.Write(DrawStringMap(i)); 176 } 177 #endregion 178 179 //画完第一行,换行 180 Console.WriteLine(); 181 182 #region 第一竖行 183 for (int i = 30; i < 35; i++) 184 { 185 for (int j = 0; j <= 28; j++) 186 { 187 Console.Write(" "); 188 } 189 Console.Write(DrawStringMap(i)); 190 191 Console.WriteLine(); 192 } 193 #endregion 194 195 #region 第二横行 196 for (int i = 64; i >= 35; i--) 197 { 198 Console.Write(DrawStringMap(i)); 199 } 200 #endregion 201 202 //画完第二横行,换行 203 Console.WriteLine(); 204 205 #region 第二竖行 206 for (int i = 65; i <= 69; i++) 207 { 208 Console.WriteLine(DrawStringMap(i)); 209 } 210 #endregion 211 212 #region //第三横行 213 for (int i = 70; i <= 99; i++) 214 { 215 Console.Write(DrawStringMap(i)); 216 } 217 #endregion 218 219 //画完最后一行,换行 220 Console.WriteLine(); 221 }//DrawMap方法的结尾 222 223 /// <summary> 224 /// 从画地图的方法中抽象出来的一个方法 225 /// </summary> 226 /// <param name="i"></param> 227 /// <returns></returns> 228 229 public static string DrawStringMap(int i) 230 { 231 string str = ""; 232 #region //画图 233 //如果玩家A的坐标跟玩家B的相同,并且在该地图上,画一个尖括号<> 234 if (PlayerPos[0] == PlayerPos[1] && PlayerPos[0] == i) 235 { 236 str = "<>"; 237 } 238 else if (PlayerPos[0] == i) 239 { 240 str = "A";//注意是全角 shift+空格 241 } 242 else if (PlayerPos[1] == i) 243 { 244 str = "B"; 245 } 246 else 247 { 248 switch (Maps[i]) 249 { 250 case 0: 251 Console.ForegroundColor = ConsoleColor.White; 252 str = "□"; 253 break; 254 case 1: 255 Console.ForegroundColor = ConsoleColor.Green; 256 str = "◎"; 257 break; 258 case 2: 259 Console.ForegroundColor = ConsoleColor.Red; 260 str = "☆"; 261 break; 262 case 3: 263 Console.ForegroundColor = ConsoleColor.Blue; 264 str = "▲"; 265 break; 266 case 4: 267 Console.ForegroundColor = ConsoleColor.DarkCyan; 268 str = "卐"; 269 break; 270 } 271 } 272 return str; 273 #endregion 274 } 275 276 /// <summary> 277 /// 玩游戏 278 /// </summary> 279 /// <param name="playerNumber"></param> 280 281 public static void PlayGame(int playerNumber) 282 { 283 Random r = new Random(); 284 int rNumber = r.Next(1, 7); 285 Console.WriteLine("{0}按任意键开始掷骰子", PlayerNames[playerNumber]); 286 Console.ReadKey(true); 287 Console.WriteLine("{0}掷出了{1}", PlayerNames[playerNumber], rNumber); 288 PlayerPos[playerNumber] += rNumber; 289 ChangePos(); 290 Console.ReadKey(true); 291 Console.WriteLine("{0}按任意键开始行动", PlayerNames[playerNumber]); 292 Console.ReadKey(true); 293 //玩家A可能踩到了玩家B、方块、幸运转盘、地雷、暂停、时空隧道 294 if (PlayerPos[playerNumber] == PlayerPos[1 - playerNumber]) 295 { 296 Console.WriteLine("玩家{0}踩到了玩家{1},玩家{2}退6格", PlayerNames[playerNumber], PlayerNames[1 - playerNumber], PlayerNames[1 - playerNumber]); 297 PlayerPos[1 - playerNumber] -= 6; 298 ChangePos(); 299 Console.ReadKey(true); 300 } 301 else//踩到了关卡 302 { 303 //玩家坐标 304 switch (Maps[PlayerPos[playerNumber]])//0 1 2 3 4 305 { 306 case 0: 307 Console.WriteLine("玩家{0}踩到了方块,安全。", PlayerNames[playerNumber]); 308 ChangePos(); 309 Console.ReadKey(true); 310 break; 311 case 1: 312 Console.WriteLine("玩家{0}踩到了幸运转盘,请选择 1-交换位置 2-轰炸对方", PlayerNames[playerNumber]); 313 string input = Console.ReadLine(); 314 while (true) 315 { 316 if (input == "1") 317 { 318 Console.WriteLine("玩家{0}选择跟玩家{1}交换位置", PlayerNames[playerNumber], PlayerNames[1 - playerNumber]); 319 Console.ReadKey(true); 320 int temp = PlayerPos[playerNumber]; 321 PlayerPos[playerNumber] = PlayerPos[1 - playerNumber]; 322 PlayerPos[1 - playerNumber] = temp; 323 Console.WriteLine("交换完成,按任意键继续游戏!"); 324 ChangePos(); 325 Console.ReadKey(true); 326 break; 327 } 328 else if (input == "2") 329 { 330 Console.WriteLine("玩家{0}选择轰炸玩家{1},玩家{2}退6格", PlayerNames[playerNumber], PlayerNames[1 - playerNumber], PlayerNames[1 - playerNumber]); 331 Console.ReadKey(true); 332 PlayerPos[1 - playerNumber] -= 6; 333 Console.WriteLine("玩家{0}退了6格", PlayerNames[1 - playerNumber]); 334 ChangePos(); 335 Console.ReadKey(true); 336 break; 337 } 338 else 339 { 340 Console.WriteLine("只能输入1或者2 1-交换位置 2-轰炸对方"); 341 input = Console.ReadLine(); 342 } 343 } 344 break; 345 case 2: 346 Console.WriteLine("玩家{0}踩到了地雷,退6格", PlayerNames[playerNumber]); 347 348 PlayerPos[playerNumber] -= 6; 349 ChangePos(); 350 Console.ReadKey(true); 351 break; 352 case 3: 353 Console.WriteLine("玩家{0}踩到了暂停,暂停一回合", PlayerNames[playerNumber]); 354 Flags[playerNumber] = true; 355 ChangePos(); 356 Console.ReadKey(true); 357 break; 358 case 4: 359 Console.WriteLine("玩家{0}踩到了时空隧道,前进10格", PlayerNames[playerNumber]); 360 PlayerPos[playerNumber] += 10; 361 ChangePos(); 362 Console.ReadKey(true); 363 break; 364 } 365 } 366 367 //ChangePos(); 368 Console.WriteLine("{0}行动完了", PlayerNames[playerNumber]); 369 Console.ReadKey(true); 370 Console.Clear(); 371 DrawMap(); 372 373 } 374 375 376 /// <summary> 377 /// 当玩家坐标发生改变时调用,限定玩家只能在地图内,不会被轰出地图 378 /// </summary> 379 public static void ChangePos() 380 { 381 if (PlayerPos[0] < 0) 382 { 383 PlayerPos[0] = 0; 384 } 385 if (PlayerPos[0] >= 99) 386 { 387 PlayerPos[0] = 99; 388 } 389 if (PlayerPos[1] < 0) 390 { 391 PlayerPos[1] = 0; 392 } 393 if (PlayerPos[1] >= 99) 394 { 395 PlayerPos[1] = 99; 396 } 397 } 398 } 399 }
最后,谢谢大家的观看!如果我有什么不足请多多指教~