复杂数据类型

主要了解枚举类、数组、结构体

枚举类

含义:是一个被命名的整型常量的集合

a.申明枚举(自定义类型)

申明位置:在namespace内声明

命名规范:E_变量名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace ConsoleApp1
{
enum E_MonsterType
{
Normal,
Boss
}

enum E_PlayerType
{
Main,
Other
}

class Program
{
static void Main(string[] args)
{
Console.WriteLine(E_shuzi.a);
}
}
}

b.使用枚举变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace ConsoleApp1
{
enum E_MonsterType
{
Normal,
Boss
}

enum E_PlayerType
{
Main,
Other
}

class Program
{
static void Main(string[] args)
{
E_PlayerType playerType = E_PlayerType.Main;
switch (playerType)
{
// 配合枚举更加直观
case E_PlayerType.Main:
Console.WriteLine("Main Player");
break;
case E_PlayerType.Other:
Console.WriteLine("Other Player");
break;
}
}
}
}

c.枚举类型的相互转化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Program
{
static void Main(string[] args)
{
E_PlayerType playerType;
playerType = E_PlayerType.Main;
// 枚举转为int
int i = (int)playerType;
Console.WriteLine(i);

// int 转化为枚举
E_PlayerType playerType2 = (E_PlayerType)1;
Console.WriteLine(playerType2);

// 枚举转为字符串
string str = playerType.ToString();
Console.WriteLine(str);

// 字符串转为枚举
E_PlayerType playerType3 = (E_PlayerType)Enum.Parse(typeof(E_PlayerType), "Main");
Console.WriteLine(playerType3);
}
}

练习

  1. 定义QQ状态枚举,并提示用户选择一个在线状态,我们接受输入的数字,并将其转化为枚举类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    namespace ConsoleApp1
    {
    /// <summary>
    /// QQ 状态说明
    /// </summary>
    enum E_UserState
    {
    /// <summary>
    /// 在线
    /// </summary>
    online,
    /// <summary>
    /// 离线
    /// </summary>
    offline,
    /// <summary>
    /// 忙碌
    /// </summary>
    busy,
    /// <summary>
    /// 离开
    /// </summary>
    leave
    }

    class Program
    {
    static void Main(string[] args)
    {
    E_UserState u;
    Console.WriteLine("Enter the user state: 0: online, 1: offline, 2: busy, 3: leave");
    try
    {
    int choice = Convert.ToInt32(Console.ReadLine());
    // int转枚举类型
    u = (E_UserState)choice;
    }
    catch
    {
    Console.WriteLine("Invalid choice");
    return;
    }

    switch (u)
    {
    case E_UserState.online:
    Console.WriteLine("User is online");
    break;
    case E_UserState.offline:
    Console.WriteLine("User is offline");
    break;
    case E_UserState.busy:
    Console.WriteLine("User is busy");
    break;
    case E_UserState.leave:
    Console.WriteLine("User is on leave");
    break;
    default:
    Console.WriteLine("Invalid choice");
    break;
    }
    }
    }
    }
  2. 用户去星巴克买咖啡,分为中杯(35),大杯(40),超大杯(43),请用户选择要购买的类型,用户选择后,打印:您购买了xxx咖啡,花费了35元

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    namespace ConsoleApp1
    {
    /// <summary>
    /// 咖啡的大小
    /// </summary>
    enum E_CoffeeSize
    {
    /// <summary>
    /// 中杯
    /// </summary>
    Medium,
    /// <summary>
    /// 大杯
    /// </summary>
    Large,
    /// <summary>
    /// 超大杯
    /// </summary>
    Huge
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("请输入您的选择,1表示Medium,2表示Large,3表示Huge");
    int choice = Convert.ToInt32(Console.ReadLine());
    E_CoffeeSize coffee = (E_CoffeeSize)(choice - 1);
    switch (coffee)
    {
    case E_CoffeeSize.Medium:
    Console.WriteLine("您选择了中杯,花费了35¥");
    break;
    case E_CoffeeSize.Large:
    Console.WriteLine("您选择了大杯,花费了40¥");
    break;
    case E_CoffeeSize.Huge:
    Console.WriteLine("您选择了超大杯,花费了43¥");
    break;
    default:
    Console.WriteLine("您的选择有误");
    break;
    }
    }
    }
    }
  3. 请用户选择英雄的性别和职业,最后打印那你英雄的基本属性(攻击力,防御力,技能)

    性别:

    • 男(攻击力+50 防御力+100)

    • 女(攻击力+150 防御力+20)

    职业:

    • 战士(攻击力+20 防御力+100 技能:冲锋)

    • 猎人(攻击力+120 防御力+30 技能:假死)

    • 法师(攻击力+200 防御力+10 技能:奥术冲击)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    namespace ConsoleApp1
    {
    /// <summary>
    /// 性别
    /// </summary>
    enum E_Gender
    {
    Man,
    Woman
    }

    /// <summary>
    /// 英雄职业
    /// </summary>
    enum E_Profession
    {
    /// <summary>
    /// 战士
    /// </summary>
    Warrior,
    /// <summary>
    /// 猎人
    /// </summary>
    Hunter,
    /// <summary>
    /// 法师
    /// </summary>
    Mage
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("请选择你的性别:");
    Console.WriteLine("1. 男");
    Console.WriteLine("2. 女");
    int genderChoice = Convert.ToInt32(Console.ReadLine());
    // 注意:枚举类型是从0开始的,所以这里要减1
    E_Gender gender = (E_Gender)(genderChoice - 1);

    Console.WriteLine("请选择你的职业:");
    Console.WriteLine("1. 战士");
    Console.WriteLine("2. 猎人");
    Console.WriteLine("3. 法师");
    int profChoice = Convert.ToInt32(Console.ReadLine());
    // 注意:枚举类型是从0开始的,所以这里要减1
    E_Profession profession = (E_Profession)(profChoice - 1);

    int attack = 0;
    int defense = 0;
    string skill = "";

    switch (gender)
    {
    case E_Gender.Man:
    attack += 50;
    defense += 100;
    break;
    case E_Gender.Woman:
    attack += 150;
    defense += 20;
    break;
    }

    switch (profession)
    {
    case E_Profession.Warrior:
    attack += 20;
    defense += 100;
    skill = "冲锋";
    break;
    case E_Profession.Hunter:
    attack += 120;
    defense += 30;
    skill = "假死";
    break;
    case E_Profession.Mage:
    attack += 200;
    defense += 10;
    skill = "奥术冲击";
    break;
    }

    Console.WriteLine("您选择的角色属性如下:");
    Console.WriteLine("攻击力:" + attack);
    Console.WriteLine("防御力:" + defense);
    Console.WriteLine("技能:" + skill);
    }
    }
    }

