C语言趣味代码(一)

C语言相关知识点的博客和大家分享完了,接下来我想开始数据结构相关的博客,在此之前呢,有的小伙伴问过我学完C语言的相关知识,我能干些什么呢?只有刷题吗?这不禁让我反思:在我们学习的过程中,我们所有学习时用到的书籍都是围绕某一知识点介绍、拓展,千篇一律的示例代码,好像从没出现一些新颖的代码。所以我想用3篇左右的博客跟大家分享一下用我们学过的知识实现的有趣代码,然后再开始后面的数据结构的博客。

1. 心算训练

什么是心算呢?心算是一种在不使用纸张或任何其他非思维工具的情况下解决数学问题的技能。心算能力是指仅用头脑进行数学计算的能力。无需计算器等外部工具的帮助。虽然在现代世界中这似乎是一项无用的技能,但它实际上非常有用,并且对于提高解决问题和决策的技能大有帮助。下面我们先介绍可能会用到的相关函数,然后再进行实现。

1.1 操纵时间

首先我们编写一个能够操纵时间,显示动态画面的程序:

#include<stdio.h>
#include<time.h>
int sleep(unsigned long x)
{
	clock_t c1 = clock(), c2;
	do 
	{
		if ((c2 = clock()) == (clock_t)-1)
		{
			return 0;
		}
	} while (1000.0 * (c2 - c1) / CLOCKS_PER_SEC<x);
	return 1;
}
int main()
{
	int i;
	clock_t c;
	for (i = 10; i > 0; i--)
	{
		printf("\r%2d", i);
		fflush(stdout);
		sleep(1000);
	}
	printf("\r\aEND! \n");
	c = clock();
	printf("程序从开始到结束运行了%.1f秒\n", (double)c / CLOCKS_PER_SEC);
	return 0;
}

因为我不太会电脑录制,就给大家看一下最终结果吧,感兴趣的可以自己试试。

在这个程序中我们使用了clock函数用来求程序开始运行到结束所花费的时间。

函数名clock函数
头文件#include<time.h>
格式clock_t clock(void)
功能求处理器调用某个进程所花费的时间
返回值从定义与程序启动相关的编程环境的时间点起,用处理系统的最佳值逼近返回程序占用处理器的时间。为了以秒为计量单位,必须用本函数的返回值除以CLOCK_FER_SEC宏的值,如果无法获取处理器调用该进程花费的时间,或无法显示数值是,就返回(clock_t)-1。

可以使用<time.h>头文件吧返回值的类型clock_t型定义成等同于算术类型,clock_t主要等同于那种类型(unsigned,unsigned long....)要取决于编程环境。在某些环境中clock_t型并不等同于unsigned型,程序在这些编程环境中,比一定能顺畅运行。除此之外,因为不同的硬件和OS会导致时钟的精准度也不同,所以clock_t型表示数值的单位也取决于编程环境,因此通常用<time.h>头文件定义CLOCK_FER_SEC这一对象宏,CLOCK_FER_SEC直接翻译过来就是“每秒的时钟数”。如果时钟的精度在0.001秒,那么一秒内就有1000个时钟,这个宏的值就定义为1000。

#define CLOCK_FER_SRC 1000//定义示例,根据编程环境的不同有所差距

在上面的程序中,用一位小数的实数值,表示程序启动后花费的时间。

c = clock();
printf("程序从开始到结束运行了%.1f秒\n", (double)c / CLOCKS_PER_SEC);

上面这部分代码把c强制类型转换成了double型,来求出经过的秒数,这是因为“整数/整数”的运算中会舍去小数部分。另外,因为clock函数返回的值只用于求经过的时间,所以不加入变量c也能实现(这样一来变量c也就可以省去了):

c = clock();
printf("程序从开始到结束运行了%.1f秒\n", (double)clock() / CLOCKS_PER_SEC);

