第4章-数组

一、一维数组

1、 一维数组的创建和初始化

数组是一组相同类型元素的集合

(1)数组的创建

//语法形式
type_t   arr_name[const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
#include<stdio.h>
int main()
{
    //创建一个数组
    int arr[10];//存放10个整型
    char arr2[5];

    int count = 10;
    int arr2[count];//数组不可以正常创建,存放的是变量,数组自能存放常量
    
    char arr3[10];
    float arr4[1];
    double arr5[20];

    return 0;
}

注:数组创建,[ ]中要给一个常量才可以,不能使用变量。

(2)数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)

#include<stdio.h>
#include<string.h>
int main()
{
    int arr1[10] = {1,2,3};
    //不完全初始化,初始化前三位,剩下元素默认初始化为0
    char ch2[5] = {'a','b'};//字符初始化 ab000
    char ch3[5] = "ab";//a b (无'\0'后为乱码)
    char arr4[] = "abcdef";
    printf("%d\n", sizeof(arr4));//7
    //sizeof计算arr所占空间的大小,单位是字节--操作符
    printf("%d\n", strlen(arr4));//6
    //strlen是求字符串的长度,即'\0'前字符个数--库函数-使用需要头文件
    //sizeof和strlen没有关联
    return 0;
}

2、一维数组的使用

 [ ]--下标引用操作符,数组访问的操作符

数组下标从0开始。

#include<stdio.h>
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
    int sz = sizeof(arr)/sizeof(arr[0]);
    int i = 0;
    for (i=0;i<sz;i++) 
    {
        printf("%d",arr[i]);
    }
    
    return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
    char arr[] = "abcdef";//[a][b][c][d][e][f][\0]
    int i = 0;
    int len = strlen(arr);
    for (i = 0; i <len; i++)
    //for (i = 0; i < 6; i++)
    {
        printf("%c", arr[i]);
    }
    //printf("%c\n", arr[3]);
    return 0;
}

3、一维数组在内存中的存储

数组在内存中是连续存放

随着数组下标的增长,元素的地址由低到高变化,有规律的递增

#include<stdio.h>
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);
    }
    return 0;
}
#include <stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int*p = arr;//数组名是数组首元素的地址
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d ", *p);
        p++;
    }
    return 0;
}

二、二维数组

1、二维数组的创建和初始化

(1)二维数组的创建

#include<stdio.h>
int main()
{
    int arr[3][4];
    //3*4,即3行4列的二维数值
    char arr[5][6];
    return 0;
}

(2)二维数组的初始化

初始化 ,即创建的同时给赋值

#include<stdio.h>
int main()
{
    int arr[3][4] = { 1,2,3,4 };
    //初始化 - 创建的同时给赋值
    int arr[3][4] = { 1,2,3,4,5,6,7};
    //不完全初始化 - 后面补0
    int arr[3][4] = { {1,2},{4,5} };
    //{1,2}放一行,{4,5}放一行
    int arr[][4] = { {2,3},{4,5} };
    //二维数组有初始化,行可以省略,列不能省略
    return 0;
}

2、 二维数组的使用