数组

数组是存储相同类型数据的集合(可以是任何类型)

一维数组

a.申明数组(int类型为例)

方式1

1
int[] arr;

方式2

1
2
3
4
5
6
7
// 默认值是0
int[] arr2 = new int[5];

foreach (int i in arr2)
{
Console.WriteLine(i);// 0
}

方式3

1
2
3
4
5
6
// new int[]也是等价的
int[] arr3 = new int[5] { 1, 2, 3, 4, 5 };
// 编译器提示简写为如下形式
int[] arr3 = [1, 2, 3, 4, 5];
// 大括号和中括号是等价的
int[] arr3 = {1, 2, 3, 4, 5};

b.数组的使用

  1. 长度

    1
    2
    3
    int[] arr = [1, 2, 3, 4, 5];

    Console.WriteLine(arr.Length); // 5
  2. 获取元素

    1
    2
    3
    4
    int[] arr = [1, 2, 3, 4, 5];

    // 通过index获取元素
    Console.WriteLine(arr[0]); // 1

    index不能越界,越界报错。

    Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.

  3. 修改元素

    1
    2
    3
    4
    5
    int[] arr = [1, 2, 3, 4, 5];

    Console.WriteLine(arr[0]); // Output: 1
    arr[0] = 99;
    Console.WriteLine(arr[0]); // Output: 99

    修改后的值类型要相同

  4. 遍历元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int[] arr = [1, 2, 3, 4, 5];

    // 方式一
    for (int i = 0; i < arr.Length; i++)
    {
    Console.WriteLine(arr[i]);
    }

    // 方式二
    foreach (int i in arr)
    {
    Console.WriteLine(i);
    }
  5. 增加元素

    C#不支持直接增加数组的长度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    int[] arr = [1, 2, 3, 4, 5];
    int[] arr2 = new int[6];

    for (int i = 0; i < arr.Length; i++)
    {
    arr2[i] = arr[i];
    }

    // 引用类型 直接传递了地址
    arr = arr2;

    for (int i = 0; i < arr.Length; i++)
    {
    Console.WriteLine(arr[i]);
    }

    arr[2] = 100;
    // 通过arr修改了arr2的值
    Console.WriteLine(arr2[2]); // 100
  6. 删除元素

    C#不能直接删除数组元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int[] arr = [1, 2, 3, 4, 5];
    int[] arr2 = new int[4];

    for (int i = 0; i < arr2.Length; i++)
    {
    arr2[i] = arr[i];
    }

    arr = arr2;

    foreach (int i in arr)
    {
    Console.WriteLine(i);
    }
  7. 查找元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int[] arr = [1, 2, 3, 4, 5];

    // 要查找元素
    int temp = 3;
    for (int i = 0; i < arr.Length; i++)
    {
    if (arr[i] == temp)
    {
    Console.WriteLine("index:{0}", i);
    break;
    }
    }