讲了如何计算程序启动后经过的时间,下面来教大家如何计算处理特定部分所需要的时间。因为程序不接受错误的答案,所以在回答正确之前程序都不会改变。我们试着实现一下:提示的问题是要把三个三位数的整数相加,输出答案后,画面上会显示解题共花费了多长时间:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
	int a, b, c;//要进行加法运算的数值
	int x;//读取的值
	clock_t start, end;//开始时间和结束时间
	double req_time;//所需时间
	srand(time(NULL));
	a = 100 + rand() % 900;
	b = 100 + rand() % 900;
	c = 100 + rand() % 900;
	printf("%d+%d+%d的计算结果是多少:", a, b, c);
	start = clock();
	while (1)
	{
		scanf("%d", &x);
		if (x == a + b + c)
			break;
		printf("\a回答错误!\n请重新输入");
	}
	end = clock();
	req_time = (double)(end - start) / CLOCKS_PER_SEC;
	printf("用时%.1f秒", req_time);
	if (req_time > 30.0)
		printf("花费时间太长了\n");
	if (req_time > 15.0)
		printf("还不错\n");
	else
		printf("好厉害\n");
	return 0;
}

我们运行一下来看看吧(我算的有点慢):

这里面的while语句是为了不接受错误答案而设置的循环,因为控制表达式的是1,所以循环会一直执行下去,当回答正确时,程序会通过break语句强行中断while循环。如果不想使用brak语句,也可以使用下面的do..while语句来中断循环:

do
{
  scanf("%d",&x);
  if(x!=a+b+c)
    printf("\a回答错误!\n请重新输入:");
}while(x!=a+b+c);

 在上面的代码中,为了将处理暂停一段时间,我们使用了sleep函数:

int sleep(unsigned long x)
{
	clock_t c1 = clock(), c2;
	do
	{
		if ((c2 = clock()) == (clock_t)-1)
		{
			return 0;
		}
	} while (1000.0 * (c2 - c1) / CLOCKS_PER_SEC < x);
	return 1;
}

首先程序一开始调用了clock函数,把程序启动后经过的时间存入c1,然后运行do语句,在每次循环时调用clock函数,把获取的数值赋给c2。程序中while语句括号里面会以毫秒为单位表示sleep函数开始运行后经过的时间,当这个数值大于等于x时,通过do语句进行的循环就结束了。上文所说,clock函数“如果无法获取处理器调用该进程花费的时间,或无法显示数值是,就返回(clock_t)-1”。这里是把int型的整数值-1强制类型转换成clock_t类型后的值,绝不是“clock_t-1后的值”。当clock函数返回表示错误的-1时,sleep函数会通过返回0来通知调用发生了问题。注意:sleep函数会占用CPU,与其说“运行函数花了多长时间”,但不如说“sleep函数让CPU这个大脑持续运行了多少时间”。

1.2 最终实现

这是一个把3个3位数连续相加的心算训练程序,程序最后会显示进行10次心算所需要的时间:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
	int stage;//次数
	int a, b, c;
	int x;
	int n;//空白的宽度
	clock_t start, end;
	srand(time(NULL));
	printf("心算训练开始!\n");
	start = clock();
	for (stage = 0; stage < 10; stage++)
	{
		a = 100 + rand() % 900;
		b = 100 + rand() % 900;
		c = 100 + rand() % 900;
		n = rand() % 15;
		printf("%d%*s+%*s%d%*s+%*s%d=", a, n, "", n, "", b, n, "", n, "", c);
		do
		{
			scanf_s("%d", &x);
			if (x == a + b + c)
				break;
			printf("\a回答错误!\n请重新回答");
		} while (1);
	}
	end = clock();
	printf("一共用时%.1f秒", (double)(end - start) / CLOCKS_PER_SEC);
	return 0;
}

其中,我们把空白字符的个数n定位0~14的随机数。我们命令printf函数“至少用n位数表示空的字符串”,程序就会显示n个空白字符串。数值间留有空白,可以训练我们的心算能力。

