首页 > 其他分享 >C语言学习8

C语言学习8

时间:2024-11-07 19:20:21浏览次数:3  
标签:rand int time C语言 学习 随机数 printf include

最近学的不是很多,只能更几个C语言小游戏给大家看看。

一.猜数字游戏(难)

1.随机数的生成

  • 要想完成猜数字游戏,⾸先得产⽣随机数,那怎么产⽣随机数呢?
2.rand
  • C语⾔提供了⼀个函数叫 rand,这函数是可以⽣成随机数的,函数原型如下所⽰:
int rand(void);
  • rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的⼤⼩是依赖编译器上实现的,但是⼤部分编译器上是32767。
  • rand函数的使⽤需要包含⼀个头⽂件是:<stdlib.h>
那我们就测试⼀下rand函数,这⾥多调⽤⼏次,产⽣5个随机数:
#include <stdio.h>
int main()
{
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	return 0;
}
  • 我们先运⾏⼀次,看看结果,再运⾏⼀次再看看结果,多运⾏⼏次呢?
第一次运行:

第二次运行:

  • 想必大家看到这里就已经有了疑问,为什么两次随机产生的结果完全一样呢?接下来就来解释这一现象:
  • 我们可以看到虽然⼀次运⾏中产⽣的5个数字是相对随机的,但是下⼀次运⾏程序⽣成的结果和上⼀次⼀模⼀样,这就说明有点问题。
  • 如果再深⼊了解⼀下,我们就不难发现,其实 rand 函数⽣成的随机数是伪随机的,伪随机数不是真正的随机数,是通过某种算法⽣成的随机数。真正的随机数的是⽆法预测下⼀个值是多少的。⽽ rand 函数是对⼀个叫“种⼦”的基准值进⾏运算⽣成的随机数。
  • 之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的,那是因为rand函数⽣成随机数的默认种⼦是1
  • 为了测试一下是不是1,可以稍稍将代码加个数字看看。
#include <stdio.h>
int main()
{
	printf("%d\n", rand(1));
	printf("%d\n", rand(1));
	printf("%d\n", rand(1));
	printf("%d\n", rand(1));
	printf("%d\n", rand(1));
	return 0;
}

运行结果:

  • 由此可见,上述伪随机数确实是种子为1时候的默认值。
  • 如果要⽣成不同的随机数,就要让种⼦是变化的

3.srand

  • C语⾔中⼜提供了⼀个函数叫 srand,⽤来初始化随机数的⽣成器的,srand的原型如下:
void srand (unsigned int seed);
  • 程序中在调⽤ rand 函数之前先调⽤ srand 函数,通过 srand 函数的参数seed来设置rand函数⽣成随机数的时候的种⼦,只要种⼦在变化,每次⽣成的随机数序列也就变化起来了。
  • 那也就是说给srand的种⼦是如果是随机的,rand就能⽣成随机数;在⽣成随机数的时候⼜需要⼀个随机数,这就⽭盾了。

4.time

  • 在程序中我们⼀般是使⽤程序运⾏的时间作为种⼦的,因为时间时刻在发⽣变化的。
  • 在C语⾔中有⼀个函数叫 time ,就可以获得这个时间,time函数原型如下:
time_t time (time_t* timer);
  • time 函数会返回当前的⽇历时间,其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运⾏时间之间的差值,单位是秒。返回的类型是time_t类型的,time_t 类型本质上其实就是32位或者64位的整型类型。
  • time函数的参数 timer 如果是⾮NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
  • 如果 timer 是 NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。
  • time函数的时候需要包含头⽂件:<time.h>
//VS2022 上time_t类型的说明
#ifndef _CRT_NO_TIME_T
#ifdef _USE_32BIT_TIME_T
typedef __time32_t time_t;
#else
typedef __time64_t time_t;
#endif
#endif
typedef long __time32_t;
typedef __int64 __time64_t;
  • 这个看不懂也没啥问题哈(拷贝的时候格式有亿点丑陋),反之意思就是time_t函数类型是32位或者64位的整数类型。

补充:顺便看一下时间戳是什么东西,在网上直接搜时间戳就会有时间戳工具弹出来了(下面那个红圈标注的地方,如果不暂停,就一直以秒为单位上涨。)

  • 回归正题哈,如果只是让time函数返回时间戳,我们就可以这样写:
tima(NULL);  //调用time函数返回时间戳
  • 那我们就可以让⽣成随机数的代码改写成如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
	srand((unsigned int) time (NULL));
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	return 0;
}
打印结果1: 打印结果2:
  • 这么看来是不是两次运行的结果就不一样了。
  • srand函数是不需要频繁调⽤的,⼀次运⾏的程序中调⽤⼀次就够了。

5.设计随机数的范围

  • 如果我们要⽣成0~99之间的随机数,⽅法如下:
rand() % 100; //随机数的范围是0~99
  • 如果要⽣成1~100之间的随机数,⽅法如下:
rand() % 100 + 1;
  • 如果要⽣成100~200的随机数,⽅法如下:
100 + rand() % (200 - 100 + 1);
  • 所以如果要⽣成a~b的随机数,⽅法如下:
a + rand() % (b - a + 1);

6.代码实现

//  1.打印游戏菜单,选择1进行游戏,选择0结束游戏。
//  2.随机生成1~100的数字
//  3.游戏内容的实现:猜数字,比大小。猜的大了,告诉你什么情况。猜的小了,告诉你什么情况。


#include <stdio.h>
#include <stdlib.h>
#include <time.h> 

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

void game()
{
	int guess = 0;
	int r = rand() % 100 + 1;
	while (1)
	{
		printf("请输入数字:");
		scanf("%d", &guess);
		if (guess > r)
		{
			printf("猜大了\n");
		}
		else if (guess < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
		}
	}
}

int main()
{
	int input;
	srand((unsigned int)time(NULL));
	do
	{
		menu();     //调用menu函数
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();      //调用game函数
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}
  • 还可以加上猜数字的次数限制,如果5次猜不出来,就算失败:
#include <stdio.h>
#include <stdlib.h>
#include <time.h> 

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

void game()
{
	int guess = 0;
	int count = 5;
	int r = rand() % 100 + 1;
	while (count)
	{
		printf("你还有%d次机会\n", count);
		printf("请输入数字:");
		scanf("%d", &guess);
		if (guess > r)
		{
			printf("猜大了\n");
		}
		else if (guess < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
		}
		count--;
	}
	if (count == 0)
	{
		printf("你失败了,正确答案是%d\n", r);
	}
}

int main()
{
	int input;
	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);
	return 0;
}

打印结果:

二.多个字符向中间移动(中)

编写代码,演⽰多个字符从两端移动,向中间汇聚:
#include <stdio.h>
int main()
{
	char arr1[] = { "hello bei bei tan" };
	char arr2[] = { "*****************" };
	int left = 0;
	int right = sizeof(arr1) / sizeof(arr1[0]) - 2; //求总字符数
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		left++;
		right--;
		printf("%s\n", arr2);
	}
}

打印结果:

也可以这么写,实现代码的动态变化:
#include <stdio.h>
#include <windows.h>

int main()
{
	char arr1[] = { "hello bei bei tan" };
	char arr2[] = { "*****************" };
	int left = 0;
	int right = sizeof(arr1) / sizeof(arr1[0]) - 2;
	//是从下标0开始,含有\0先-1,从下标0开始再-1
	//int right = strlen(arr1) - 1;  //strlen 求的是\0之前的字符总数,所以要-1。
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		Sleep(1000);
		left++;
		right--;
		printf("%s\n", arr2);
	}
	return 0;
}

三.二分查找(中)

在⼀个升序的数组中查找指定的数字n,很容易想到的⽅法就是遍历数组,但是这种⽅法效率⽐较低。 ⽐如我买了⼀双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜?你会1,2,3,4...这样猜吗?显然很慢;⼀般你都会猜中间数字,⽐如:150,然后看⼤了还是⼩了,这就是⼆分查找,也叫折半查找前提:有序数组
#include <stdio.h>
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12};
	int input = 0;
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]) - 1;  //用的是下标,所以要-1
	int mid = 0;  //定义中值
	int find = 0;
	printf("请输入:");
	scanf("%d", &input);
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (arr[mid] < input)
		{
			left = mid + 1;
		}
		else if (arr[mid] > input)
		{
			right = mid - 1;
		}
		else
		{
			find = 1;
			break;
		}
	}
	if (find == 1)
	{
		printf("找到了,下标为%d\n", mid);
	}
	else
	{
		printf("找不到了\n");
	}
	return 0;
}
求中间元素的下标,使⽤ mid = (left+right)/2 ,如果left和right⽐较⼤的时候可能存在问 题,可以使⽤下⾯的⽅式:
mid = left + (right - left) / 2;  
四.海伦公式(易)
#define _CRT_SECURE_NO_WARNINGS
计算三角形面积
#include <stdio.h>
#include <math.h>