c.练习

  1. 创建一个以为数组A,在创建一个一维数组B,将A的每个元素乘以2存入B中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Random random = new Random();

    int[] arr = new int[100];

    for (int i = 0; i < arr.Length; i++)
    {
    // Random包头不包尾
    arr[i] = random.Next(1, 101);
    Console.WriteLine(arr[i]);
    }

    int[] arr2 = new int[100];

    for (int i = 0; i < arr2.Length; i++)
    {
    arr2[i] = arr[i] * 2;
    Console.WriteLine(arr2[i]);
    }
  2. 随机(0-100)生成一个长度为10的整数数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Random random = new Random();

    int[] arr = new int[10];

    for (int i = 0; i < arr.Length; i++)
    {
    // Random包头不包尾
    arr[i] = random.Next(0, 101);
    }
  3. 从一个整数数组中找出最大值,最小值,总和,平均值(可以使用随机数0-100)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    Random random = new Random();

    int[] arr = new int[10];

    for (int i = 0; i < arr.Length; i++)
    {
    arr[i] = random.Next(1, 101);
    }

    int max = arr[0];
    int min = arr[0];
    float avg = 0f;

    foreach (int i in arr)
    {
    if (i > max)
    {
    max = i;
    }

    if (i < min)
    {
    min = i;
    }

    avg += i;
    Console.Write(i);
    Console.Write(" ");
    }

    Console.WriteLine();
    avg /= arr.Length;

    Console.WriteLine("Max: " + max);
    Console.WriteLine("Min: " + min);
    Console.WriteLine("Avg: " + avg);
  4. 逆置数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    int[] arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // 找到中枢
    float mid = arr.Length / 2;
    int midInt = (int)mid;

    for (int i = 0; i < midInt; i++)
    {
    // 数据交换
    int temp = arr[i];
    arr[i] = arr[arr.Length - 1 - i];
    arr[arr.Length - 1 - i] = temp;
    }

    for (int i = 0; i < arr.Length; i++)
    {
    Console.Write(arr[i]);
    Console.Write(" ");
    }

    // Output: 10 9 8 7 6 5 4 3 2 1
  5. 将一个整数数组的每一个元素进行如下的处理

    • 如果元素是正数,元素加1
    • 如果元素是负数,元素减1
    • 如果元素是0,则不变
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    Random random = new Random();

    int[] numbers = new int[10];

    for (int i = 0; i < numbers.Length; i++)
    {
    numbers[i] = random.Next(-10, 11);
    Console.Write(numbers[i] + " ");
    }
    Console.WriteLine();
    for (int i = 0; i < numbers.Length; i++)
    {
    int temp = numbers[i];
    if (temp < 0)
    {
    numbers[i] -= 1;
    }
    else if (temp > 0)
    {
    numbers[i] += 1;
    }
    Console.Write(numbers[i] + " ");
    }

    // -1 3 8 0 6 8 9 4 2 4
    // -2 4 9 0 7 9 10 5 3 5
  6. 定义一个长度为10的数组,输入十位同学的成绩,将成绩存入数组中,然后求最高分和最低分,并且求出个同学成绩的平均值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    int[] arr = new int[5];

    int index = 0;
    while (index < 5)
    {
    try
    {
    Console.WriteLine("Enter a number: ");
    arr[index] = Convert.ToInt32(Console.ReadLine());
    index++;
    }
    catch (Exception e)
    {
    Console.WriteLine("Invalid input. Please enter a number.");
    }
    }

    int maxScore = arr.Max();
    int minScore = arr.Min();
    int sum = arr.Sum();
    float avg = sum / 5;

    Console.WriteLine("Max score: " + maxScore);
    Console.WriteLine("Min score: " + minScore);
    Console.WriteLine("avg: " + avg);
  7. 请申明一个string类型的数组(长度为25),通过遍历数组取出其中的符号并打印出如下的效果

    1
       
    1
       

二维数组

按行存储的多个一维数组的集合,且一维数组的长度和类型要相同(同类型数据方阵

image-20250104112047742

a.申明

方式一

1
int[,] arr;

方式二

1
2
// 默认值是0
int[,] arr2 = new int[3, 3];

方式三

1
2
3
4
5
6
7
8
9
10
11
12
13
int[,] arr3 = { 
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
// 不支持集合表达式初始化类型 int[,] arr2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9] ]

// 等价
int [,] arr3 = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};

b.使用二维数组

  1. 获取长度

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

    // 获取行数和列数
    Console.WriteLine(arr.GetLength(0)); // 4
    Console.WriteLine(arr.GetLength(1)); // 3
  2. 获取元素

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

    // 获取元素
    Console.WriteLine(arr[1, 2]); // Output: 6

    注意不要越界

  3. 修改元素

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

    // 修改元素
    arr[0,0] = 100;
    Console.WriteLine(arr[0,0]); // 100
  4. 遍历数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    int [,] arr = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 },
    { 10, 11, 12 }
    };

    // 方式一
    // 获取行号
    for (int i = 0; i < arr.GetLength(0); i++)
    {
    // 获取列号
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }

    // 1 2 3
    // 4 5 6
    // 7 8 9
    // 10 11 12

    // 方式二
    foreach (int i in arr)
    {
    Console.WriteLine(i);
    }
  5. 增加数组

    C#不支持直接增加行数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    int[,] arr = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 },
    };

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

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    arr2[i, j] = arr[i, j];
    }
    }

    // 引用,传递地址
    arr = arr2;
  6. 删除数组

    C#不支持直接增加行数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int[,] arr = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 },
    };

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

    for (int i = 0; i < arr2.GetLength(0); i++)
    {
    for (int j = 0; j < arr2.GetLength(1); j++)
    {
    arr2[i, j] = arr[i, j];
    }
    }

    arr = arr2;
  7. 查找数组元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int[,] arr = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 },
    };

    int search = 5;

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    if (arr[i, j] == search)
    {
    Console.WriteLine($"Element found at index {i}, {j}");
    break;
    }

    }
    }

c.练习

  1. 将1-10000赋值给一个二维数组(100,100)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int[,] arr = new int[100, 100];

    int number = 1;
    for (int i = 0; i <= arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    arr[i, j] = number;
    number++;
    // Console.Write(arr[i, j] + " ");
    }
    // Console.WriteLine();
    }
  2. 将二维数组(4,4)的右上部分清零(元素随机1-100)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    int[,] arr = new int[4, 4];

    Random random = new Random();

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    arr[i, j] = random.Next(1, 101);
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    if (i <= j)
    {
    arr[i, j] = 0;
    }
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }
  3. 求二维数组(3,3)的对角线元素之和(元素随机1-10)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    int[,] arr = new int[3, 3];

    Random random = new Random();

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    arr[i, j] = random.Next(1, 11);
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }

    int sum = 0;
    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    if (i == j)
    {
    sum += arr[i, j];
    }
    }

    }
    Console.WriteLine("Sum of diagonal elements: " + sum);

    /*
    8 9 3
    5 9 9
    3 4 4
    Sum of diagonal elements: 2
    */
  4. 求二维数组(5,5)的最大元素和行列号(元素随机1-500)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    int[,] arr = new int[5, 5];

    Random random = new Random();

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    arr[i, j] = random.Next(1, 501);
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }

    int max = arr[0, 0];
    int maxRow = 0;
    int maxCol = 0;
    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    if (arr[i, j] > max)
    {
    max = arr[i, j];
    maxRow = i;
    maxCol = j;
    }
    }

    }

    Console.WriteLine($"Max element: {max} at row {maxRow} and column {maxCol}");

    /*
    166 180 418 339 64
    167 489 84 419 407
    273 206 216 7 254
    12 4 180 165 114
    103 407 216 479 228
    Max element: 489 at row 1 and column 1
    */
  5. 给一个M*N的二维数组,数组元素的值为0或者1,要求转化宿主,将含有1的行和列全部置为1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    int[,] arr = new int[3, 3];

    Random random = new Random();

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    arr[i, j] = random.Next(0, 2);
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }

    Console.WriteLine("-----------------");

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    for (int j = 0; j < arr.GetLength(1); j++)
    {
    if (arr[i, j] ==1)
    {
    arr[i, j] = 0;
    }
    Console.Write(arr[i, j] + " ");
    }
    Console.WriteLine();
    }



    /*
    0 1 0
    1 1 0
    1 1 1
    -----------------
    0 0 0
    0 0 0
    0 0 0
    */