2. 猜拳游戏

现在我们要编写一个提供两位玩家对战的“猜拳游戏”。当然,这里所说的“两位玩家”是指计算机和玩家,即游戏采用人机对战的模式。:

2.1 流程分析

  1. 确定计算机要出的手势。
  2. 显示“石头剪刀布”,然后玩家输入自己要出的手势。
  3. 进行输赢判断。,显示结果。
  4. 询问是否继续,如果玩家希望继续,就回到1。

下面我们详细设计一下各个步骤:

1.用随机数确定计算机所出的手势:

之所以要先确定计算机出的手势,再读取玩家的手势,是为了避免计算机作弊。

2.如果用“石头”,“剪刀”,“布”的字符串来进行手势输入,可能会产生输入错误,例如一不小心打错字,变成“势头”,“见到”等。因此我们把“石头”,“剪刀”,“布”这三个手势分别对应数字0,1,2(类型设为int型)。如果玩家的手势和计算机的手势能用相同的数值表示出来,就保持了一致性,会方便,这样一来,也确定了在1的设计中未解决的手势的数值。

3.根据计算机和玩家的手势判断胜负:

此处使用变量human和comp来分别表示玩家和计算机的手势,下面为手势和胜负的关系:

平局情况:

humancomphuman-comp(human-comp+3)%3
0000
1100
2200

玩家失败情况:

humancomphuman-comp(human-comp+3)%3
02-21
1011
2111

 玩家胜利的情况:

humancomphuman-comp(human-comp+3)%3
01-12
12-12
2022

上面的3个表格中汇总了双方的手势数值、human减去comp后的值、判断表达式(human-comp+3)%3的值。如果human和comp的值相等就算作“平局”,此时human-comp的值为0。失败和胜利的情况同理。

2.2 程序的实现

2.2.1 用switch语句实现

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
	int human;//玩家的手势
	int comp;//电脑的手势
	int judge;//胜负
	int retry;//再来一次?
	srand(time(NULL));
	printf("猜拳游戏开始!\n");
	do
	{
		comp = rand() % 3;
		printf("\n\a石头剪刀布   (0)石头(1)剪刀(2)布:");
		scanf("%d", &human);
		printf("我出的是:");//显示计算机出的手势
		switch (comp)
		{
		   case 0:
			   printf("石头");
			   break;
		   case 1:
			   printf("剪刀");
			   break;
		   case 2:
			   printf("布");
			   break;
		}
		printf("。\n");
		judge = (human - comp + 3) % 3;
		switch (judge)
		{
		   case 0:
			   printf("平局");
			   break;
		   case 1:
			   printf("你输了");
			   break;
		   case 2:
			   printf("你赢了");
			   break;
		}
		printf("还要再来一次吗?(0)否(1)是");
		scanf("%d", &retry);
	} while (retry == 1);
	return 0;
}

我们来运行看一下:

2.2.2 让计算机“后出” 

为了让计算机赢,我们可以让计算机比玩家后出。具体实现代码 :

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
	int i;
	int human;
	int comp;
	int judge;
	int retry;
	char* hd[] = { "石头","剪刀","布" };
	printf("猜拳游戏开始!\n");
	do
	{
		do 
		{
			printf("\n\a石头剪刀布   ");
			for (i = 0; i < 3; i++)
				printf("(%d)%s", i, hd[i]);
			printf(":");
			scanf("%d", &human);
		} while (human < 0 || human>2);
		comp = (human + 2) % 3;//计算机后出
		printf("我出%s,你出%s.\n", hd[comp], hd[human]);
		judge = (human - comp + 3) % 3;
		switch (judge)
		{
			  case 0:
				printf("平局\n");
				break;
		      case 1:
			    printf("你输了\n");
				break;
			  case 2:
				printf("你赢了\n");
				break;
		}
		printf("再来一次吗?   (0)否(1)是");
		scanf("%d", &retry);
	} while (retry == 1);
	return 0;
}

