c#基础知识

1,复杂数据类型概述。

前景提要
数据(变量)类型(几个字节,存储数位)
无符号变量:byte、ushort、uint、ulong
有符号变量:sbyte,short,int,long
浮点数:float,double,decimal
特殊类型:bool、char、string

复杂数据(变量)类型特点

1.数据集合

一般是多个数据(变量)集合在一起构成的数据

2.自定义

一般可以自己取名字,可以自定义的数据(变量)

例子:

枚举:整形常量的集合,可以自定义

数组:任意变量类型顺序存储的数据

结构体:任意变量的数据集合,可以自定义

111.枚举:

1.枚举是什么:枚举是一个比较特别的存在,它是一个被命名的整形常量的集合。一般用它来表示 状态 类型 等等

2.声明枚举 和 申明枚举变量::注意:串明枚举 和 声明枚举变量是两个概念!

声明枚举:相当于是 创建一个自定义的枚举类型

声明枚举变量:使用声明的自定义枚举类型 创建一个枚举变量

枚举关键字:enum
3.声明枚举语法

枚举名命名规范: 以E或者E 开头

例子:

enum E_ 自定义枚举名

{

白定义枚举项名字,//枚举中包裹的 整形常量 第一个默认值是。 下面会依次累加

自定义枚举项名字1,//1

自定义枚举项名字2,//2

}

22,在哪里声明

在namspace 语句块(常用),在class语句块中, struct语句块中。

注意:枚举不在函数语句中声明

例子:

enum E_PlayerType

{

Main,//1

other,//2

}

33,枚举的使用

声明枚举是在方法里面的:自定义枚举类型 变量名 = 默认值;(自定义的枚举类型。枚举项)

E PlayerType playerType =E PlayerType.Main;

if( playerType ==E_PlayerType.Main )

{

Console.WriteLine("主玩家逻辑");

}

else if(playerType ==E PlayerType.0ther)

{

Console.WriteLine("其它玩家逻辑");

}

//枚举和switch搭配使用

E MonsterType monsterType =E MonsterType.Boss;

switch(monsterType)

{

case E MonsterType.Normal:

break;

case E MonsterType.Boss:

break;

default:

break;

}

44,枚举的类型转换

//1.枚举和int互转(括号强转)

int i=(int)playerType;

Console.WriteLine(i);

//int 转枚举

playerType = 0;

//2.枚举和string相互转换

string str = playerType.Tostring();

Console.WriteLine(str);

把string转成枚举呢?Parse后 第一个参数 :你要转的是哪个 枚举类型, 第二个参数:用于转换的对应枚举项的字符串。。转换完毕后 是一个通用的类型 我们需要用括号强转成我们想要的目标枚举类型。

看习题

55,枚举的作用

1,在游戏开发中,对象很多时候 会有许多的状态:比如玩家 有一个动作状态 我们需要用一个变量或者标识 来表示当前玩家处于的是哪种状态

2,综合考虑 可能会使用 int 来表示他的状态:1 行走 2 待机 3 跑步 4 跳跃。。。。。。。

3,枚举可以帮助我们 清晰的分清楚状态的含义

.数组

11,一维数组

数组是存储一组相同类型数据的集合:数组分为 一维、多维、交错数组。一般情况 一维数组 就简称为 数组。

数组的声明:变量类型[]数组名;//只是声明了一个数组

01 变量类型 所有变量类型都可以int[] arrls;或者 int a = 10;

02变量类型[]数组名 = new 变量类型[数组的长度]; int[]arr2 = new int[5];//这种方式 相当于开了5个房间 但是房间里面的int值 默认为8

03变量类型[]数组名 = new 变量类型[数组的长度]{内容1,内容2,内容3,} int[]arr3 =new int[5]{1,2,3,4,5 };

04变量类型[]数组名 = new 变量类型[]{内容1,内容2,内容3.} int[] arr4 = new int[]{ 1,2,3,4,5,6,7,8,9};//后面的内容就决定了 数组的长度"房间数"

05变量类型[]数组名 ={内容1,内容2,内容3,...}; int[] arr5 ={ 1,3,4,5,6};

数组的使用

int[]array ={1,2,3,4,5 };

1.数组的长度.Length

2.获取数组中的元素

数组中的下标和索引 他们是从@开始的...。通过 索引下标去 获得数组中某一个元素的值时

一定注意:不能越界 数组的房间号 范围 是0 ~ Length-1

Console.WriteLine(array[0]);

Console.WriteLine(array[2]);