#include<stdio.h>
int main()
{
    int arr[3][4] = { {1,2,3},{4,5} };
    int i = 0;
    for (i = 0; i <3; i++)
    {
        int j = 0;
        for (j = 0; j < 4; j++)
        {
            printf("%d",arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

3、二维数组在内存中的存储

#include<stdio.h>
int main()
{
    int arr[3][4] = { {1,2,3},{4,5} };
        //存储位置
        //1 2 3 0
        //4 5 0 0
        //0 0 0 0
        //下标
        //   0 1 2 3
        //0 
        //1
        //2
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        int j = 0;
        for (j = 0; j < 4; j++)
        {
            printf("&arr[%d][%d]=%p\n", i, j, &arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

二维数组在内存中也是连续存储的

4. 数组作为函数参数

(1)冒泡排序函数

冒泡排序——升序

两两相邻进行比较,满足条件进行交换

  • 一趟冒泡排序
  • 9 8 7 6 5 4 3 2 1 0
  • 8 9 7 6 5 4 3 2 1 0 
  • 8 7 9 6 5 4 3 2 1 0 
  • ...
  • 8 7 6 5 4 3 2 1 0 9

10个元素9趟冒泡排序

一趟进行9次

//错误思路
#include <stdio.h>
void bubble_sort(int arr[], int sz)//形参arr本质是指针
{
    //计算数组元素个数
    int sz = sizeof(arr) / sizeof(arr[0]);
        //确定趟数
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        //一趟冒泡排序的过程
        int j = 0;
        for (j = 0; j < sz-1-i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                //交换
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
int main()
{
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    bubble_sort(arr, sz);//数组传参的时候,传递的其实是数组首元素的地址
    return 0;
}

修改

#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz - 1; i++) 
    {
        int j = 0;
        for (j = 0; j < sz-1-i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
int main()
{
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    //对arr数值进行传参,传递的数值arr首元素地址,即&arr[]
    bubble_sort(arr,sz);
    for (i = 0; i < sz; i++)
    {
        printf(" %d", arr[i]);
    }
    return 0;
}

(2)优化

#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int flag = 1;
        //假设有序
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
                flag = 0;
                //本趟排序不完全有序
            }
        }
        if (flag == 1)
        {
            break;
        }
    }
}
int main()
{
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, sz);
    for (i = 0; i < sz; i++)
    {
        printf(" %d", arr[i]);
    }
    return 0;
}

(5)数组名

1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组,单位是字节。

2. &数组名,取出的是数组的地址,数组名表示整个数组。

除此1,2两种情况之外,所有的数组名都表示数组首元素的地址。

#include <stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5 };
    printf("%p\n", arr);//打印第一个元素地址
    printf("%p\n", &arr[0]);//首元素地址,下标为0的元素
    printf("%d\n", *arr);//1
    printf("%p\n", &arr);//数组的地址,指整个数组
    return 0;
}

三、数组的应用实例

1. 三子棋

 头文件game.h

#pragma once

//头文件的包含
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//符号的定义
#define ROW 3
#define COL 3

//函数的声明
//初始化棋盘的
void InitBoard(char board[ROW][COL], int row, int col);

//打印棋盘的函数
void DisplayBoard(char board[ROW][COL], int row, int col);

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

//
//1. 玩家赢了 - *
//2. 电脑赢了 - #
//3. 平局 - Q
//4. 游戏继续 - C

//判断游戏是否有输赢
char IsWin(char board[ROW][COL], int row, int col);

 

源文件game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化为空格
void InitBoard(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            board[i][j] = ' ';
        }
    }
}

////通过更改棋盘,行的隔数固定,只能打印3*3
//void DisplayBoard(char board[ROW][COL], int row, int col)
//{
//    int i = 0;
//    for (i = 0; i < row; i++)
//    {
//        printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
//        if(i<row-1)//减少一行分割
//            printf("---|---|---\n");
//    }
//}



void DisplayBoard(char board[ROW][COL], int row, int col)
{
    int i = 0;
    for (i = 0; i < row; i++)
    {
        int j = 0;
        for (j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if(j<col-1)
                printf("|");
        }
        printf("\n");
        if (i < row - 1)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                printf("---");
                if(j<col-1)
                    printf("|");
            }
            printf("\n");
        }
    }
}


void PlayerMove(char board[][COL], int row, int col) 
{
    int x = 0;
    int y = 0;

    printf("玩家走:>\n");

    while (1)
    {
        printf("请输入下棋的坐标:>");
        scanf("%d %d", &x, &y);
        //判断坐标合法性
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //下棋
            //坐标是否被占用
            if (board[x - 1][y - 1] == ' ')
            {
                board[x - 1][y - 1] = '*';
                break;
            }
            else
            {
                printf("坐标被占用, 请重新输入\n");
            }
        }
        else
        {
            printf("坐标非法, 请重新输入\n");
        }
    }
}

void ComputerMove(char board[ROW][COL], int row, int col)
{
    printf("电脑走:>\n");

    while (1)
    {
        int x = rand() % row;
        int y = rand() % col;

        //判断占用
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}


int IsFull(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')
            {
                return 0;//棋盘没满
            }
        }
    }

    return 1;//棋盘满了
}
char IsWin(char board[ROW][COL], int row, int col)
{
    int i = 0;
    //判断三行
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
        {
            return  board[i][1];//
        }
    }
    
    //判断三列
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
        {
            return board[1][i];
        }
    }

    //判断对角线
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
    {
        return board[1][1];
    }
    if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
    {
        return board[1][1];
    }

    //判断平局
    //如果棋盘满了返回1, 不满返回0
    int ret = IsFull(board, row, col);
    if (ret == 1)
    {
        return 'Q';
    }

    //继续
    return 'C';
}

test.c

#define _CRT_SECURE_NO_WARNINGS 
#include "game.h"
void menu()
{
    printf("******************************\n");
    printf("******    1. play        *****\n");
    printf("******    0. exit        *****\n");
    printf("******************************\n");
}

void game()
{
    //存储数据 - 二维数组
    char board[ROW][COL];
    //初始化棋盘 - 初始化空格
    InitBoard(board, ROW, COL);
    //打印一下棋盘 - 本质是打印数组的内容
    DisplayBoard(board, ROW, COL);
    char ret = 0;//接受游戏状态
    while (1)
    {
        //玩家下棋
        PlayerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        //判断玩家是否赢得游戏
        ret = IsWin(board, ROW, COL);
        if (ret != 'C')
            break;
        //电脑下棋
        ComputerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        //判断电脑是否赢得游戏
        ret = IsWin(board, ROW, COL);
        if (ret != 'C')
            break;
    }
    if (ret == '*')
    {
        printf("玩家赢了\n");
    }
    else if(ret == '#')
    {
        printf("电脑赢了\n");
    }
    else
    {
        printf("平局\n");
    }
    DisplayBoard(board, ROW, COL);
}

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误,重新选择\n");
            break;
        }
    } while (input);
    //选择错误选项,跳出do while,跳转到这里,从新进入do while
    return 0;
}

 

2.扫雷游戏

posted @ 2021-11-14 21:56  mljrm  阅读(140)  评论(0)    收藏  举报