交错数组

在二维数组的基础上,每行的列数可以不同

image-20250104120147172

a.申明

方式一

1
int[][] arr;

方式二

1
2
// 不可以写列数,因为列数是不确定的
int[][] arr2 = new int[3][];

方式三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int[][] arr3 = new int[3][] {
new int[] {1,2},
new int[] {4,5,6},
new int[] {7,8,9,10},
};

// 等价
int[][] arr4 = {
new int[] {1,2},
new int[] {4,5,6},
new int[] {7,8,9,10},
};

// 等价
int[][] arr5 = {
[1, 2],
[4, 5, 6],
[7, 8, 9, 10]
};

// 等价
// 可以简化集合初始化
int[][] arr6 = [
[1, 2],
[4, 5, 6],
[7, 8, 9, 10]
];

b.使用

  1. 获取长度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int[][] arr = [
    [1, 2],
    [4, 5, 6],
    [7, 8, 9, 10]
    ];

    Console.WriteLine(arr.GetLength(0)); // 3

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    // 取得具体一行在获取长度
    Console.WriteLine(arr[i].Length);
    }
  2. 获取元素

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

    Console.WriteLine(arr[1][2]); // Output: 6
  3. 修改元素

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

    arr[1][2] = 9;
    Console.WriteLine(arr[1][2]); // Output: 9
  4. 遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int[][] arr = [
    [1, 2],
    [4, 5, 6],
    [7, 8, 9, 10]
    ];

    for (int i = 0; i < arr.GetLength(0); i++)
    {
    // 根据具体行来获取长度
    for (int j = 0; j < arr[i].GetLength(0); j++)
    {
    Console.Write(arr[i][j]+" ");
    }
    Console.WriteLine();
    }
    /*
    1 2
    4 5 6
    7 8 9 10
    */
  5. 增加(套路都相同)

  6. 删除(套路都相同)

  7. 查找(套路都相同)

引用类型

a.分类

引用类型:

  • string
  • 数组

值类型:

  • 其他基础类型
  • 结构体

值类型

  • 存储在栈空间,系统自动分配,自动回收,小而快(连续空间)
  • 赋值时,复制一份内容,相互互不影响

引用类型

  • 存储在堆空间,需要申请和释放,大而慢(非连续空间)
  • 赋值时,传递的是地址,会相互影响
  • 变量对应的栈空间所存储的是堆空间的地址

b.复制Copy

引用类型引出了浅复制(ShallowCopy)和深复制(DeepCopy)

  • ShallowCopy 只会复制当前的对象类型,如果有更深层次的引用,那么只会复制地址
  • DeepCopy 会递归复制所有的对象类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class Address
{
public string City { get; set; }
}

class Person
{
public string Name { get; set; }
public Address Address { get; set; }

public Person DeepCopy()
{
// 创建一个新的 Person 对象,并复制所有字段
Person newPerson = new Person
{
Name = this.Name,
Address = new Address { City = this.Address.City }
};
return newPerson;
}


public Person ShallowCopy()
{
return (Person)this.MemberwiseClone();
}
}

class Program
{
static void Main(string[] args)
{
// 创建一个 Person 对象,并初始化其字段
Person original = new Person { Name = "John", Address = new Address { City = "New York" } };

// 浅复制
Person shallowCopy = original.ShallowCopy();
// 深复制
Person deepCopy = original.DeepCopy();

// 修改浅复制对象的字段
shallowCopy.Name = "Jane";
shallowCopy.Address.City = "Los Angeles";

// 修改深复制对象的字段
deepCopy.Name = "Mike";
deepCopy.Address.City = "Chicago";

// 输出原始对象和复制对象的字段值
Console.WriteLine("Original Name: " + original.Name); // 输出:John
Console.WriteLine("Original City: " + original.Address.City); // 输出:Los Angeles

Console.WriteLine("Shallow Copy Name: " + shallowCopy.Name); // 输出:Jane
Console.WriteLine("Shallow Copy City: " + shallowCopy.Address.City); // 输出:Los Angeles

Console.WriteLine("Deep Copy Name: " + deepCopy.Name); // 输出:Mike
Console.WriteLine("Deep Copy City: " + deepCopy.Address.City); // 输出:Chicago
}
}

/*
Original Name: John
Original City: Los Angeles
Shallow Copy Name: Jane
Shallow Copy City: Los Angeles
Deep Copy Name: Mike
Deep Copy City: Chicago
*/

