C learning_8

简介: C learning_8

猜数字游戏


猜数字游戏:


       1.电脑会随机产生一个数


       2.猜数字


               a>猜大了,提醒猜大了,继续猜

               b>猜小了,提醒猜小了,继续猜

               c>猜对了,恭喜你,猜对了,游戏结束


       3.玩完之后可以继续玩,不想退出程序


首先我们要完成这个游戏,就必须要生成一个随机数,接下来看看生成随机数的函数


rand()函数,生成一个伪随机数,参数是void,返回值是int类型,使用时需要引用头文件<stdlib.h>,它的作用是生成一个范围在0和RAND_MAX之间的随机整数,其中RAND_MAX是一个常量,通常其值是32767。每次调用rand()函数时,将返回一个新的随机数。接下来我们用它来形成三个随机函数。


#include<stdio.h>

#include<stdlib.h>

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),无返回值,使用时需要引用头文件<stdlib.h>,srand函数是C语言标准库中的一个随机数种子初始化函数,用于初始化随机数序列。


其原型时是:


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<stdio.h>
#include<stdlib.h>
#include<time.h>
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;
}


想体验的小伙伴,可以亲自去尝试一下哟。


goto语句


       C语言中提供了可以随意滥用的 goto语句和标记跳转的标号,但是只能在当前函数内跳转,不能跨越多个函数进行跳转。


goto语句是一条跳转语句,可用于将程序的执行从一段代码直接跳转到其他代码的特定位置。它可以在程序的任何地方使用,但过度使用goto语句可能导致代码难以理解和维护。 在使用goto语句时,需要定义一个标签,用于标示跳转的目标位置。例如,如果有一段代码需要重复执行多次,可以在代码块的开头定义一个标签,并在代码块的末尾通过goto语句跳转到该标签的位置,从而实现代码块的循环执行。


例如,下面是一个使用goto语句实现循环的示例代码:


#include <stdio.h>

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<stdio.h>
#include<stdlib.h>
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 <stdio.h>
#include <stdlib.h>
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;
}


素数的求解的n中境界


思路:


       素数:即质数,除了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; j<i; j++)
    {
      if(i%j == 0)
      {
        break;
      }
    }
    // 上述循环结束之后,如果j和i相等,说明[2, i)之间的所有数据都不能被i整除,则i为素数
    if(j==i)
    {
      count++;
      printf("%d ", i);
    }
  }
  printf("\ncount = %d\n", count);
  return 0;
}
//上述方法的缺陷:超过i一半的数据,肯定不是i的倍数,上述进行了许多没有意义的运算,因此可以采用如下
// 方式进行优化
// 方法二:每拿到一个数据,只需要检测其:[2, i/2]区间内是否有元素可以被2i整除即可,可以说明i不是素数
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<=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;
}


相关文章
|
5月前
|
机器学习/深度学习 传感器 自然语言处理
Deep Learning
【6月更文挑战第7天】
39 2
|
5月前
|
机器学习/深度学习 数据采集 人工智能
Supervised Learning
【6月更文挑战第7天】
49 2
|
6月前
|
存储 编译器 C语言
C learning_2
C learning_2
|
6月前
|
算法 C语言 数据安全/隐私保护
C learning_6
C learning_6
|
6月前
|
编译器 C语言
C learning_1
C learning_1
|
6月前
|
存储 C语言 C++
|
6月前
|
存储 安全 程序员
C learning_5
C learning_5
|
6月前
|
存储 API 数据安全/隐私保护
C learning_7
C learning_7
|
6月前
|
存储 缓存 安全
C learning_4
C learning_4
|
6月前
|
C语言