运行一下看看结果:

这个程序可以拿给朋友玩,在旁边看他一直输。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/551818.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【RSGIS数据资源】2001-2022年中国玉米种植分布数据集

文章目录 数据介绍精彩截图2001&#xff5e;2020年中国玉米种植频率分布2001年至2020年研究区域融合数据的平均填充百分比。 数据介绍 2001-2022年中国玉米种植分布数据集&#xff08;CCD-Maize&#xff09;&#xff0c;涵盖中国22个省、市的玉米种植分布图&#xff0c;文件格…

一文搞定 EventLoop、宏任务、微任务

面试官&#xff1a;你了解JavaScript事件循环吗&#xff0c;掌握多少&#xff0c;把你知道的都说一下。 今天我们就来说一下&#xff0c;JavaScript作为一门单线程语言&#xff0c;如何通过事件循环&#xff08;Event Loop&#xff09;和任务队列&#xff08;Task Queue&#…

CTFHUB-技能树-Web前置技能-文件上传(无验证,JS前端验证,前端验证)

CTFHUB-技能树-Web前置技能-文件上传&#xff08;无验证&#xff0c;JS前端验证&#xff0c;前端验证—.htaccess&#xff09; 文章目录 CTFHUB-技能树-Web前置技能-文件上传&#xff08;无验证&#xff0c;JS前端验证&#xff0c;前端验证—.htaccess&#xff09;文件上传无验…

关联规则挖掘(二)

目录 三、FP-增长算法&#xff08;一&#xff09;算法的背景&#xff08;二&#xff09;构造FP-树&#xff08;三&#xff09;生成频繁项集 四、关联规则的评价&#xff08;一&#xff09;支持度和置信度的不足&#xff08;二&#xff09;相关性分析 三、FP-增长算法 &#xf…

C++内存管理——new/delete、operator new/operator delete

内存管理 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(sizeof(int) * 4);int* pt…

tcp三次握手和四次断开以及tcpdump的基本使用

前言 最近工作中会发现有超时的问题&#xff0c;还有就是在面试的时候很多都要求深入理解TCP/IP协议。突然感觉TCP/IP协议是一个既熟悉&#xff0c;又陌生的技术。又想到上大学的时候&#xff0c;老师说过 网络的圣经&#xff1a;“TCP/IP详解” 卷一 卷二 卷三&#xff0c;三…

IIC总线读取温度湿度传感器数据实验

iic.c #include "iic.h"extern void printf(const char* fmt, ...); /** 函数名 &#xff1a; delay_us* 函数功能&#xff1a;延时函数* 函数参数&#xff1a;无* 函数返回值&#xff1a;无* */ void delay_us(void) //微秒级延时 {unsigned int i 2000;while(i-…

性能工具之emqtt-bench BenchMark 测试示例

文章目录 一、前言二、典型压测场景三、机器准备四、典型压测场景1、并发连接2、消息吞吐量测试2.1 1 对 1&#xff08;示例&#xff09;2.2 多对1&#xff08;示例&#xff09;2.3 1对多&#xff08;示例&#xff09; 五、遇到的问题client(): EXIT for {shutdown,eaddrnotava…

java学习之路-多态

文章目录 目录 文章目录 前言 1.多态 1.1 多态的概念 1.2 多态实现条件&#xff08;重点&#xff09; 多态实现的栗子 1.3重写 重写的规则 重写和重载的区别 1.4静态和动态绑定 1.5向上转型和向下转型 1.向上转型 2.向下转型 1.6多态的优点 前言 本文内容&#xff1a;多…

DHCP是什么意思 路由器中DHCP服务器怎么设置?

