猜数字游戏:
1.电脑会随机产生一个数
2.猜数字
a>猜大了,提醒猜大了,继续猜
b>猜小了,提醒猜小了,继续猜
c>猜对了,恭喜你,猜对了,游戏结束
3.玩完之后可以继续玩,不想退出程序
首先我们要完成这个游戏,就必须要生成一个随机数,接下来看看生成随机数的函数
rand()函数,生成一个伪随机数,参数是void,返回值是int类型,使用时需要引用头文件
#include
#include
int main()
{
int i = 0;
for(i=0;i<3;i++)
{
int randomNumber = rand();
printf("%d\n", randomNumber);
}
return 0;
}
我将该程序运行了三次,发现生成的随机数一样,为什么呢?
此时我们就要注意上面加粗的字体——伪随机数
rand函数生成的随机数序列是伪随机数序列,而不是真正的随机数序列,因此每次生成的随机数序列都是相同的。这是因为rand函数使用的是一种叫做线性同余算法的伪随机数生成方式,它是基于计算机的固有特性(如时钟周期、操作系统的种子等)生成的,因此每次运行程序所生成的随机数序列都是相同的。
为了避免生成的随机数序列每次都相同,可以使用srand函数来初始化随机数种子,从而改变生成的随机数序列,接下来我们来看看srand函数。
srand函数,设置一个随机的起始点,参数是无符号整型(unsigned int),无返回值,使用时需要引用头文件
其原型时是:
void srand(unsigned int seed);
在使用rand函数生成随机数之前,需要先调用srand函数来设置随机数种子,以确保每次运行程序生成的随机数序列都是不同的。
当我们使用函数srand分别传入1,2,3就可以显示不同的随机数了
但是我们生成随机数希望可以自己变化,而不是我们手动去设置它才能变化,因此我们要设置一个随机种子,但是我们原来就是想生成一个随机数,现在又要生成一个随机种子,那这样不是矛盾了吗?其实不然,我们发现时间每时每刻都在变化,所以我们可以用时间戳来设置这个随机种子,这是我们首先就需要了解时间戳的概念。
时间戳(Timestamp)是指某个特定时间点所对应的数字,通常是一个整数。在计算机中,时间戳通常是指自某个特定时间开始(例如:1970年1月1日0点0分0秒)到当前时刻所经过的秒数(称为Unix时间戳),也可以是毫秒数、微秒数等其他时间单位。 时间戳通常用于记录和表示某个事件发生的时间,它不受时区的影响,因此具有很高的精度和通用性。在编程中,常常会用时间戳来对不同的事件进行排序、计算时间差、生成随机数种子等操作。
所以这时我们就要获取计算机的时刻,就要用到time函数。
time函数是C语言标准库中用于获取当前系统时间的函数,
其原型为:
time_t time(time_t *tloc);
time函数返回当前的系统时间,并以time_t类型的值表示(time_t是C语言标准库中用于表示时间的数据类型)。如果参数不为NULL,则time函数也会将当前时间存储到该指针指向的变量中。 time函数返回的时间表示自1970年1月1日0时0分0秒起至当前时间所经过的秒数,因此也被称为Unix时间戳。time函数可以用于获取当前系统时间,计算时间差,确定随机数种子等操作。
这里注意一个小细节,由于srand()函数的参数是(无符号整型)unsigned int,time函数的返回值是time_t,所以我们需要将time函数的返回值进行强制类型转换:
srand((unsigned int)time(NULL));
这时我们发现,使用时间戳作为随机种子后,我们生成的随机数就都不一样了。
为了使游戏的难度降低,我们想要生成1-100之间的数,我们就需要使用下面的方法就可以生成啦
rand()%100+1;
接下来,我们来看完整的猜数字游戏的代码
//猜数字游戏
#include
#include
#include
void menu()
{
printf("****************************\n");
printf("******1.paly 0.exit******\n");
printf("****************************\n");
}
void game()
{
//1.生产随机数
//srand((unsigned int)time(NULL));//要给srand传递一个变化的值,\
计算机上的时间是时刻发生变化的
//srand( unsigned int seed )
//time函数可以返回一个时间戳 - time_t
//rand();//生产随机数,随机数范围0-32767
int ret = rand() % 100 + 1;//生产随机数,随机数范围1-100
//printf("%d", ret);
//2.猜数字
int guess = 0;
while(1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess > ret)
{
printf("猜大了\n");
}
else if (guess < ret)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
//打印菜单
//1.玩游戏
//2.退出游戏
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("猜数字游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
想体验的小伙伴,可以亲自去尝试一下哟。
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号,但是只能在当前函数内跳转,不能跨越多个函数进行跳转。
goto语句是一条跳转语句,可用于将程序的执行从一段代码直接跳转到其他代码的特定位置。它可以在程序的任何地方使用,但过度使用goto语句可能导致代码难以理解和维护。 在使用goto语句时,需要定义一个标签,用于标示跳转的目标位置。例如,如果有一段代码需要重复执行多次,可以在代码块的开头定义一个标签,并在代码块的末尾通过goto语句跳转到该标签的位置,从而实现代码块的循环执行。
例如,下面是一个使用goto语句实现循环的示例代码:
#include
int main()
{
int i = 1;
LOOP:
printf("%d ", i);
i++;
if (i <= 10)
goto LOOP;
return 0;
}
在这个示例代码中,我们定义了一个标签LOOP,并使用goto语句在代码块的末尾跳转到该标签的位置。在每次执行该代码块时,程序都会按照顺序执行代码,直到满足if语句的条件时跳转到标签LOOP的位置,然后重新开始执行代码块,实现了代码块的循环执行,直到i的值达到10为止。
过度使用goto语句可能导致代码难以理解和维护,但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过 程。 例如:一次跳出两层或多层循环。 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
for (...)
for (...)
{
for (...)
{
if (disaster)
goto error;
}
}
error :
if (disaster)
// 处理错误情况
1.程序运行起来,将会在一分钟内关机
2.如果输入1,我们就取消关机
这里我们首先介绍一个关机的命令:shutdown
Windows 系统自带一个名为Shutdown.exe的程序,可以用于关机操作(位置在Windows\System32下),一般情况下Windows系统的关机都可以通过调用程序 shutdown.exe来实现的,同时该程序也可以用于终止正在计划中的关机操作。
//关机程序
// 1.程序运行起来,将会在一分钟内关机
// 2.如果输入1,我们就取消关机
#include
#include
int main()
{
int input = 0;
//程序关机倒计时
again:
system("shutdown -s -t 60");
printf("请注意,你的电脑将在1分钟内关机,如果输入1,就会取消关机\n");
scanf("%d", &input);
if (input == 1)
{
system("shutdown -a");
}
else
{
goto again;
}
return 0;
}
system("shutdown -s -t 60");
`system("shutdown -s -t 60")` 是一个 `system()` 函数的调用,它的作用是在调用这个函数的程序中执行一条系统命令。 在这个特定的例子中,系统命令是 `shutdown`,它是 Windows 操作系统的一个命令,可以用来关机、重启、注销等等。 `-s` 选项表示关机,`-t 60` 表示在60秒后关机。 因此,这行代码的意思是让执行这个程序的电脑,在运行程序后的60秒内关机。
system("shutdown -a");
`system("shutdown -a")` 是一个 `system()` 函数的调用,它的作用是在调用这个函数的程序中执行一条系统命令。 在这个特定的例子中,系统命令是 `shutdown`,它是 Windows 操作系统的一个命令,可以用来关机、重启、注销等等。 `-a` 选项表示取消之前已经发出的关机、重启等命令。 因此,这行代码的意思是让执行这个程序的电脑,取消之前已经设定的关机命令。
而如果不适用goto语句,则可以使用循环:
#include
#include
int main()
{
int input[10] = 0;
system("shutdown -s -t 60");
while (1)
{
printf("电脑将在1分钟内关机,如果输入:1,就取消关机!\n请输入:>");
scanf("%d", &input);
if (1 == input)
{
system("shutdown -a");
break;
}
}
return 0;
}
思路:
素数:即质数,除了1和自己之外,再没有其他的约数,则该数据为素数,具体方式如下
//方法一:试除法
int main()
{
int i = 0;
int count = 0;
// 外层循环用来获取100~200之间的所有数据,100肯定不是素数,因此i从101开始
for(i=101; i<=200; i++)
{
//判断i是否为素数:用[2, i)之间的每个数据去被i除,只要有一个可以被整除,则不是素数
int j = 0;
for(j=2; ji-1
int j = 0;
for(j=2; j<=i/2; j++)
{
if(i%j == 0)
{
break;
}
}
//...
if(j>i/2)
{
count++;
printf("%d ", i);
}
}
printf("\ncount = %d\n", count);
return 0;
}
/*
方法二还是包含了一些重复的数据,再优化:
如果i能够被[2, sqrt(i)]之间的任意数据整除,则i不是素数
原因:如果 m 能被 2 ~ m-1 之间任一整数整除,其二个因子必定有一个小于或等于sqrt(m),另一个大于或等于 sqrt(m)。
*/
int main()
{
int i = 0;
int count = 0;
for(i=101; i<=200; i++)
{
//判断i是否为素数
//2->i-1
int j = 0;
for(j=2; j<=sqrt(i); j++)
{
if(i%j == 0)
{
break;
}
}
//...
if(j>sqrt(i))
{
count++;
printf("%d ", i);
}
}
printf("\ncount = %d\n", count);
return 0;
}
//方法4
/*
继续对方法三优化,只要i不被[2, sqrt(i)]之间的任何数据整除,则i是素数,但是实际在操作时i不用从101逐渐递增到200,因为出了2和3之外,不会有两个连续相邻的数据同时为素数
*/
int main()
{
int i = 0;
int count = 0;
for(i=101; i<=200; i+=2)
{
//判断i是否为素数
//2->i-1
int j = 0;
for(j=2; j<=sqrt(i); j++)
{
if(i%j == 0)
{
break;
}
}
//...
if(j>sqrt(i))
{
count++;
printf("%d ", i);
}
}
printf("\ncount = %d\n", count);
return 0;
}