七、判断(二)

引:学校举办了一个抽奖获得,根据学号给予学生奖励,学生奖励如下:

学号 奖励
15692 现金500
65432 现金450
98741 现金250
2531 现金150
666 学号*2
321 学号*2
//if语句实现
#include <iostream>

int main()
{
	unsigned int sId{}, sPr{};  //定义学生学号和奖励
	std::cout << "请输入你的学号:";
	std::cin >> sId;
	if (sId == 15692) sPr = 500;
	if (sId == 65432) sPr = 450;
	if (sId == 98741) sPr = 250;
	if (sId == 2531) sPr = 150;
	if (sId == 666) sPr = sId*2;
	if (sId == 321) sPr = sId*2;

	std::cout << "恭喜你获得了奖学金" << sPr << "人民币";
}

1、switch语句

注:if语句中的条件是一个bool类型值,switch语句的条件是一个整数值

1)switch语法

//switch语法
switch(值)          //值是一个整数值,里面的值不管是小数还是其他类型的值默认都会转化为整数类型
{
        case 选项1:        //选项和switch中的值进行比较
            break;
        case 选项2:
            break;
        case 选项3:
        case 选项4:
            break;
    	default:    //前面的选项没有的一律会进入default,需要再加个break返回
        	break;
        
        
}

2)上述案例实现

//switch实现用户抽奖
#include <iostream>

int main()
{
	unsigned int sId, sPr{};  //定义学生学号和奖励
	std::cout << "请输入你的学号:";
	std::cin >> sId;
	switch(sId)
	{
		case 15692:
			sPr = 500;
			break;       //遇到break跳出switch语句
		case 65432:
			sPr = 450;
			break;
		case 98741:
			sPr = 250;
			break;
		case 2531:
			sPr = 150;
			break;
		case 666:         //等于666,因没有break,自动执行下面的语句,同样使得sId*2
		case 321:
			sPr = sId*2;        //等同于sId << 1;
			break;
		default:    //上述条件都未满足,则执行default中的代码
			std::cout << "对不起,你未参加本次的抽奖!!";
			break;
	}
	if(sPr)std::cout << "恭喜你获得了奖学金" << sPr << "人民币";  //Spr==0不执行该语句
}

3)switch语法C++17升级内容【fallthrough

switch(值)          
{
        case 选项1:        
            break;
        case 选项2:
            break;
        case 选项3:
            [[fallthrough]];  //贯穿选项。表示选项3以后直接执行选项4,而不是因为开发人员漏写了break
        case 选项4:
            break;
    	default:    
        	break;
}
2、语句块中的变量声明方式

1)if语句

①if语句中临时变量的声明

if(条件)
{
    变量声明;   //变量在哪用,在那声明
}
else
{
    变量声明;  //上面定义的变量,在else中无法使用
}

②c++17新语法中临时变量的声明

if(变量声明;条件)   //if(int a;a>0){ }else{ }
{
    变量使用;      //if中声明的变量,在if代码块和else代码块中都可以使用
}
else
{
    变量使用
}

2)switch语句中临时变量的声明

switch(变量声明,值)          //switch(int a{},300){...}
{
        case 选项1:        
            break;
        case 选项2:
            break;
    	default:    
        	break;
}
3、C语言格式化输出流及转义

1)printf格式化输出

字符 含义 示例
d 十进制整数 print("我叫%s,年龄%d","张三",20);
o 八进制整数
u 无符号十进制整数 将负号去掉
x/X 十六进制整数
f float小数
lf double小数
s 字符串
0 用0来补齐 %05d即00001
+ 替数字输出符号%+ d %+05d 会将符号表述出来
#include <iostream>
int main()
{
	int age{ 18 };
	printf("你好,世界!!!\n");
	printf("我叫%s,我的年龄%d岁", "张三\n",age);
	printf("0x%X\n",age); //十六进制输出
	printf("%05d\n", age); //字符对其
	printf("%+d", age); //输出符号
}

2)scanf格式化输入

字符 含义
d 十进制整数
o 八进制整数
u 无符号十进制整数
x/X 十六进制整数
f float小数
lf double小数
s 字符串%s
#include <iostream>
int main()
{
	int age{  };
	printf("请输入你的年龄:");
	scanf_s("%d",&age);
	printf("输入的年龄为:%d",age);
}

注:**&为取值运算符,&a,表示取a的地址

3)无显示的输入

//输入键盘上的字符后,不显示到屏幕上 
#include <iostream>
#include <conio.h>
int main()
{
	int uin = _getch();    //输入一个字符,会将输入的字符或者数字,通过ASCII表翻译成整数(输入的是键盘按键的值)
	std::cout << "你输入的字符为:"<<uin << std::endl;
}

4、goto语句

1)goto语句语法

//goto语法
标签:
goto 标签;

注:goto常和判断一起使用

2)案例:

//goto案例
#include <iostream>