Console.WriteLine(array[4]);
3.修改数组中的元素

array[0]= 99;

Console.WriteLine(array[0]);
4.遍历数组 通过循环 快速获取数组中的每一个元素

Console.WriteLine("*******************")

for(int i=0;i< array.Length; i++)

{

Console.WriteLine(array[i]);

}
5.增加数组的元素
数组初始化以后 是不能够 直接添加新的元素的::::

int[] array2 = new int[6];

for(int i=0;i< array.Length; i++)

{

array2[i]= array[i];

array = array2;

}

for(int i=0;i< array.Length; i++)

{

Console.WriteLine(array[i]);

}

array[5]= 999;

Console.WriteLine("*******")

6.删除数组的元素

数组初始化以后 是不能够 直接删除元素的

int[] array3 = new int[5];

for(int i=0;i< array3.Length; i++)

{

array3[i]= array[i];

}

array = array3;

Console.WriteLine(array.Length);
7.查找数组中的元素

// 要查找 元素在哪个位置

// 只有通过遍历才能确定 数组中 是否存储了一个日标元素

例子:

int a = 3;

for(int i=0;i<array.Length; i++)

{

if( a == array[i])

Console.WriteLine("和a相等的元素在{0}索引位置",i);

break;

}

}
总结
1.概念:同一变量类型的数据集合
2.一定要掌握的知识:中明,遍历,增删查改
3.所有的变量类型都可以申明为 数组
4.她是用来批量存储游戏中的同一类型对象的 容器 比如 所有的怪物 所有玩家

二维数组

概念:二维数组 是使用两个下标(索引)来确定元素的数组,两个下标可以理解成 行标 和 列标。比如矩阵

例子:

可以用二维数组 in+[2,3]表示。好比 两行 三列的数据集合

声明:

01量类型[,]二维数组变量名;

int[ , ]arr;//申明过后 会在后面进行初始化

02变量类型[ , ]二维数组变量名 = new 变量类型[行,列];

int[,] arr2 = new int[3, 3];

03变量类型[,]二维数组变量名 = new 变量类型[行,列]

int[,]arr3 =new int[3,3]{{1,2,3 },

{4,5,6}

{7,8,9 }};

04变量类型[,]二维数组变量名 = new 变量类型[,]

int[,]arr4 = new int[,]{{1,2,3 },

{4,5,6 },

{7,8,9}};