概述 DHCP是什么意思&#xff1f;很多朋友在路由器设置中&#xff0c;都会看到有一项“DHCP服务器”设置功能&#xff0c;而很多朋友对这个功能不太了解&#xff0c;也不知道怎么设置。其实&#xff0c;对于普通用户来说&#xff0c;无需去单独设置路由器DHCP服务器功能&#…

李沐46_语义分割和数据集——自学笔记

语义分割 语义分割将图片中的每个像素分类到对应的类别。 实例分割&#xff08;目标检测的进化版本&#xff09; 如果有物体&#xff0c;会区别同一类的不同物体。 语义分割重要数据集&#xff1a;Pascal VOC2012 %matplotlib inline import os import torch import torch…

【强化学习的数学原理-赵世钰】课程笔记(九)策略梯度方法(Policy Gradient Method)

目录 一.policy gradient 的基本思路&#xff08;Basic idea of policy gradient&#xff09; 二.定义最优策略的 metrics&#xff0c;也就是 objective function 是什么 三.objective function 的 gradient 四.梯度上升算法&#xff08;REINFORCE&#xff09; 五.总结 上…

DevExpress WinForms中文教程 - 如何通过UI测试自动化增强应用可靠性?(二)

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…

数字工厂管理系统与MES系统有什么区别

随着工业4.0时代的到来&#xff0c;数字化转型已经成为制造企业发展的必然趋势。在这个过程中&#xff0c;数字工厂管理系统和MES管理系统都扮演者至关重要的角色。然而&#xff0c;尽管两者都致力于优化生产流程和提高生产效率&#xff0c;但它们在实际应用、功能定位和系统架…

Datapump数据迁移方案

环境准备 确认源数据库和目标数据库的版本 确保源数据库和目标数据库的Oracle版本兼容&#xff0c;以保证Datapump工具能够正常工作。 硬件资源检查 确认源数据库和目标数据库服务器的硬件资源&#xff08;如CPU、内存、存储空间&#xff09;能够满足数据迁移的需求。 网络连…

基于STM32的智能垃圾分类识别系统设计(论文)_kaic

摘 要 智能垃圾分类技术逐渐受到了政府的重视和支持&#xff0c;越来越多的城市开始推行垃圾分类政策。因此设计一款能够对垃圾进行识别并分类的控制系统具有一定的现实意义。本设计采用STM32单片机作为整个系统的控制核心&#xff0c;利用K210开发板作为图像识别控制系统&…

在Postgres中,如何有效地管理大型数据库的大小和增长

文章目录 一、定期清理和维护1. VACUUM和ANALYZE2. 删除旧数据和归档 二、分区表三、压缩数据四、配置优化1. 调整维护工作负载2. 监控和日志 五、使用外部存储和扩展1. 外部表和FDW2. 扩展和插件 六、定期备份和恢复测试结论 管理大型数据库的大小和增长是数据库管理员&#x…

如何看懂电路图,理解电流回路

任何电器都需要电源来供电。电源有正极(+)和负极(-),为了向负载提供电力,电流必须从正极流出,通过负载后再回到负极。这构成了一个供电电流回路,负载得到电力供应后才能开始工作。如果其中的某个环节断开,就无法形成供电电流回路,负载将得不到供电,也无法正常工作。 在一…

Typescript 总结3——类

一、是什么 类&#xff08;Class&#xff09;是面向对象程序设计&#xff08;OOP&#xff0c;Object-Oriented Programming&#xff09;实现信息封装的基础 类是一种用户定义的引用数据类型&#xff0c;也称类类型 传统的面向对象语言基本都是基于类的&#xff0c;JavaScript …

机器学习与深度学习 --李宏毅(笔记与个人理解)Day 20

Day 20 RNN 2 实际使用和其他应用 在实际的学习&#xff08;training&#xff09;过程中是如何工作的&#xff1f; step 1 Loss step 2 training Graindent Descent 反向传播的进阶版 – BPTT CLIpping 设置阈值~ 笑死昨天刚看完关伟说的有这玩意的就不是好东西 Why&#xff1…