int main()
{
	double a, b, c, p, area;
	printf("请输入三边边长:\n");
	scanf("%lf%lf%lf", &a, &b, &c);
	p = (a + b + c) / 2.0;
	if (a + b > c && a + c > b && b + c > a)
	{
		printf("是三角形\n");
		area = sqrt(p * (p - a) * (p - b) * (p - c));
		printf("%.2f\n", area);
	}
	else
	{
		printf("不是三角形,请重新输入\n");
	}
	return 0;
}

先判断三角形,如果是三角形再将数学式的海伦公式转换为计算机语言就行了。

标签:rand,int,time,C语言,学习,随机数,printf,include
From: https://blog.csdn.net/2401_87671334/article/details/143568727

相关文章

  • C语言逻辑操作符
    C语言逻辑操作符在C语言中,逻辑操作符用于执行逻辑运算,它们通常用于控制流语句中,如if和while循环,以根据给定的条件逻辑来决定程序的执行路径。C语言提供了三种逻辑操作符: 1.逻辑与(&&):当两个操作数都为真(非零)时,结果为真;否则结果为假。 2.逻辑或(||):当两个操作数中......
  • C# SqlSugar学习笔记
    前言今天介绍一款C#ORM框架什么是ORM?来看一下百度术语:对象关系映射(英语:ObjectRelationalMapping,简称ORM,或O/RM,或O/Rmapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 通俗理解ORM我们只需要知道ORM是一种技术,使用了ORM之后我们就不必在......
  • React学习笔记(六) Create React App
    React学习笔记(六)CreateReactApp 1、介绍CreateReactApp是官方支持的创建单页应用程序的方法,可以帮助我们快速搭建一个繁杂的脚手架我们可以直接使用命令 npminstallcreate-react-app-g 全局安装CreateReactApp然后使用命令 create-react-app<project-na......
  • 高性能的Reactor和Proactor模式学习
    0、引言在上一篇的笔记中,我们学习了操作系统提供的高效I/O管理技术,主要用于解决服务器在高并发场景下的资源浪费和瓶颈问题。但是在实际的代码编写中,要是我们都全部调用底层的I/O多路复用接口来编写网络程序这种面向过程的方式,必然会导致开发的效率不高。于是在这一章节,我们来学......
  • 用C语言代码输出三个数
    题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?已知:1、三位数2、1-43、各不相同输出:1、有多少个这样的三位数2、依次输出#include<stdio.h>intmain(){for(intb=1;b<5;b++)  {   for(ints=1;s<5;s++)    ......
  • GPU释放威力:在Gymnasium环境中使用稳定基线3在AMD GPU上训练强化学习代理
    GPUUnleashed:TrainingReinforcementLearningAgentswithStableBaselines3onanAMDGPUinGymnasiumEnvironment—ROCmBlogs2024年4月11日作者: DouglasJia.本博客将深入探讨深度强化学习的基本原理,通过一个实用的代码示例,指导您如何利用AMDGPU在Gymnasium......
  • React系统学习之路
    React系统学习之路学习目录第1章:React入门介绍React的基本概念和应用场景安装Node.js和npm创建第一个React应用React的JSX语法组件的基本结构和生命周期第2章:组件与状态管理函数组件与类组件的区别状态(State)和属性(Props)的使用受控组件与非受控组件高阶组件(HOC)的概念和......
  • 插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序
    #include<stdio.h>#include<stdlib.h>//插入排序voidInsertSort(intA[],intn){inti,j,temp;for(i=1;i<n;i++){temp=A[i];j=i-1;while(j>=0&&A[j]>temp){A......
  • 机器学习系列----介绍前馈神经网络和卷积神经网络 (CNN)
    前言 在深度学习领域,神经网络是一种模拟人脑神经元结构和功能的数学模型。它通过大量的层次结构和参数调整来实现模式识别、分类、回归等任务。常见的神经网络结构有前馈神经网络(FeedforwardNeuralNetworks,简称FNN)和卷积神经网络(ConvolutionalNeuralNetworks,简称CNN)......
  • 数据结构学习
    computer数据结构第一章算法一个有限指令集接受一些输入产生输出一定要在有限的步骤之后终止每一条指令必须有明确色目标,不可以有歧义,计算机能处理的范围之内,不依赖任何语言和描述。什么是好算法时间复杂度空间复杂度复杂度的渐进表示法输入规模n每十亿`......