c.特殊的引用类型string

1
2
3
4
5
6
7
string str = "123";
string str2 = str;

str2 = "456";

Console.WriteLine(str); // 123
Console.WriteLine(str2); // 456

C#对string类型做了特殊处理,虽然属于引用类型,但是赋值还是相当于复制

使用VsCode的调试来监视两变量的地址,两变量地址完全不同,这说明传递的并非是地址。

image-20250104155228447

函数

函数基础

也称方法,主要的作用是将代码封装起来,提高代码的复用率。

编写位置:classstruct

构成:

1
2
3
4
5
static 返回类型 函数名(参数类型 参数1,参数类型 参数2)
{
// 函数逻辑
return [可选]
}

规范:

  • 函数名要用帕斯卡命名法

  • 参数名用驼峰命名法,参数类型是任意的

  • 返回值必须与规定的返回类型一致

    void也可以使用return

1
2
3
4
5
6
7
8
static int Add(int num1,int num2)
{
return num1 + num2;
}

int result = Add(1,2);

Console.WriteLine(result);

返回多个值

1
2
3
4
5
6
7
8
9
10
11
// (sum,avg)是元组类型
static (int sum, float avg) DealData(int num1, int num2)
{
int sum = num1 + num2;
float avg = sum / 2.0f;
return (sum, avg); // 返回元组
}

// var是C# 3.0引入的隐式类型,编译器会根据右边的表达式推断出变量的类型
var result = DealData(10, 20); // 调用方法并接收返回的元组
Console.WriteLine($"Sum: {result.sum}, Average: {result.avg}"); // 输出结果

练习

  1. 写一个函数,比较两个数字的大小,返回最大值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    static int MaxNumber(int num1, int num2)
    {
    return num1 > num2 ? num1 : num2;
    }

    int num1 = 12;
    int num2 = 10;
    int result = MaxNumber(num1, num2);
    Console.WriteLine($"{num1}{num2}的最大值是{result}");
  2. 写一个函数,用于计算一个圆的面积和周长,并返回打印

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    static (double area, double length) Calculate(int radio)
    {
    double area = Math.Pow(radio, 2) * Math.PI;
    double length = 2 * radio * Math.PI;
    return (area, length);
    }

    int radio = 2;
    var result = Calculate(radio);
    Console.WriteLine($"半径为{radio}的圆\n面积:{result.area}\n周长:{result.length}");
  3. 写一个函数,求一个数组的总和、最大值、最小值、平均值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    static int[] Calculate(int[] nums)
    {
    int max = nums.Max();
    int min = nums.Min();
    int sum = nums.Sum();
    int avg = sum / nums.Length;

    return [max, min, sum, avg];
    }


    int[] nums = [1, 2, 3, 4, 5];
    var result = Calculate(nums);
    Console.WriteLine("nums的最大值:{0},最小值:{1},总和:{2},平均值:{3}", result[0], result[1], result[2], result[3]);
  4. 写一个函数,判断传入的参数是不是素数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    static bool Justdge(int num)
    {
    for (int i = 2; i < num; i++)
    {
    if (num % i == 0) return false;
    }

    return true;
    }

    int num = 3;
    bool result = Justdge(num);
    if (result)
    {
    Console.WriteLine("{0}是一个素数", num);
    }
    else
    {
    Console.WriteLine("{0}不是一个素数", num);
    }
  5. 写一个函数,判断你输入的年份是否是闰年

    判断条件

    • 年份能被400整除
    • 年份能被4整除,不能被100整除
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    static bool IsLeapYear(string year)
    {
    try
    {
    int temp = Convert.ToInt32(year);
    return temp % 400 == 0 || (temp % 4 == 0 && temp % 100 != 0);
    }
    catch
    {
    Console.WriteLine("输入数字不合规");
    return false;
    }
    }

    string year = "2024";
    if (IsLeapYear(year))
    {
    Console.WriteLine("{0}是闰年", year);
    }
    else
    {
    Console.WriteLine("{0}不是闰年", year);
    }

ref和out

用以实现在函数内部改变传入参数的值

问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void ChangeArray(int[] num)
{
// 无法对引用副本赋值,编译器提示删除未使用的参数num
num = [4, 5, 6];
}

static void PrintArray(int[] num)
{
foreach (int i in num)
{
Console.WriteLine(i);
}
}

int[] num = [1, 2, 3];
PrintArray(num); // 1 2 3
ChangeArray(num);
PrintArray(num); // 1 2 3

使用:

1
2
3
4
5
6
7
8
9
static void ChangeValueRef(ref int num)
{
num = 0;
}

int num = 9;
Console.WriteLine(num); // Output: 9
ChangeValueRef(ref num);
Console.WriteLine(num); // Output: 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void ChangeArrayRef(ref int[] num)
{
// 新建一个数组
num = [4, 5, 6];
}

static void PrintArray(int[] num)
{
foreach (int i in num)
{
Console.WriteLine(i);
}
}

int[] num = [1, 2, 3];
PrintArray(num); // 1 2 3
ChangeArrayRef(ref num);
PrintArray(num); // 4 5 6

out的用法和ref是一摸一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void ChangeArrayOut(out int[] num)
{
// 新建一个数组
num = [4, 5, 6];
}

static void PrintArray(int[] num)
{
foreach (int i in num)
{
Console.WriteLine(i);
}
}

int[] num = [1, 2, 3];
PrintArray(num); // 1 2 3
ChangeArrayOut(out num);
PrintArray(num); // 4 5 6

refout的区别:

  • ref传入的参数必须初始化,out无需初始化
  • out传入的变量必须在内部赋值,ref则不需要

