1. .net/dotnet:一般指.Net Framework框架。一种平台,一种技术。
2. c#(sharp):一种编程语言,可以开发基于.net平台的应用
1. 桌面应用程序 Winform(.net开发的桌面应用程序叫Winform应用程序)
2. Internet应用程序 ASP.NET
3. (.net开发的internet应用程序叫ASP.NET应用程序)
4. 手机开发 wp8
5. (.net可以做手机开发,Wp8,目前在中国刚刚起步,也许 这是一个机会)
6. Wp8已经来袭,要善于抓住机会,敢于尝试.----掌握分寸
7. Unity3D游戏开发或者虚拟现实(大家的机遇)
以.cs结尾的文件 我们称之为"类"文件
引用命名空间:
A--ProjectA---顾客类
B--ProjectB---顾客类
C--ProjectC---需要用到A和B的两个顾客类 顾客
注意:一个项目里只能有1个main函数,在哪个类里都行。
解决方案:一个公司
项目:一个部门
类:员工
.sln:解决方案文件,这个文件中包含着当前这个解决方案的一些信息,我们可以双击打开。
.csproj:项目文件,里面包含着当前这个项目的信息,不允许双击打开
Console.WriteLine("要输出到控制台的文本");
Console.ReadKey();表示暂停这个程序,等待用户按下任意键继续,并且用户按下的任意键将显示到控制台中。
Ctrl+K+D:快速对齐代码
Ctrl+Z:撤销
Ctrl+S:保存(一定要经常保存!)
Ctrl+J:快速弹出智能提示
Shift+End 、Shift+Home
Ctrl+K+C:注释所选代码
Ctrl+K+U:取消对所选代码的注释
F1:转到帮助文档
折叠冗余代码:#Region 和#EndRegion
1)、单行注释 //
2)、多行注释 /*要注释的内容*/
3)、文档注释 ///
用来存储数据
1、杨浩然 1个人 开一个单人间 208
2、杨浩然 和一个女同事 一个双人间 104
3、杨浩然 和一个男同事 开了两个单人间 309 308
当开房的人员跟数量还有性别不同的时候,我们在旅馆开的房间是不一样的。
我们在计算机中存储数据的大小、类型不同的时候,我们在计算机中开的房间类型也是不一样的。
50 int
int number;//表示在内存中开辟了一个整数类型的房间,并且我们取名为number
number=50;//表示将50这个整数放到number中
3.14
double d;
d=3.14;
变量类型 变量名;//声明了一个变量
变量名=值;//给这个变量赋值
=号在这行代码中表示赋值的意思,表示把等号右边的值,赋值给等号左边的变量。
一种更为简单的方法:
变量类型 变量名=值;
90.54
double d=90.54;
int:表示整数类型,只能存放整数。
double:表示小数类型,既能存储整数也能存储小数
string:能够存储多个文本,可以为空
char:字符类型,能够存储单一的字符,要求 最多最少只能存储1个字符,不能为空
decimal:金钱类型,精度要高于double类型 。
变量的使用过程:必须要先声明在赋值最后使用
*注意*:**变量不允许重复的声明或者定义**。但是可以被重复的赋值。
1 必须以“字母”_或@符号开头.--不要以数字开头
2 后面可以跟任意“字母”、数字、下划线.
注意:
1)你起的变量名不要与c#系统中的关键字重复.
2)在c#中,大小写是敏感的.
3)同一个变量名不允许重复定义(先这么认为,不严谨)
4)、变量名唯一能够出现的特殊字符只有下划线
**要遵守的两个命名规范:**
Camel:骆驼命名规范,要求变量名中首单词的首字母要小写,其余每个单词的首字母都要大写,多用于给变量去命名。
nameJapanStar highSchoolStudent
Pascal:要求变量名中每个单词的首字母都要大写,多用于给类或者方法命名
JapanHotStar
=:表示把等号右边的值赋值给等号左边的变量。
int number=10;
由等号连接的表达式我们称之为赋值表达式,每个表达式,我们都认为可以求解出一个定值,
那么,对于赋值表达式而言,等号左边变量的值就是整个赋值表达式的值。
如果+号两边有一边是字符串的话,那么此时这个+号就起到连接的作用。
如果+号两边都是数字,而不是字符串,那么此时加号就起到相加的作用。
挖个坑,再填个坑。
占位符需要我们注意的地方:
1)、占位符从{0}开始
2)、你挖了几个坑,就填几个坑,如果你多填了,没有效果,但是如果你少填了,程序抛异常
3)、占位符最终按照填坑的顺序输出
10、我们在向控制台输出的内容的时候,不管你输入的内容是什么类型,当打印到控制台的时候,都是字符串类型。
不管我们在控制台输入的内容是什么类型,当我们接受的时候,都必须要按照字符串类型去处理。
转义符值得就是 一个'\'加上一个特殊的字符,组成了一个具有特殊意义的字符。
\+":表示一个英文半角的双引号。\表示转义,而不表示字符。
\r\n:表示换行,操作系统支持
\n:表示换行,操作系统不支持
\b:表示一个退格键,\b放到字符串的两边没有效果
\t:表示一个tab键
\\:表示一个\
12、@符号的用法
1)、取消\在字符串中的转移作用,使其单纯的表示为一个\
2)、让代码按照你编译的原格式输出
+
-
*
/
%
//自动类型转换或者隐式类型转换
//1)、类型必须相兼容 (int和double)
//2)、必须是小的类型转大的类型
//int n=10;
//double d = n;
```
//强制类型转换 结果:丢失精度
//303.6===》303 double---->int
int result = (int)303.6;
Console.WriteLine(result);
Console.ReadKey();
```
在使用的时候需要注意:
如果要发生类型转换的两个变量的类型不兼容,那么这个时候使用Convert类型转换。
前提:面儿上一定要过的去。
如果转换成功,就成功了,如果失败,则抛异常。
++;分为前++和后++,不管是前++还是后++,最终的结果都是这个变量的值自身加1.
区别:如果在一个表达式中遇到了++运算符,
如果是前++,则首先这个变量的值自身加一,然后拿着这个加一后的值去参与运算。
如果是后++,则首先拿原值参与运算,运算完成后,自身再加一。
**谁在前先用谁**
+=
-=
*=
/=
%=
>
<
>=
<=
==
!=
关系运算符用来描述两个事物之间的关系。
由关系运算符连接的表达式我们称之为关系表达式。
关系表达式的结果是bool类型。
bool类型只有两个值,true false
&& shift+7
||
!
逻辑与的优先级要高于逻辑或,也就是说,在一个逻辑表达式中,如果既有逻辑与运算符,也有逻辑或运算符,
先算逻辑与运算符。
顺序结构:从上到下,代码一行一行的执行,不会发生跳跃。
分支结构:if结构 if-else结构
选择结构:if else-if switch-case
循环结构:while do-while for foreach
语法:
if(关系表达式或者bool类型的值或者逻辑表达式)
{
代码;
}
执行过程:
程序执行到if处,首先判断if后面所带的条件的值,如果为true,那么。进入if所带的大括号,执行其中的代码。
如果为false,则跳过if所带的大括号,继续向下执行。
执行特点:先判断,再执行,有可能一行代码都不执行。
语法:
if(关系表达式或者bool类型的值或者逻辑表达式)
{
代码;
}
else
{
}
执行构成:程序首先判断if所带的小括号中的条件是否成立,如果成立,则执行if所带的大括号中的代码,
执行完成后,跳出if-else结构。
如果条件不成立,则跳过if所带的大括号,去执行else所带的大括号中的代码。
特点:先判断,再执行,最少都要执行一个语句块中的代码
注意:else永远都跟离它最近的那个if配对
作用:用来做多条件的区间判断
语法:
if(条件1)
{
代码;
}
else if(条件2)
{
代码;
}
else if(条件3)
{
代码;
}
else
{
}
执行过程:程序运行到if处,首先判断第一个if所带的小括号中的条件是否成立,如果成立,也就是返回一个true,
则执行当前if所带的大括号中的代码,执行完成后,退出if else-if结构。
如果第一个if所带的条件不成立,则继续向下进行判断,如果在判断的过程中,某一个if所带的条件成立了,
则执行该if所带的代码,执行完成后,跳出if else-if结构。
如果每一个if所带的条件都不成立,则看该结构中有没有else,如果有else,则执行else中的代码
,如果没有else,则该if else-if结构什么都不做。
try
{
可能会出现异常的代码;
范德萨范德萨范德萨范德萨
fdsfdsf
fdsfdsfds
fdsfds
}
catch
{
出现异常后要执行的代码;
}
执行过程:当try中的代码出现异常的时候,出现异常的这行代码后面的代码不会被执行。
而是直接跳到catch中执行catch的代码。
使用规律:哪行代码有可能出现异常,就踹他一脚。
能够访问到这个变量的范围。
变量的作用域一般从声明他的那个大括号开始到这个大括号所对应的结束的大括号。
作用:用来做多条件的定值判断
语法:
switch(要判断的变量或者表达式)
{
case 值1:要执行的代码;
break;
case 值2:要执行的代码;
break;
case 值3:要执行的代码;
break;
........
default:要执行的代码;
break;
}
执行过程:程序运行到switch处,首先计算switch后面所带的小括号中的变量或者表达式的值,拿着计算出来的
这个结果跟每个case的值进行匹配,一旦匹配成功,则执行该case所带的代码块,
如果跟每个casa所带的值都不匹配,则看当前switch-csae结构中是否有default,如果有default,
则执行default所带的代码块,否则的话,什么都不做。
break:跳出switch-case结构。
while do-while for foreach
语法:
while(循环条件)
{
循环体;
}
执行过程:
循环条件:当满足这个条件的时候,才进行循环。循环条件一般可以为bool类型的值或者关系表达式或者逻辑表达式。
程序运行到while处,首先判断while所带的循环条件是否成立,如果成立,也就是为true,则执行大括号中的循环体,
当循环体执行完成一遍后,继续回到循环条件进行判断,如果成立,则执行,如果不成立,则跳出while循环。
每个循环都有那么一行代码,能够改变循环条件,使之终有一天不再成立,如果程序中没有那么一行代码能够改变循环条件,
那么我称之为这种循环叫做死循环。
while(true)
{
}
注意:在写while循环的时候,一定要分析出循环体和循环条件。
特点:先判断,再执行,有可能一次都不执行。
break:
1)、跳出switch-case语句。
2)、跳出循环
break单独放到循环中没意义,一般跟if配合着使用,表示当满足某个条件的时候,跳出循环。
do
{
循环体;
}while(循环条件);
执行过程:首先执行do中的循环体,执行完成后,去判断循环条件是否成立,如果成立,
则继续回到do中执行循环体,如果不成立,则跳出do-while循环。
特点:先执行,再判断,最少执行一遍循环体。
F11 单步调试 逐语句调试
F10 逐过程
断点调试
for(表达式1;表达式2;表达式3)
{
循环体;
}
表达式1:一般为声明一个循环变量,用来记录循环的次数
表达式2:一般为循环条件
表达式3:一般为能够改变循环条件的代码
执行过程:在第一次循环的时候,首先执行表达式1,再执行表达式2,然后跳过表达式3.直接执行循环体,
执行完循环体之后,执行表达式3,执行表达式2,循环体,表达式3,表达式2,循环体。。。。。
知道表达式2不成立之后,跳出for循环。
break只能够跳出当前循环,而不能跳出所有循环。
尝试着将一个字符串转换成int类型,如果转换成功的话,返回一个true,并且将转换成功后的值
赋值给一个int类型的参数,如果转换失败的话,返回一个false,并且给这个int类型的参数赋值为0
在循环中,如果遇到break,则跳出当前循环。
如果遇到continue,则立即停止本次循环,回到循环条件进行判断,如果循环条件成立,则继续执行循环。
如果不成立,则跳出循环。
单独把continue放到循环中没有意义,一般也跟着if语句配合着使用。
表达式1?表达式2:表达式3;
表达式1一般为一个关系表达式,如果关系表达式1的结果为true,那么表达式2的值就是整个三元表达式的值,
否则,表达式3就是整个三元表达式的值。
要求:表达式2和表达式3的结果类型必须一致,并且也要和整个三元表达式的结果类型一致。
语法:
const 常量类型 常量名称=值;
语法:
[public] enum 枚举名
{
值1,
值2,
值3,
…
}
public:访问修饰符。访问的权限,公开的,公共的,谁都能访问。
enum:表示声明枚举的关键字
枚举名:必须要Pascal命名规范。每个单词的首字母都要大写。
枚举类型和int类型互相兼容,所以两种类型可以通过强制类型转换的语法互相转换。
枚举类型的值默认是从0开始的。
不管是将字符串类型的数字转换成枚举类型还是将int类型转换成枚举类型,结果都不会抛异常。
但是,如果要转换的字符串,在枚举中,并没有所对应的值,这个时候会抛异常。
语法:
[public] struct 结构名
{
结构成员;
}
字段跟变量有一个本质的区别:字段可以存储多个值,而变量只能存储一个值。
数组类型[] 数组名=new 数组类型[数组长度];
注意:数组的长度一旦声明了,就不能再被改变了。
int[] nums={9,8,7,6,5,4,3,2,1,0}; 0,1,2,3,4,5,6,7,8,9
第一趟比较:8 7 6 5 4 3 2 1 0 9 交换了9次 i=0 j=nums.Length-1-0;
第二趟比较:7 6 5 4 3 2 1 0 8 9 交换了9次 比较了 但是没交换 i=1 j=8 j=nums.Length-1-1;
第三趟比较:6 5 4 3 2 1 0 7 8 9 交换了7次 i=2 j=7 j=nums.Length-1-2
第四趟比较:5 4 3 2 1 0 6 7 8 9 交换了6次 i=3 j=6
第五趟比较:4 3 2 1 0 5 6 7 8 9 交换了5次 i=4 j=5
第六趟比较:3 2 1 0 4 5 6 7 8 9 交换了4次
第七趟比较:2 1 0 3 4 5 6 7 8 9 交换了3次
第八趟比较:1 0 2 3 4 5 6 7 8 9 交换了2次
第九趟比较:0 1 2 3 4 5 6 7 8 9 交换了1次
```csharp
for(int i=0;inums[j+1])
{
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
}
}
语法:
[public] static 返回值类型 方法名([参数列表])
{
方法体;
}
public:访问修饰符,公开的,公共的
static:表示静态
返回值类型:如果没有返回值,写void
方法名:Pascal,要求每个单词的首字母都要大写。
参数列表:完成这个方法,所必须要提供给这个方法的条件。哪怕方法中不需要参数,小括号也不能省略。
参数:
返回值:
方法的调用:
类名.方法名([参数列表]);
1)、在方法中返回要返回的值
2)、立即结束当前方法
我们在Main()函数中调用Test()函数,
我们管Main()函数叫做调用者,管Test()函数叫做调用者,管Test被调用者。
如果被调用者想要得到调用者中的值:
1、传递参数
2、声明一个静态的字段,当做"全局变量"使用。
如果调用者想要得到被调用者中的值:
1、写返回值。
形参:形式上的参数,也会在内存中开辟空间。
实参:调用函数的时候传入的参数。
问题:形参和实参的名字必须一样么?
1、方法的功能一定要单一。
2、在方法中尽量的避免出现提示用户输入之类的代码。
可以帮助我们在一个方法中返回多个值,不限类型。
使用out参数的时候要求,out参数必须在方法内为其赋值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _14out参数练习
{
class Program
{
static void Main(string[] args)
{
//使用out参数返回一个数组的最大值、最小值、总和、平均值
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int max;
int min;
int sum;
int avg;
GetMaxMinSumAvg(nums, out max, out min, out sum, out avg);
Console.WriteLine(max);
Console.WriteLine(min);
Console.WriteLine(sum);
Console.WriteLine(avg);
Console.ReadKey();
}
public static void GetMaxMinSumAvg(int[] nums, out int max, out int min, out int sum, out int avg)
{
max = nums[0];
min = nums[0];
sum = 0;
for (int i =0; i < nums.Length; i++)
{
if (nums[i] > max)
{
max = nums[i];
}
if (nums[i] < min)
{
min = nums[i];
}
sum += nums[i];
}
avg = sum / nums.Length;
}
}
}
ref参数侧重于将一个变量以参数的形式带到一个方法中进行改变,
改变完成后,再将改变后的值带出来。
在使用ref参数的时候需要注意:ref参数在方法外必须为其赋值。
out 和 ref 的区别:
首先,俩者都是按地址传递的,使用后都将改变原来参数的数值。
其次,ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次。这个就是俩个的区别,或者说就像有的网友说的 —— ref是有进有出,out是只出不进。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _02ref参数练习
{
class Program
{
static void Main(string[] args)
{
//交换两个int类型的变量
int n1 = 10;
int n2 = 20;
//int temp = n1;
//n1 = n2;
//n2 = temp;
//n1 = n1 - n2;
//n2 = n1 + n2;
//n1 = n2 - n1;
//Console.WriteLine(n1);
//Console.WriteLine(n2);
// Change(out n1, out n2);
Change(ref n1, ref n2);
Console.WriteLine(n1);
Console.WriteLine(n2);
Console.ReadKey();
}
public static void Change(ref int n1, ref int n2)
{
int temp = n1;
n1 = n2;
n2 = temp;
}
}
}
方法的重载指的是方法的名称相同,但是参数不同。
参数不同:
1)、如果参数的个数相同,那么参数的类型就不能相同。
2)、如果参数的类型相同,那么参数的个数就不能相同。
方法的重载跟返回值没有关系。
1、作用:可以让代码重复的使用
2、参数:完成这个方法所必须要的条件
3、返回值:完成方法后,方法返回的结果
4、out参数:可以让方法返回多个值
5、ref参数:侧重于将一个变量带到方法中进行改变,改变完成后,再将改变后的值带出去。
6、params可变参数:将实参列表中跟可变参数数组类型一样的参数当做是可变参数数组中的元素。
可变参数必须形参列表中的最后一个元素
7、方法的重载:
方法的名称相同,但是参数不同。跟返回值没关系。
参数不同:
1)、如果参数的个数相同,那么参数的类型就不能相同。
2)、如果参数的类型相同,那么参数的个数就不能相同。
8、方法的递归:自己在方法中调用自己。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 飞行棋游戏
{
class Program
{
public static int[] Maps = new int[100];//存储地图的数组
public static int[] PlayerPos = new int[2];//PlayerPos[0]A的坐标 玩家坐标
public static string[] PlayerName = new string[2];//存储玩家姓名
public static bool[] Flags = new bool[2];
static void Main(string[] args)
{
GameHead();
#region 输入玩家姓名
Console.WriteLine("请输入玩家A的姓名");
PlayerName[0] = Console.ReadLine();
while (PlayerName[0] == "")
{
Console.WriteLine("玩家A的姓名不能为空,请重新输入");
PlayerName[0] = Console.ReadLine();
}
Console.WriteLine("请输入玩家B的姓名");
PlayerName[1] = Console.ReadLine();
while (PlayerName[1] == "" || PlayerName[1] == PlayerName[0])
{
if (PlayerName[1] == "")
{
Console.WriteLine("玩家B的姓名不能为空,请重新输入");
PlayerName[1] = Console.ReadLine();
}
else
{
Console.WriteLine("玩家B的姓名不能跟玩家A的姓名相同,请重新输入");
PlayerName[1] = Console.ReadLine();
}
}
#endregion
Console.Clear();//清屏
//清屏完成后,再讲游戏头画一遍
GameHead();
Console.WriteLine("{0}的士兵用A表示",PlayerName[0]);
Console.WriteLine("{0}的士兵用B表示",PlayerName[1]);
InitialMap();
DrawMap();
while (PlayerPos[0] < 99 && PlayerPos[1] < 99)
{
if (Flags[0] == false)
{
PlayGame(0);//A 第一次玩的时候踩到了暂停
}
else
{
Flags[0] = false;
}
if (PlayerPos[0] >= 99)
{
Console.WriteLine("玩家{0}无耻的赢了玩家{1}",PlayerName[0],PlayerName[1]);
break;
}
if (Flags[1] == false)
{
PlayGame(1);
}
else
{
Flags[1] = false;
}
if (PlayerPos[1] >= 99)
{
Console.WriteLine("玩家{0}无耻的赢了玩家{1}", PlayerName[1], PlayerName[0]);
break;
}
}//while
Win();
Console.ReadKey();
}
///
/// 画游戏头
///
public static void GameHead()
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("******************************");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("******************************");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("******************************");
Console.WriteLine("***0326版骑士飞行棋游戏--v1.0*");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("******************************");
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine("******************************");
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("******************************");
}
///
/// 初始化地图
///
public static void InitialMap()
{
//我用0表示普通,显示给用户就是 □
//....1...幸运轮盘,显示组用户就◎
//....2...地雷,显示给用户就是 ☆
//....3...暂停,显示给用户就是 ▲
//....4...时空隧道,显示组用户就 卐
int[] luckyturn = { 6, 23, 40, 55, 69, 83 };//幸运轮盘◎
for (int i = 0; i < luckyturn.Length; i++)
{
Maps[luckyturn[i]] = 1;
}
int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };//地雷☆
for (int i = 0; i < landMine.Length; i++)
{
Maps[landMine[i]] = 2;
}
int[] pause = { 9, 27, 60, 93 };//暂停▲
for (int i = 0; i < pause.Length; i++)
{
Maps[pause[i]] = 3;
}
int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };//时空隧道卐
for (int i = 0; i < timeTunnel.Length; i++)
{
Maps[timeTunnel[i]] = 4;
}
}
public static void DrawMap()
{
Console.WriteLine("图例:幸运轮盘:◎ 地雷:☆ 暂停:▲ 时空隧道:卐");
#region 第一横行
for (int i = 0; i <= 29; i++)
{
Console.Write(DrawStringMap(i));
}//for
#endregion
//画完第一横行后应该换行
Console.WriteLine();
#region 第一竖行
for (int i = 30; i <= 34; i++)
{
for (int j = 0; j < 29; j++)
{
Console.Write(" ");
}
Console.WriteLine(DrawStringMap(i));
}
#endregion
#region 第二横行
for (int i = 64; i >= 35; i--)
{
Console.Write(DrawStringMap(i));
}
#endregion
//画完第二横行后应该换行
Console.WriteLine();
#region 第二竖行
for (int i = 65; i <= 69; i++)
{
Console.WriteLine(DrawStringMap(i));
}
#endregion
#region 第三横行
for (int i = 70; i <= 99; i++)
{
Console.Write(DrawStringMap(i));
}
#endregion
//画完最后一行后应该换行
Console.WriteLine();
}
///
/// 抽象出来的画地图的方法 返回一个要画的字符串
///
/// 当前地图坐标
///
public static string DrawStringMap(int i)
{
string str = "";
if (PlayerPos[0] == PlayerPos[1] && PlayerPos[1] == i)
{
str="<>";
}
else if (PlayerPos[0] == i)
{
str="A";//shift+空格 切换全角/半角
}
else if (PlayerPos[1] == i)
{
str="B";
}
else
{
switch (Maps[i])
{
case 0:
Console.ForegroundColor = ConsoleColor.DarkYellow;
str="□";
break;
case 1:
Console.ForegroundColor = ConsoleColor.Red;
str="◎";
break;
case 2:
Console.ForegroundColor = ConsoleColor.Green;
str="☆";
break;
case 3:
Console.ForegroundColor = ConsoleColor.Blue;
str="▲";
break;
case 4:
Console.ForegroundColor = ConsoleColor.DarkGray;
str="卐";
break;
}//switch
}//else
return str;
}//方法的结束括号
///
/// 玩游戏
///
///
public static void PlayGame(int playerNumber)
{
#region 玩游戏的过程
Random r = new Random();
int rNumber=r.Next(1,7);
Console.WriteLine("玩家{0}按任意键开始掷骰子", PlayerName[playerNumber]);
Console.ReadKey(true);//按下的任意键不在控制台中显示
Console.WriteLine("玩家{0}掷出了{1}", PlayerName[playerNumber],rNumber);
PlayerPos[playerNumber] += rNumber;
ChangePos();
Console.ReadKey(true);
Console.WriteLine("玩家{0}按任意键开始行动", PlayerName[playerNumber]);
Console.ReadKey(true);
Console.WriteLine("玩家{0}行动完了", PlayerName[playerNumber]);
Console.ReadKey(true);
//如果玩家A踩到了玩家B
if (PlayerPos[playerNumber] == PlayerPos[1-playerNumber])
{
Console.WriteLine("玩家{0}踩到了玩家{1},玩家{2}退6格", PlayerName[playerNumber], PlayerName[1 - playerNumber], PlayerName[1 - playerNumber]);
Console.ReadKey(true);
PlayerPos[1 - playerNumber] -= 6;
ChangePos();
Console.WriteLine("玩家{0}退了5格", PlayerName[1 - playerNumber]);
Console.ReadKey(true);
}
else//玩家A并没有踩到玩家B,而是踩到了特殊的关卡上
{
switch (Maps[PlayerPos[playerNumber]])
{
case 0: Console.WriteLine("玩家{0}踩到了方块,什么都不发生", PlayerName[playerNumber]);
Console.ReadKey(true);
break;
case 1: Console.WriteLine("玩家{0}踩到了幸运轮盘,请选择 1--交换位置 2--轰炸对方", PlayerName[playerNumber]);
string input = Console.ReadLine();
while (true)
{
if (input == "1")
{
Console.WriteLine("玩家{0}选择了跟玩家{1}交换位置", PlayerName[playerNumber], PlayerName[1 - playerNumber]);
int temp = PlayerPos[playerNumber];
PlayerPos[playerNumber] = PlayerPos[1 - playerNumber];
PlayerPos[1 - playerNumber] = temp;
ChangePos();
Console.ReadKey(true);
break;
}
else if (input == "2")
{
Console.WriteLine("玩家{0}选择了轰炸玩家{1},玩家{2}退6格", PlayerName[playerNumber], PlayerName[1 - playerNumber], PlayerName[1 - playerNumber]);
PlayerPos[1 - playerNumber] -= 6;
ChangePos();
Console.ReadKey(true);
break;
}
else
{
Console.WriteLine("输入有误,请重新输入 1--交换位置 2--轰炸对方");
input = Console.ReadLine();
}
}
break;
case 2: Console.WriteLine("玩家{0}踩到了地雷,退6格", PlayerName[playerNumber]);
PlayerPos[playerNumber] -= 6;
ChangePos();
Console.ReadKey(true);
break;
case 3: Console.WriteLine("玩家{0}踩到了暂停,暂停一回合", PlayerName[playerNumber]);
Flags[playerNumber] = true;
Console.ReadKey(true);
break;
case 4: Console.WriteLine("玩家{0}踩到了时空隧道,前进10格", PlayerName[playerNumber]);
PlayerPos[playerNumber] += 10;
ChangePos();
Console.ReadKey(true);
break;
}
}
Console.Clear();
DrawMap();
#endregion
}
///
/// 当玩家坐标发生改变的时候 判断玩家的坐标 让玩家一直保持在这个地图上
///
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;
}
}
///
/// 胜利啦!!!
///
public static void Win()
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(" ◆ ");
Console.WriteLine(" ■ ◆ ■ ■");
Console.WriteLine(" ■■■■ ■ ■ ◆■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ■ ◆ ■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■■■■■■ ■■■■■■■ ■ ■ ■");
Console.WriteLine(" ■■■■ ■ ■ ●■● ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ● ■ ● ■ ■ ■");
Console.WriteLine(" ■ ■ ■■■■■■ ● ■ ● ■ ■ ■");
Console.WriteLine(" ■■■■ ■ ● ■ ■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ■ ■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ■ ■ ■ ");
Console.WriteLine(" ■ ■ ■ ■ ● ■ ");
Console.WriteLine(" ■ ■■ ■■■■■■ ■ ● ●");
Console.ResetColor();
}
}
}
[访问修饰符] class 类名
{
类的成员;
//字段、属性、方法
}
访问修饰符:public
类名:Pascal 要求每个单词的首字母都要大写。
称之为类的实例化。
使用关键字 new.
1)、字段:存储数据
private:私有的,只能在类的内部访问,出了这个类之后,就访问不到了。
this代表当前类的对象
既有get方法也有set方法的属性我们称之为可读可写属性
只有get方法没有set方法我们称之为只读属性
只有set方法没有get方法我们称之为只写属性
对象创建好后,依次的给对象的每个属性赋值,这个过程我们称之为对象的初始化。
主要作用就是对 对象进行初始化。(相当于是python中__init__)
构造函数其实就是一个函数,只不过是一个特殊的函数。
语法:
public 构造函数名()
{
代码;
}
1、没有返回值,连void也不能写。
2、构造函数的名称必须跟类名一致。
new的作用:
1)、在内存的堆中开辟空间
2)、在开辟的堆空间中创建对象
3)、调用对象的构造函数
1)、可以重载
2)、类中默认会有一个无参数的构造函数,当你写了一个新的构造函数后,那个默认的无参数的
构造函数就被干掉了。
静态成员需要被static修饰,非静态成员不需要加static。
问题1:在一个非静态类中,是否允许出现静态成员?
答:非静态类中是可以出现静态成员的。
问题2:在非静态函数中,能不能够访问到静态成员?
答:在非静态函数中,既可以访问到非静态成员,也可以访问到静态成员。
问题3:在静态函数中,能不能够访问到非静态成员?
答:静态方法只能够访问到静态成员。
问题4:在静态类中能否出现非静态成员?
答:不可以,在静态类中,只允许出现静态成员。
1、在调用实例成员的时候,需要使用对象去调用
2、在调用静态成员的时候,必须使用类名.静态成员名;
3、静态类是不允许创建对象的
什么时候使用静态类,什么时候使用非静态类?
如果你写的类属于工具类,可以考虑写成静态类。
静态的好处:资源共享。
静态类应该越少越好。
15、GC Gargbage Collection
当我们程序结束之后,GC会扫描整个内存,发现,如果有的空间没有被指向,
则马上把这块空间销毁。
16、在一个项目中引用另一个项目的类
1、添加要引用的类所在的项目。
2、引用命名空间
17、访问修饰符
public :公开的,公共的
private:私有的,只能在类的内部访问,出了这个类之后,就访问不到了。
能够修饰类的访问修饰符只有两个:
1)、public
2)、internal:表示只能在当前程序集的内部进行访问,出了这个程序集就访问不到啦。
对于咱们而言,现阶段就将程序集理解为当前项目。
18、字符串
由于字符串的不可变性,所以,当我们需要给一个字符串进行大量的拼接、赋值等操作的时候,
会产生大量的内存垃圾,所以说,这么做是不合算的。
如果你需要对一个字符串进行大量的重复,拼接等操作,我们推荐使用StringBuilder
19、字符串的各种方法
ToCharArray():将字符串转换成char类型的数组
new string(char[] chs):将一个字符数组转换成一个字符串
ToUpper():表示将一个字符串转换成大写形式。
ToLower():表示将一个字符串转换成小写形式。
Equals(“要比较的字符串”,StringComparison.OrdinalIgnoreCase):比较字符串,忽略大小写
Split(new char[]{‘要分割的字符串’},StringSplitOption.RemoveEmptyEntries):分割字符串,返回一个字符串类型的数组
Substring():截取字符串
我们在写类的过程当中,会发现,在多个类当中会存在一些相同的属性和方法。
为了解决这种代码冗余,于是乎,我们使用继承来解决这个问题。
我们把一些类当中所共同具有的属性和方法单独的拿出来封装成一个父类。
然后让其他类去继承这个父类。
如果一个类继承了另一个类,我们管这个类称之为子类,管被继承的那个类称之为父类。
或者 管这类称之为派生类,管被继承的那个类称之为基类。
语法:
:要继承的类
字段、属性、方法、构造函数
子类继承了父类的属性和方法。
子类并没有继承父类的私有字段。
子类并没有继承父类的构造函数,而是会默认的调用父类那个无参数的构造函数,
当你在父类中写了一个有参数的构造函数之后,那个默认的无参数的构造函数就被干掉了,
此时子类就调不到那个无参数的构造函数了。
解决办法:
1)、在父类中重新写一个无参数的构造函数。
2)、让子类去显示的调用父类有参数的构造函数。使用关键字:base()
1、单根性,一个子类只能有一个父类。一个儿子只能有一个爹。
2、传递性,爷爷有的,爹肯定有,爹有的,最终儿子也会有。
1)、创建对象
2)、隐藏从父类那里继承过来的成员
1)、代表当前类的对象
2)、显示的调用自己的构造函数
1)、子类可以赋值给父类。
2)、如果这个父类中装的是子类对象,那么可以将这个父类强转为子类对象。
is:类型转换 ,如果转换成功,返回一个true,否则返回一个false。
as:类型转换,如果转换成功,则返回对应的对象,如果转换失败,返回一个null。
1、使用快捷键 alt+shift+F10
2、使用鼠标的方式
Exist():判断指定的文件是否存在
Move():对一个指定的文件进行剪切操作
Copy():对一个指定的文件进行复制操作
Create():创建一个新文件
Delete():删除一个指定的文件