系统学习之C复习(4)数组-创新互联

一:一维数组的创建和初始化

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

我们提供的服务有:成都网站设计、成都网站制作、微信公众号开发、网站优化、网站认证、息烽ssl等。为超过千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的息烽网站制作公司

int n  = 10;

int arr[n] = {0};

但是 n 不可以变化

C99中引入了变长数组的概念,允许数组的大小用变量指定。

如果编译器不支持的C99中的变长数组,则不能使用

数组的初始化:在创建的时候赋值 

不完全初始化:不赋值完,后续默认0;

  int arr[] = {1,2,3,4} 不赋数组大小,系统默认分配。

  int arr[10];        数组不赋值系统分配随机值。

二:一维数组的使用 三:一维数组在内存中的存储

打印数组中每个元素中的地址——%p   (16进制)

#include#includeint main()
{
    char arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    int sz = sizeof(arr1) / sizeof(arr1[0]);    //计算数组元素个数。
    for (i = 0; i< sz; i++)
    {
        printf("&arr1[%d] = %p\n", i, &arr1[i]);
    }
    return 0;
}

一组数组在内存是连续的。随着数组下标的增加,地址由低到高。

用指针访问数组

#include#includeint main()
{
    char arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    int sz = sizeof(arr1) / sizeof(arr1[0]);    //计算数组元素个数。

    char* p = &arr1[0];

    for (i = 0; i< sz; i++)
    {
        printf("&arr1[%d] = %p<=====>%p\n", i, &arr1[i],p+i);
    }
    return 0;
}
四:二维数组的创建和初始化

int arr[3][5];  //三行五列

int arr[3][5] = {{1,2},{3,4},{5,6}};        // 一个{}一行

可以省略行,不可以省略 列

  int arr[][5] = {1,2,3,4,5,6,7};        //此时只有两行,系统自动发配行

  int  arr[][5] = {{1,2},{3,4},{5,6}};   //此时三行

五:二维数组的使用

二维数组的访问:

int main()
{
	//int arr[3][5] = {1,2,3,4,5,6,7};	//三行五列
	int arr[][5] = { {1,2},{3,4},{5,6} };
	int i = 0;
    //for (i = 0; i< sizeof(arr) / arr[0]; i++)//0 1 2 
	for (i = 0; i< 3; i++)//0 1 2  行
	{
		int j = 0;
		for (j = 0; j< 5; j++)     //列
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}
六:二维数组在内存中的存储

和一维数组一样。连续的。 第一列的最后一位与第二列的第一位相连。

七:数组越界

请程序员本身注意。

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    for(i=0;i<=10;i++)    //此处越界,c语言本身不检查。
    {
        printf("%d ",arr[i]);
    }
    return  0;
}
八:数组作为函数参数 冒泡排序的错误方式

冒泡排序

数字中2个相邻的元素进行比较,如果不满足顺序则交换。

距离

若: 9 8 7 6 5 4 3 2 1        排序为升序

第一次:                        第二次:

8 9 7 6 5 4 3 2 1 0                 7 8 6 5 4 3 2 1 0 9

8 7 9 6 5 4 3 2 1 0                 7 6 8 5 4 3 2 1 0 9

8 7 6 9 5 4 3 2 1 0                 ……

……

8 7 6 5 4 3 2 1 0 9

一趟冒泡排序搞定一个

int bubble_sort(int* arr)
{
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i< sz; 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);
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i< sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}
//此时 输出依旧依旧是9 8 7 6 5 4 3 2 1 0

经过调试,我们发现sz = 1;

首先,数组名是什么?

printf("%p\n",arr);

printf("%p\n",&arr[0]);
//这两者输出一致

数组名就是数组的首元素的地址;

  有2个例外:

  &数组名 与 sizeof(数组名),此时数组名不是数组首元素的地址,是代表整个数组

  

arr 与 &arr[0] 都是数组首元素地址,  &arr是数组地址。 

所以,函数中的 sz 计算的1;

修改:将sz的计算放到函数外计算,作为参数传进去。