int main()
{
	char a;
linput:
	printf("请输入一个大写字母:");
	std::cin >> a;
	if (a > 64 && a < 91)
	{
		a += 32;
		std::cout << "转化后的小写字母为:" << a << std::endl;
		goto linput;   //跳到标签定义的位置,重复执行
	}
	else
	{
		printf("你输入的内容不符合要求,请重新输入\n");
		goto linput;  //跳到标签定义的位置,重复执行
	}

}

5、案例:网银证书密码攻击(安全实验)

需求:设计一个系统来模拟网银密码被攻击的场景,用户输入一个6位的数字密码,然后我们破解它的密码

#include <iostream>
#include <conio.h>

int main()
{
linput:
	int password,repassword;
	std::cout << "请输入一个6位数数字密码:";
	std::cin >> password;
	std::cout << "请你再数一次你的数字密码:";
	std::cin >> repassword;

	if (password == repassword)
	{
		if (password > 999999) goto linput;
		system("cls");
		std::cout << "密码设置成功,请按任意键进入密码破解系统\n";
		_getch();
		int testpass{};
lhack:
		if (testpass != password)
		{
			testpass++;
			goto lhack;
		}
		else std::cout << "密码为:" << testpass;

	}
	else goto linput;

}
6、if语句和switch语句的出场时机

注:switch语句效率比if语句的效率高,超过3个判断尽量使用switch

if语句和switc语句汇编比较

cmp指令表示比较;jmp相当于goto,进行跳转

7、项目:设置游戏技能

需求:设计麟江湖的技能释放模型,要求用户按下相应技能快捷键后开始释放技能,技能数据如下,假设角色的当前等级下最高内力为1000,最高生命为3000,基础攻击力为50

快捷键 技能名称 技能效果
1 治愈 消耗100内力,生命值恢复最大生命值的10%
2 金刚掌 消耗50内力,对远程目标造成基础攻击+50点伤害
3 麻痹数 消耗50内力,禁止目标攻击三个回合
4 鹰抓功 10个回合内,对目标造成伤害将恢复伤害量20%的内力伤害量60%的生命
5 绝处逢生 消耗100内力,对目标造成基础攻击+已损失血量的伤害
6 易筋经 消耗300内力,将内力和生命值进行互换,攻击力提高1000%
#include <iostream>
#include <conio.h>

struct Role 
{
	int Hp;
	int maxHp;
	int Mp;
	int maxMp;
	int act; //攻击力
	int cantact; //禁止攻击
	int bufcount; //回合
	bool cant;
};
int main() 
{	
	int inkey, damage;
	Role user{ 3000,3000,1000,1000,50,0,false };
	Role boss{ 30000,30000,1000,1000,190,0,false };
lfight:
	system("cls");
	printf("生命[%d/%d]  BOSS生命[%d/%d]\n",user.Hp,user.maxHp,boss.Hp,boss.maxHp);
	printf("内力[%d/%d]  攻击力[%d]\n", user.Mp, user.maxMp, user.act);
	printf("请输入你的技能:");
	
	inkey = _getch();
	damage = 0;
	switch(inkey)
	{
		case 49: 
			if (user.Mp > 99)
			{
				user.Mp -= 100;
				user.Hp += 300;
				user.Hp = user.Hp > user.maxHp ? user.maxHp : user.Hp;
			}
			break;
		case 50: 
			if (user.Mp >= 50)
			{
				user.Mp -= 50;
				user.Hp -= 50 + user.act;
			}
			break;
		case 51:
			if (user.Mp >= 50)
			{
				user.Mp -= 50;
				boss.cantact = 3;
			}
			break;
		case 52:
			user.bufcount = 10;
			break;
		case 53:
			if (user.Mp >= 100)
			{
				user.Mp -= 100;
				damage = user.maxHp - user.Hp + user.act;
			}
			break;
		case 54:
			if ((user.Mp >= 300) && (!user.cant))
			{
				int ls = user.maxHp;
				user.maxHp = user.maxMp;
				user.maxMp = ls;
				ls = user.Hp;
				user.Hp = user.Mp;
				user.Mp = ls;
				user.act *= 10;
				user.cant = true;
			}
			break;
	}

	if (boss.cantact > 0)
	{
		boss.cantact--;
	}
	else user.Hp -= boss.act;
	boss.Hp -= damage;
	if (user.bufcount > 0)
	{
		user.bufcount--;
		user.Hp += damage * 0.6;
		user.Mp += damage * 0.2;
		user.Hp = user.Hp > user.maxHp ? user.maxHp : user.Hp;
		user.Mp = user.Mp > user.maxMp ? user.maxMp : user.Mp;
	}
	if (user.Hp < 1)
	{
		system("cls");
		printf("你死了,游戏结束!!");
	}
	else if (boss.Hp < 1)
	{
		system("cls");
		printf("击败BOSS,游戏结束!!");
	}
	else goto lfight;
}