练习:让用户输入用户名和密码,返回给用户一个bool类型的登陆结果,并且还要单独返回给用户一个登录信息。

  • 如果用户名错误,除了返回登录结果之外,登录信息为“用户名错误”
  • 如果密码错误,除了返回登录结果之外,登录信息为“密码错误”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static bool UserLogin(string username, string password, ref string message)
{
if (username == "admin" && password == "admin")
{
message = "";
return true;
}
else if (username != "admin")
{
message = "Invalid username";
return false;
}
else if (password != "admin")
{
message = "Invalid password";
return false;
}

return false;
}

string username = "admin";
string password = "123";
string message = "";

if (UserLogin(username, password, ref message))
{
Console.WriteLine("Login successful");
}
else
{
Console.WriteLine("Login failed: " + message); // 打印
}

变长参数关键字

可以传入n个同类型的参数

  • params后只能是数组,类型任意
  • 只能有一个
  • 混用时,必须写在所有参数之后(比参数默认值的位置要后)

练习:

  1. 求多个数的和与平均数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    static float GetAverage(params int[] numbers)
    {
    float sum = 0;

    foreach (int number in numbers)
    {
    sum += number;
    }

    return sum / numbers.Length;
    }



    Console.WriteLine(GetAverage(numbers: [1, 2, 3, 4, 5])); // 3
    Console.WriteLine(GetAverage(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); // 5.5
    Console.WriteLine(GetAverage(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); // 8
  2. 使用params参数,求多个数字的偶数和与奇数和

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    static (float evenSum, float oddSum) SumEvenOdd(params int[] numbers)
    {
    float evenSum = 0;
    float oddSum = 0;

    for (int i = 0; i < numbers.Length; i++)
    {
    if (i % 2 == 0)
    {
    evenSum += numbers[i];
    }
    else
    {
    oddSum += numbers[i];
    }
    }

    return (evenSum, oddSum);
    }

    var result = SumEvenOdd(1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );

    Console.WriteLine($"Sum of even numbers: {result.evenSum}"); // Output: 25
    Console.WriteLine($"Sum of odd numbers: {result.oddSum}"); // Output: 30

参数默认值

也称可选参数

  • 函数可以不传入此参数,使用默认的参数。
  • 可以有多个
  • 参数混用时,所有的参数默认值必须写在最后面(在变长参数之前)
1
2
3
4
5
6
7
static void SayMyName(string name = "World")
{
Console.WriteLine($"Hello, {name}!");
}

SayMyName(); // Hello, World!
SayMyName("C#"); // Hello, C#!

函数重载

函数名相同,但是传入参数类型、个数和顺序不同的函数,就成为重载函数

最常见的例子是Console.WriteLine(),根据不同的值调用不同的Console.WriteLine,实现的逻辑都是打印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void WriteLine(char value)
{
Out.WriteLine(value);
}

public static void WriteLine(char[]? buffer)
{
Out.WriteLine(buffer);
}

public static void WriteLine(char[] buffer, int index, int count)
{
Out.WriteLine(buffer, index, count);
}

public static void WriteLine(decimal value)
{
Out.WriteLine(value);
}

public static void WriteLine(double value)
{
Out.WriteLine(value);
}

位置:classstruct

规则:

  • 和返回值的类型并无关系,只与参数有关

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    static int GetSum(ref int a, int b)
    {
    return a + b;
    }

    // 报错 已在此范围定义了名为“GetSum”的局部变量或函数
    static float GetSum(int a, int b)
    {
    return a + b;
    }
  • 仅仅只是refout的不同不能实现重载

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static int GetSum(ref int a, int b)
    {
    return a + b;
    }

    // 报错 已在此范围定义了名为“GetSum”的局部变量或函数
    static int GetSum(out int a, int b)
    {
    a = 1;
    return a + b;
    }
  • 重载函数的处理逻辑是完全相同的编译器会根据传入参数的类型自动的选择合适的重载函数

练习:

  1. 请重载一个函数

    让其可以比较两个int,两个float,两个double的大小,并返回较大的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Program
    {
    static int GetMaxNumber(int a, int b)
    {
    return a > b ? a : b;
    }

    static float GetMaxNumber(float a, float b)
    {
    return a > b ? a : b;
    }

    static double GetMaxNumber(double a, double b)
    {
    return a > b ? a : b;
    }

    static void Main()
    {
    int a = 10, b = 20;
    Console.WriteLine("Max number is: " + GetMaxNumber(a, b));

    float c = 10.5f, d = 20.5f;
    Console.WriteLine("Max number is: " + GetMaxNumber(c, d));

    double e = 10.5, f = 20.5;
    Console.WriteLine("Max number is: " + GetMaxNumber(e, f));
    }
    }
  2. 请重载一个函数

    让其可以比较n个int,n个float,n个double的大小,并返回值较大的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Program
    {
    static int GetMaxNumber(params int[] numbers)
    {
    return numbers.Max();
    }

    static float GetMaxNumber(params float[] numbers)
    {
    return numbers.Max();
    }
    static double GetMaxNumber(params double[] numbers)
    {
    return numbers.Max();
    }

    static void Main()
    {
    Console.WriteLine("Max number is: " + GetMaxNumber(1, 2, 3, 4, 5)); // Output: 5
    Console.WriteLine("Max number is: " + GetMaxNumber(1.1f, 2.2f, 3.3f, 4.4f, 5.5f)); // Output: 5.5
    Console.WriteLine("Max number is: " + GetMaxNumber(1.1, 2.2, 3.3, 4.4, 5.5)); // Output: 5.5
    }
    }

函数递归

即函数自己调用自己,但必须有结束的条件(否则栈会溢出)

1
2
3
4
5
6
7
8
9
10
11
static void PrintNumber(int a)
{
if (a > 10)
{
return;
}
Console.WriteLine(a);
PrintNumber(a + 1);
}

PrintNumber(1); // 1 2 3 4 5 6 7 8 9 10

练习:

  1. 传入一个值,递归求该值的阶乘 并返回

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    static int Factorial(int a)
    {
    if (a == 0)
    {
    return 1;
    }
    else
    {
    return Factorial(a - 1) * a;
    }
    }

    Console.WriteLine(Factorial(5));
  2. 递归求 1!+2!+3!+ …… +10!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    static int Factorial(int a)
    {
    if (a == 0)
    {
    return 1;
    }
    else
    {
    return Factorial(a - 1) * a;
    }
    }

    static int SumFactorial()
    {
    int sum = 0;
    for (int i = 1; i <= 10; i++)
    {
    int temp = Factorial(i);
    Console.WriteLine("{0}的阶乘是{1}", i, temp);
    sum += temp;
    }

    return sum;
    }

    Console.WriteLine(SumFactorial()); //4037913
  3. 一个竹竿长100米,每天砍掉一半,求第十天它的长度是多少(从第0天开始)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    static void Function(float length, int day = 0)
    {
    Console.WriteLine("第{0}天竹子的长度是{1}", day, length);
    if (day == 10)
    {

    return;
    }
    Function(length /= 2, ++day);
    }

    Function(100);
    /*
    第0天竹子的长度是100
    第1天竹子的长度是50
    第2天竹子的长度是25
    第3天竹子的长度是12.5
    第4天竹子的长度是6.25
    第5天竹子的长度是3.125
    第6天竹子的长度是1.5625
    第7天竹子的长度是0.78125
    第8天竹子的长度是0.390625
    第9天竹子的长度是0.1953125
    第10天竹子的长度是0.09765625
    */
  4. 不允许使用循环语句,条件语句,在控制台打印出1-200这200个数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    static void PrintNumber(int a)
    {
    Console.WriteLine(a);
    }

    static bool Function(int a = 1)
    {
    PrintNumber(a);
    return a >= 200 ? false : Function(++a);
    }

    Function();

结构体

是数据和函数的集合

a.位置:namespace

b.语法:

1
2
3
4
5
6
7
8
9
10
namespace Progress
{
struct 名字
{
// 变量1
// 变量2
// 函数1
// 函数2
}
}

c.规则:

  • 不能在内部使用自己,可以使用自己内部的变量,变量可以有初始值

  • 在内部的函数无需添加static

  • publicprivae分别修饰公有和私有,默认是private

  • 构造函数(用于初始化)

    没有返回值,函数的名字和结构体名相同,必须有传入参数,传入的参数必须被使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    struct Person
    {
    // 初始化方式一
    // 构造函数
    public Person(string name, int age, bool sex)
    {
    this.name = name;
    this.age = age;
    this.sex = sex;
    }
    // 公有 外部可使用
    public string name;
    // 私有 外部不可使用
    private int age;
    // 默认为私有
    bool sex;
    public void sayHello()
    {
    Console.WriteLine($"Hello My name is {name}");
    }

    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 初始化方式二
    struct Person(string name, int age, bool sex)
    {
    // 公有 外部可使用
    public string name = name;
    // 私有 外部不可使用
    private int age = age;
    // 默认为私有
    bool sex = sex;
    public void sayHello()
    {
    Console.WriteLine($"Hello My name is {name}");
    }

    };

d.使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
namespace Progress
{
struct Person
{
// 构造函数 所有的传入值都必须赋值
public Person(string name, int age, bool sex)
{
this.name = name;
this.age = age;
this.sex = sex;
}
// 公有 外部可使用
public string name;
//私有 外部不可使用
private int age;
// 默认为私有
bool sex;
public void sayHello()
{
Console.WriteLine($"Hello My name is {name}");
Console.WriteLine($"Hello My age is {age}");
Console.WriteLine("Hello My sex is {0}", sex ? "man" : "woman");
}

};

class Progress
{
static void Main()
{
Person p = new Person(
name: "gcnanmu",
age: 16,
sex: false
);

Console.WriteLine(p.name);
p.sayHello();
/*
gcnanmu
Hello My name is gcnanmu
Hello My age is 16
Hello My sex is woman
*/
}
}
}

e.练习

  1. 使用结构体描述学员信息,姓名,性别,年龄,班级,专业,创建两个学院对象,并对基础信息进行初始化并打印

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    namespace Progress
    {
    enum Classes
    {
    One,
    Two,
    Three
    }

    enum Profession
    {
    ComputerScience,
    Software,
    IntelligentScience
    }
    struct Student
    {

    public Student(string name, int age, bool gender, Profession prof, Classes cla)
    {
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.prof = prof;
    this.cla = cla;
    }
    string name;
    int age;
    bool gender;

    Profession prof;
    Classes cla;

    public void sayInfo()
    {
    Console.WriteLine(
    "name: {0}, age: {1} gender: {2}, prof: {3}, cla: {4}",
    name,
    age,
    gender ? "man" : "woman",
    prof,
    cla
    );
    }
    }

    class Progress
    {
    static void Main()
    {
    Student s1 = new Student(
    name: "zhangsan",
    age: 18,
    gender: true,
    prof: Profession.IntelligentScience,
    cla: Classes.One
    );

    Student s2 = new Student(
    name: "lisi",
    age: 20,
    gender: false,
    prof: Profession.Software,
    cla: Classes.Three
    );

    s1.sayInfo();
    s2.sayInfo();
    }
    }
    }
  2. 使用结构体描述矩形的信息,长和宽;创建一个矩形,对其长度进行初始化,并打印矩形的长、宽、面积、周长等信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    namespace Progress
    {
    struct Renctangle
    {
    public double length;
    public double width;

    public double GetArea()
    {
    return length * width;
    }

    public double GetPerimeter()
    {
    return 2 * (length + width);
    }
    }

    class Progress
    {
    static void Main()
    {
    Renctangle renctangle;
    renctangle.length = 10;
    renctangle.width = 20;

    double area = renctangle.GetArea();
    double perimeter = renctangle.GetPerimeter();

    Console.WriteLine("Area: {0}", area);
    Console.WriteLine("Perimeter: {0}", perimeter);
    }
    }
    }
  3. 使用结构体描述玩家信息,玩家名字,玩家职业

    请玩家输入姓名,选择玩家职业,最后打印玩家的攻击信息

    职业:

    • 战士(技能:冲锋)
    • 猎人(技能:假死)
    • 法师(技能:奥数冲击)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    namespace Progress
    {
    enum Profession
    {
    // 战士
    Warrior,
    // 法师
    Mage,
    // 猎人
    Hunter,
    }

    struct Player
    {
    public Player(string name, Profession prof)
    {
    this.name = name;
    this.prof = prof;

    }
    string name;
    Profession prof;

    public void Show()
    {
    Console.WriteLine("name: {0}, profession: {1}", name, prof);
    }
    }

    class Progress
    {
    static void Main()
    {
    Console.WriteLine("请输入玩家姓名:");
    string name = Console.ReadLine();
    Console.WriteLine("请选择职业:0.战士 1.法师 2.猎人");
    int choice = int.Parse(Console.ReadLine());
    Profession prof = (Profession)choice;

    Player player = new Player(name, prof);
    player.Show();
    }
    }
    }
  4. 用结构体描述小怪兽,定义一个数组存储10个小怪兽,每个小怪兽的名字为(小怪兽+数组下标)

    举例:小怪兽0,最后打印10个小怪兽的名字和攻击力数值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    namespace Progress
    {

    struct Monster
    {
    public Monster(string name, int attack)
    {
    this.name = name;
    this.attack = attack;
    }
    public string name;
    public int attack;
    }

    class Progress
    {
    static void Main()
    {
    Random random = new Random();
    for (int i = 0; i < 10; i++)
    {
    int attack = random.Next(1, 101);
    Monster monster = new Monster($"Monster{i}", attack);
    Console.WriteLine($"Monster {monster.name} has {monster.attack} attack");
    }
    }
    }
    }
  5. 实现奥特曼打小怪兽

    定义一个方法实现奥特曼攻击小怪兽

    定义一个方法实现小怪兽攻击奥特曼

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    namespace Progress
    {
    // 新的构造方法
    struct Monster(string name, int attack, int hp)
    {
    public string name = name;
    public int attack = attack;

    public int hp = hp;

    public void Show()
    {
    Console.WriteLine("Monster: " + name + " hp: " + hp);
    }

    public void Attack(ref Altman altman)
    {
    altman.hp -= attack;
    }
    }

    struct Altman(string name, int attack, int hp)
    {
    public string name = name;
    public int attack = attack;
    public int hp = hp;

    public void Show()
    {
    Console.WriteLine("Monster: " + name + " hp: " + hp);
    }

    public void Attack(ref Monster monster)
    {
    monster.hp -= attack;
    }
    }

    class Progress
    {
    static void Main()
    {
    Monster monster = new Monster("Goblin", 10, 100);
    Altman altman = new Altman("Altman", 100, 200);

    monster.Show();
    altman.Show();

    monster.Attack(ref altman);
    altman.Attack(ref monster);

    Console.WriteLine("-----After Attack-----");

    monster.Show();
    altman.Show();
    }
    }
    }
    /*
    Monster: Goblin hp: 100
    Monster: Altman hp: 200
    -----After Attack-----
    Monster: Goblin hp: 0
    Monster: Altman hp: 190
    */

排序初探

将乱序的序列按照递增或者递减调整为有序的序列

冒泡排序

详见冒泡排序 - Hello 算法

img

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static void Exchange(ref int num1, ref int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}

static void BubbleSort(ref int[] arr)
{
for (int i = arr.Length - 1; i >= 0; i--)
{
for (int j = 0; j < i; j++)
{
if (arr[j + 1] < arr[j])
{
Exchange(ref arr[j + 1], ref arr[j]);
}
}
}
}

static void PrintArray(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i]);
}
Console.WriteLine();
}

int[] arr = [4, 1, 3, 1, 2, 5];
PrintArray(arr); // 413125
BubbleSort(ref arr);
PrintArray(arr); // 112345

插入排序

详见插入排序 - Hello 算法

img

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
static void InsertSort(ref int[] arr)
{
int i, j;
for (i = 2; i < arr.Length; i++)
{
int temp = arr[i];
for (j = i - 1; j > 0; --j)
{
if (arr[j] <= temp)
{
break;
}
}

for (int k = i; k >= j + 1; k--)
{
arr[k] = arr[k - 1];
}
arr[j + 1] = temp;
// PrintArray(arr);
}
}

static void PrintArray(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i]);
}
Console.WriteLine();
}

// 默认从1开始
int[] arr = [0, 4, 1, 3, 1, 2, 5];
PrintArray(arr);
InsertSort(ref arr);
PrintArray(arr);

参考文献

  1. 【唐老狮】Unity系列之C#四部曲—C#基础
  2. 冒泡排序 - Hello 算法
  3. 插入排序 - Hello 算法