05变量类型[,]二维数组变量名 ={{0行内容1,0行内容2,0行内容3.

int[,]arr5 ={{1,2,3 },

{4,5,6},

{7,8,9}};

交错数组

1.交错数组 是 数组的数组,每个维度的数量可以不同.。注意:二维数组的每行的列数相同,交错数组每行的列数可能不同

01变量类型[][]交错数组名;

int[][] arrls

02变量类型[[] 交错数组名 = new

03变量类型[行数][];

int[][] arr2 = new int[3][];

04变量类型[][] 交错数组名 = new 变量类型[行数][]{ 一维数组1,一维数组2,... };

int[][] arr3 = new int[3][]

{

new int[]{1,2,3 },

new int[]{1,2,3 },

new int[] { 1,2.3 }};

}

使用:

int[][] array ={ new int[]{ 1,2,3},

new int[]{ 4,5} };

1.数组的长度
01 行

Console.WriteLine(array.GetLength(0));
02 得到某一行的列数

Console.WriteLine(array[0].Length);
2.获取交错数组中的元素

Console.WriteLine(array[0][1]);
3.修改交错数组中的元素

4.遍历交错数组

for(int i=0;i<array.GetLength(0);i++)

{

for(int j=0;j< array[i].Length; j++)

{

Console.Write(array[i][j]+"");

}

Console.WriteLine();

}

值类型与引用类型

变量类型的复习
01无符号整形

byte b = 1;

ushort us = 1;

uint yi = 1;

ulong ul = 1;
02有符号整形

sbyte sb =1;

short s.= 1;

int i = 1;

long 1.= 1;
03浮点数

float f = 1f;

double d = 1.1;

decimal de =1.1m;
04特殊类型

bool bo = true;

char c.= 'A';

string str ="strs"
05复杂数据类型
enum 枚举
数组(一维,二维,交错)

值类型

int a = 10;

01引用类型

int[]arr = new int[]{1,2,3,4 };

02中明了一个b让其等于之前的a

int b = a;

03申明了一个arr2让其等于之前的arr

int[] arr2 = arr;

Console.WriteLine("a={0},b={1}",a, b);

Console.WriteLine("arr[e]={0},arr2[0]={1}",arr[0],arr2[0]);

b= 20;

arr2[0]= 5;

Console.WriteLine("修改了b和arr2[0]之后");

Console.WriteLine("a={0},b={1}",a, b);

Console.WriteLine("arr[0]={0},arr2[0]={1}",arr[0],arr2[0]);

值类型 在相互赋值时 把内容拷贝给了对方 它变我不变

引用类型的相互赋值 是 让两者指向同一个值 它变我也变

2.为什么有以上区别

值类型 和 引用类型 存储在的 内存区域 是不同的 存储方式是不同的,所以就造成了 他们在使用上的区别:

值类型存储在 栈空间- 系统分配,自动回收,小而快

引用类型 存储在 堆空间 - 手动申请和释放,大而慢

string的 它变我不变

因为string是引用类型 :string非常的特殊 它具备 值类型的特征 它变我不变

string 虽然方便 但是有一个小缺点 就是频繁的 改变string 更新赋值

会产生 内存垃圾

函数

函数(方法)本质是一块具有名称的代码块,可以使用函数(方法)的名称来执行该代码块。函数(方法)是封装代码进行重复使用的一种机制

函数(方法)的主要作用1.封装代码2,提升代码复用率(少写点代码)3.抽象行为

函数写在哪里:1.class语句块中2.struct语句块中

基本语法

1 2 3 4

static 返回类型 函数名(参数类型 参数名1,参数类型 参数名2,

函数的代码逻辑

函数的代码逻辑:

函数的代码逻辑;

5

return 返回值;(如果有返回类型才返回)

解释:

1.关于static: 类和结构体之前 都是必须写的
2-1.关于返回类型 引出一个新的关键字void(表示没有返回值)
2-2.返回类型 可以写任意的变量类型,14种变量类型 + 复杂数据类型(数组、枚举、结构体、类class)
3.关于函数名 使用帕斯卡命名法命名myName(驼峰命名法)MyName(帕斯卡命名法)
4-1.参数不是必须的,可以有0~n个参数 参数的类型也是可以是任意类型的 14种变量类型 + 复杂数据类型(数组、枚举、结构体、类class)多个参数的时候 需要用 逗号隔开
4-2.参数名 驼峰命名法
5.当返回值类型不为void时 必须通过新的关键词 return返回对应类型的内容 (注意:即使是void也可以选择性使用return)

函数的实际运用

1.无参无返回值的数

static void sayHellow()

{

Console.WriteLine("你好世界");

}

2.有参无返回值函数

1 2 3 4

static void SayYourName(string name)

{

Console.WriteLine("你的名字是:{0}",name);

}

// return;省略了

3.无参有返回值函数

static stringWhatYourName()

{

return"填丫丫 ";

}

4.有参有返回值函数

static int Sum(int a, int b)

{

//int c= a+ b;

//return c;

return a+b;

}

5.有参有多返回值函数

传入两个数 然后计算两个数的和 以及他们两的平均数 得出结果返回出来

函数的返回值 一定是一个类型 只能是一个内容

static int[] calc(int a, int b)

{

int sum = a + b;

int avg =sum /2;

//int[]arr ={ sum, avg };

//return arr;

return new int[l{sum, avg};

}

关于return

即使函数没有返回值,我们也可以使用return,

return:可以直接不执行之后的代码,直接返回到函数外部.02 可以提前结束函数逻辑,程序是线性执行了,从上到下。

ref和out

**1,ref和out:**它们可以解决 在函数内部改变外部传入的内容 里面变了外面也要变

2.ref和out的使用

函数参数的修饰符。当传入的值类型参数在内部修改时 或者引用类型参数在内部重新申明时,外部的值会发生变化。

例子:

static void changeValueRef(ref int value)

{

value = 3;

}

static void changeArrayRef( ref int[] arr )

{

arr = new int[]{100,200,300 };

}

ref和out的区别

1.ref传入的变量必须初始化 out不用

2.out传入的变量必须在内部赋值 ref不用

ref传入的变量必须初始化 但是在内部 可改可不改

out传入的变量不用初始化 但是在内部 必须修改该值(必须赋值A

变长参数

变长参数关键字 params

举例 函数要计算 n个整数的和

//static int Sum(int a,int b。。。。。。。)

//变长参数关键字 params

2个引用

static int Sum(params int[] arr)

{

int sum =0;

for(int i=0;i< arr.Length; i++)

{

sum += arr[i];

return sum;

}

}

//params int[]意味着可以传入n个int参数 n可以等于8 传入的参数会存在arr数组中

注意:

1.params关键字后面必为数组。

2.数组的类型可以是任意的类型

3.函数参数可以有 别的参数和 params关键字修饰的参数

4.函数参数中只能最多出现一个params关键字 并且一定是在最后一组参数 前面可以有n个其它参数

示例:

static void Eat( string name, int a, int b, params string[] things.

{

}

参数默认值

有参数默认值的参数 一般称为可选参数

作用是: 当调用函数时可以不传入参数,不传就会使用默认值作为参数的值

static void Speak(string sjtr ="我没什么话可说")

{

Console.WriteLine(str);

}

注意:

1.支持多参数默认值 每个参数都可以有默认值

2.如果要混用 可选参数 必须写在 普通参数后面

例子:

static void Speak( string a,string sjtr ="我没什么话可说",string sttr ="我没什么话可说")

{

Console.WriteLine(str);

}

函数重载

基本概念

概念:同一个语句块中,函数名相同,参数数量、类型、顺序不同的函数 就称为我们的重载函数

注意: 和返回值无关

作用: 一般用来处理不同参数的同一类型的逻辑处理。

汪意:1.重载和返回值类型无关,只和参数类型,个数,顺序有关 2.调用时 程序会自己根据传入的参数类型判断使用哪一个重载参数数量不同

static int CalcSum(int a, int b)

{

return a + b;

}

//参数数量不同

static int CalcSum(int a,int b,int c)

{

return a +b+c;

}

//数量相同 类型不同

static int CalcSum(int a,int b)

{

return a +b;

}

//数量相同 类型不同

static float CalcSum(int a, float f)

{

return a + f;

}

//数量相同 顺序不同

static float CalcSum(float f, int a)

{

return f+a;

}

ref 和 out

static float CalcSum(ref float f, int a)

{

return f+ a;

}

static float calcSum(int a, int b, params int[] arr)

{

return 1;

}

static void Main(string[] args)

{

Console.WriteLine("函数重载");

Calcsum(1,2);

Calcsum(1.1f,2);

Calcsum(1,2,3);

Calcsum(1,1.2f);

}

递归函数

基本概念: 递归函数就是让函数自己调用自己

一个正确的递归函数 1.必须有结束调用的条件 2.用于条件判断的 这个条件 必须改变 能够达到停止的目的

实例:

//用递归函数打印出 0到10

//递归函数 就是自己调用自己

static void Main(string[] args)

{

// 正常情况

Fun(1); // 打印1-10

// 边界情况

Fun(10); // 只打印10

// 无效输入

Fun(0); // 显示错误信息

Fun(-5); // 显示错误信息

}

static void Fun(int a)

{

// 参数验证

if (a <= 0)

{

Console.WriteLine("输入参数必须大于0");

return;

}

// 递归终止条件

if (a > 10)

{

return;

}

// 打印当前值

Console.WriteLine(a);

// 递归调用

Fun(a + 1);

}

结构体

基本概念

结构体是一种自定义变量类型 类似枚举需要自己定义,它是数据和函数的集合。在结构体中 可以申明各种变量和方法。

作用:用来表现存在关系的数据集合 比如用结构体表现学生 动物 人类等等

基本语法

1.结构体一般写在 namespace语句块中

2.结构体关键字 struct

struct 自定义结构体名

{

第一部分

// 变量

第二部分

// 构造函数(可选)

第三部分

// 函数

}

实例

struct

{

函数方法

//表现这个数据结构的行为

//注意 在结构体中的方法 目前不需要加static关键字

0 个引用

void speak()

{

//函数中可以直接使用结构体内部申明的变量

Console.WriteLine("我的名字是{0},我今年{1}岁",name,age);

}

//可以根据需求 写无数个函数的

}

结构体的构造函数

/基本概念
//1.没有返回值
//2.函数名必须和结构体名相同
//3.必须有参数
//4.如果申明了构造函数 那么必须在其中对所有变量数据初始化

冒泡排序

排序的基本概念

//排序是计算机内经常进行的一种操作,其目的是将一组"无序"的记录序列调整为"有序"的记录序列

//常用的排序例子

//871542639

// 把上面的这个无序序列 变为 有序(升序或降序)序列的过程

//123456789(升)

//987654321(降序)

//在程序中 序列一般 存储在数组当中

//所以 排序往往是对 数组进行排序

int[]arr =hew int[]{8,7,1,514,2,6,3,9,};

//把数组里面的内容变为有序的

冒泡排序基本原理
//871542639
两两相邻
不停比较
不停交换
比较n轮

代码实现

示例:

//第一步 如何比较数组中两两相邻的数

//8,7,1,5,4,2,6,3,9

//从头开始

//第n个数和第n+1个数 比较

for(intn=0;n<arr.Length-1;n++)

{

//如果 第n个数 比第n+1个数 大 他们就要交换位置

if( arr[n]>arr[n + 1])

{

// 第二步 交换位置

// 中间商不赚差价

int temp = arr[n];

arr[n]= arr[n +1];

arr[n +1]= temp;

}

}

声明的数组:(粉色最终,红色第二步)

int[]arr =new int[]{8,7,1,5,4,2,6,3,9,};

int[] arr = new int[] { 8, 7, 1, 5,7,2,6,3, 9, };

//有几个数 就比较多少轮 m

for (int m = 0; m<arr.Length; m++)

{

bool isSort = false;

// 一次循环 就要比较一轮//m是减去m轮,剩下的伦去比较

for (int n = 0; n < arr.Length - m; n++)

{

//如果 第n个数 比第n+1个数 大 他们就要交换位置

if (arr[n] > arr[n + 1])

{

isSort = true;

// 第二步 交换位置

// 中间数

int temp = arr[n];

arr[n] = arr[n + 1];

arr[n + 1] = temp;

}

}

if (!isSort)

{

break;

}

}

如果一轮结束后,issort标识是false就意味着已经是最终的序列了,不需要再判断交换了。

issort标识是为了能够使得不需要比较的可以不移动(也就是最后几个以确定的不需要再去比较)

for (int i = 0; i < arr.Length; i++)

{

Console.WriteLine(arr[i]);

}

总结
基本概念:两两相邻,不停比较,不停交换,比较m轮,套路写法,两层循环,外层轮数内层比较,两值比较,满足交换
如果优化 1.比过不比2.加入boo1

选择排序:

选择排序基本原理//87 1 5 4
新建中间商
依次比较
找出极值(最大或最小)
放入目标位置
比较n轮

语法

internal class Program

{

static void Main(string[] args)

{

int[] arr = new int[] { 0, 5 };

//05 比较m伦

for (int m = 0; m < arr.Length; m++)

{

//声明中间值来记录索引

//每一轮开始默认第一个都是极值

int index = 0;

//02依次比较:-m是:排除上一轮已经放好的数

for (int n = 0;n < arr.Length-m ; n++)

{

//03 找到最大值

if (arr[index] < arr[n])

{

index = n;

}

}

//04放入目标位置:length-1-轮数 。 如果当前极值是目标位置,那就没必要交换了。

if (index != arr.Length - 1 - m )

{

int temp = arr[index];

arr[index] = arr[arr.Length - 1 - m];

arr[arr.Length - 1 - m] = temp;

}

}

//打印值

for(int i = 0; i < arr.Length; i++)

{

Console.WriteLine(arr[i]+" ");

}

//总结
//基本概念:新建中间商;依次比较
找出极值
放入目标位置
比较n轮
套路写法
两层循环
外层轮数
内层寻找
初始索引
记录极值
内存循环外交换

}

}

相关推荐
༒࿈༙྇洞察༙༙྇྇࿈༒1 分钟前
PostgreSQL快速入门
数据库·postgresql
携欢5 分钟前
Portswigger靶场之Visible error-based SQL injection通关秘籍
数据库·sql
-XWB-32 分钟前
PostgreSQL诊断系列(4/6):表空间与膨胀分析——解决“越用越大”的存储难题
数据库·postgresql
幸福清风34 分钟前
【SQL】深入理解MySQL存储过程:MySQL流程控制语句详解
数据库·sql·mysql
她说人狗殊途1 小时前
DDL DML DQL DCL 语句
数据库·oracle
爱隐身的官人2 小时前
爬虫基础学习-爬取网页项目(二)
前端·爬虫·python·学习
Ysn07193 小时前
pytorch_grad_cam 库学习笔记—— Ablation-CAM 算法的基类 AblationCAM 和 AblationLayer
pytorch·笔记·学习
**AE86**3 小时前
sed截取慢SQL大文件并导出指定时间范围内容
数据库·sql·sed
霜绛4 小时前
Unity笔记(七)——四元数、延迟函数、协同程序
笔记·学习·unity·游戏引擎