int bubble_sort(int* arr, int sz)
{
	int i = 0;
	//int sz = sizeof(arr) / sizeof(arr[0]);
	//因为传进来的是数组首元素地址,所以 sz = 1;
	//将此计算大小移出计算,作为参数传进来。
	for (i = 0; i< sz; 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 sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i< sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

三子棋

先 确定框架,

再 测试基本逻辑是否运行 

最后编写game内容

首先 基本框架与逻辑 

#define _CRT_SECURE_NO_WARNINGS 1
#include#include "game.h"

void menu()
{
	printf("***************\n");
	printf("**按1开始游戏**\n");
	printf("**按0结束游戏**\n");
	printf("***************\n");
}

void game()
{
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏");
			break;
		default:
			printf("请选择1or0\n");
			break;
		}
	} while (input);
	return  0;
}

然后 新建一个 game.h和game.c文件,进行模块化

游戏的内容都在game.c里面写,主函数调用即可。

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void InitBoard(char board[ROW][COL], int row, int col)//row  行 col 列
{
	int i = 0;
	for (i = 0; i< row; i++)
	{
		int j = 0;
		for (j = 0; j< col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

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

//这段代码的效果限制了 列的生成,倘若生成 10*10,那么依旧只显示3列。 为此,修改成如下

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

棋盘构成了。随后棋手入场。

电脑和玩家 各自下棋。

电脑和玩家 各自下棋。

void game()
{
	//存放下棋的数据
	char board[ROW][COL] = { 0 };
	//初始化棋盘为全空额
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//电脑下棋
		conputer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
	}
}
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家下棋\n");
		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;		//记得brak退出 前面在死循环
			}
			else
			{
				printf("该坐标已被占用,请重新输入\n");
			}
		}
		else
			printf("非法坐标,请重新输入\n");
	}
}
//电脑下棋
void conputer_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	//使用rand()生成随机数前需要调用
	//srand((unsigned int)time(NULL));	#include#includeprintf("电脑下棋\n");
	while (1)
	{
		x = rand() % row;	//0~ROW-1	
		y = rand() % col;	//0~COL-1
		//落子的地方需要就判断是否有子
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

选手下完棋子后,需要判断游戏状态 。

死种游戏状态:        令:

玩家赢        —— 返回 ' * '

电脑赢        —— 返回 ' # '

平局            —— 返回 ' Q ' 

继续            —— 返回 ' C '

每一次 落子后就需要判断。

char ret = 0;
	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢 
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		//电脑下棋
		conputer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢 
		ret = is_win(board, ROW, COL);
		if(ret != 'C')
		{
			break;
		}
	}
	if ('*' == ret)
	{
		printf("玩家赢了\n");
	}
	else if ('#' == ret)
	{
		printf("你给电脑赢了??\n");
	}
	else if('Q' == ret)
	{
		printf("平局\n");
	}

判断 横、竖 、对角线 ,棋盘满子  等四种情况

char is_win(char board[ROW][COL], int row, int col)
{
	// 判断横竖三,对角线是否三个相同的
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 0; i< row; i++)//判断ROW行
	{
		for (j = 1; j< col; j++)
		{
			if (board[i][j] == board[i][j - 1]  && board[i][j] != ' ')
			{
				count++;
			}
			if (count == GAME_COUNT - 1)
			{
				return board[i][j];
			}
		}
		count = 0;
	}
	for (j = 0; j< col; j++)//判断COL列
	{
		for (i = 1; i< row; i++)
		{
			if (board[i][j] == board[i-1][j] && board[i][j] != ' ')
			{
				count++;
			}
			if (count == GAME_COUNT - 1)
			{
				return board[i][j];
			}
		}
		count = 0;
	}

	for (i = 1, j = 1; i<= row || j<= col; i++, j++)	//判断对角线
	{
		if (board[i][j] == board[i - 1][j - 1] && board[i][j] != ' ')
		{
			count++;
		}
		if (count == GAME_COUNT - 1)
		{
			return board[i][j];
		}
		count = 0;
	}
	if (FULL == is_full(board, ROW, COL))//判断平局
	{
		return 'Q';	
	}
	return 'C';
}
//检测是否棋盘满子
int is_full(char board[ROW][COL],int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i< row; i++)//判断ROW行
    {
        for (j = 0; j< col; j++)
        {
            if (board[i][j] == ' ')
            {
                return 0;
            }
        }
    }
    return 1;
}

用count++计数,   当有一次相同时,count 计数+1,

每一行或者每一列 检测完毕的时候count清零。为下一行重新检测

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻标题:系统学习之C复习(4)数组-创新互联
新闻来源:http://myzitong.com/article/didjej.html