四、基本數據類型和計算(三) 1、枚舉變數 1)通過案例體現枚舉類型的作用 假設要為我們的游戲裝備設置稀有度屬性,應該如何設計 裝備級別 變數名 普通 normal 高級 high 稀有 rare 史詩 epic 傳說 legend 神話 myth 不使用枚舉變數,使用常量方式設置 #inclu ...
四、基本數據類型和計算(三)
1、枚舉變數
1)通過案例體現枚舉類型的作用
假設要為我們的游戲裝備設置稀有度屬性,應該如何設計
裝備級別 | 變數名 |
---|---|
普通 | normal |
高級 | high |
稀有 | rare |
史詩 | epic |
傳說 | legend |
神話 | myth |
不使用枚舉變數,使用常量方式設置
#include <iostream>
#define Normal 0 //普通裝備
#define High 1 //高級裝備
#define Rare 2 //稀有裝備
#define Epic 3 //史詩裝備
#define Legend 4 //傳說裝備
#define myth 5 //神話裝備
int main()
{
short weaponLv;
short weaponALv = Rare; //稀有
short weaponBLv = myth; //神話
std::cout << "裝備A的等級為:" << weaponALv << std::end;;
std::cout << "裝備B的等級為:" << weaponBLv << std::endl;
}
2)枚舉變數定義及聲明
電腦中沒有這種類型,我們自定義一種數據類型,就叫做枚舉類型
定義 | enum class 類型名稱:基本類型{選項1,選項2}; |
---|---|
聲明 | 類型名稱 變數名稱; |
示例 | 如下 |
註:基本類型只能是整數類型,如果不寫預設為int類型,整數類型用來說明大括弧中定義的變數是什麼類型。
//通過枚舉類型設置裝備的稀有程度
#include <iostream>
int main() {
enum class EquipLv : int { //可以將int替換為其他整數類型,如float
normal = 10, armyA = normal,//普通 //若不初始化,預設為0
high, armyB = high,//高級 //從上之下自動遞增,此處high為11
rare, armyC = rare,//稀有
epic, armyD = epic,//史詩
legend, armyE = legend,//傳奇
myth = 100, armyS = normal//神話
};
EquipLv weaponAlv{ EquipLv::normal }; //定義裝備A等級
EquipLv weaponBlv{ EquipLv::myth }; //定義裝備B等級
short diff = (int)weaponAlv - (int)weaponBlv; //如果不強制類型轉化,無法直接進行計算
std::cout << "weaponAweaponB裝備的等級差為:" << diff << std::endl;
weaponAlv = EquipLv::rare; //重新賦值。修改裝備A的等級
std::cout << "裝備A的等級修改為:" << int(weaponAlv)<<std::endl;
}
2)枚舉類型註意點
①枚舉類型可以提高代碼的可讀性和安全性
②枚舉類型預設是int類型
③枚舉類型成員只能是整數類型
④枚舉類型和其他類型轉化需要強制轉化
⑤預設情況下,枚舉類型的下一項的初始值是上一項的初始值+1
2、自定義變數名稱
將C/C++中已有的變數進行改名,可以將一些特別長的變數名進行改名
語法 | 含義 | 缺點 |
---|---|---|
#define A TypeName | 以後代碼中的A可以被替換為TypeName | 簡單替換 |
typedef TypeName A; | 以後TypeName類型的名字可以用A替換 | 不直觀 |
using A=TypeName; | 以後TypeName類型的名字可以用A替換 | 可以實現一些信特性 |
#include <iostream>
#define 整數 int //自定義變數名稱方法一
#define elong long ////自定義變數名稱方法一,將long替換為elong
int main() {
整數 num{ 100 }; //編譯器編譯時,會將所有的"整數"替換為int
typedef unsigned xxx; //自定義方法名稱二,即將unsigned類型替換為xxx
xxx A{200};
using ellong = long long; //自定義變數名稱方法三,將long long替換為ellong,
ellong a{50};
using elllong = elong elong; //此時的一個long已通過elong替換
std::cout << num << char(10);
std::cout << A << char(10);
std::cout << a << char(10);
}
3、命名空間
1)命名空間定義
為了將需要用的東西放到一起,例如: 糧食倉庫::大米;糧食倉庫:小麥
namespace namespace_name {
// 代碼聲明
}
2)命名空間使用
使用方式 | 語法 | 備註 |
---|---|---|
方式一 | std::cout | 使用限定符:: |
方式二 | using std::cout;cout<<"再不用std"; | 使用using,只有cout不需要寫命名空間std |
方式三 | using namespace std; | 命名空間所有內容都可進行使用,不推薦 |
//命名空間的定義和使用
#include <iostream>
namespace lGame {
int HP{ 1000 };
int MP{ 1000 };
int lv{ 1 };
namespace Weapon { //命名空間的內嵌定義
int damage{ 3000 };
namespace WeaponInfo {
int lv = lGame::lv;
}
}
}
int main() {
using std::cout; //命名空間第一種使用方式
using namespace std; //命名空間第二種使用方式
using lGame::HP; //命名空間第三種使用方式
std::cout<<"用戶血量為"<<lGame::HP<<std::endl; //命令空間的使用
std::cout<<"用戶血量為"<<HP<<std::endl;
int c = lGame::Weapon::damage; //命名空間內嵌使用
cout << c; //此時不需要在寫cout
}
3)命名空間註意事項
①不能將命名空間定義放在函數體內
②可以在一個命名空間內嵌入另一個命名空間
③子級命名空間調用父級命名空間依然需要限定符::
4、變數的生命周期
變數的聲明周期,本質上為記憶體的生命周期。即記憶體的申請和釋放
#include <iostream>
int a{ 100 }; //沒有在代碼塊內,屬於全局變數,程式結束則變數結束
int main()
{
int a{ 160 };
{
int a{ 350 }; //在代碼快中可以用::a來調用全局變數a{100};
{
char a = 'A';
std::cout << a<<std::endl; //輸出A
std::cout << ::a << std::endl; //輸出100
}
std::cout << a << std::endl; //輸出350 //變數就近往上原則,聲明周期原則,通常找距離它最近的值
}
std::cout << a <<std::endl; //輸出160
}
1)註意事項
①代碼塊中的變數的生命周期從聲明開始,知道這個代碼塊結束
②聲明在代碼開始前的變數叫做全局變數,全局變數的生命從程式運行開始,知道程式退出
③在變數名衝突的情況下,採用就近原則
④要訪問名稱衝突的全局變數,可以使用限定符::來訪問
⑤變數哪裡用哪裡聲明
5、位運算之異或運算
1)異或運算關係:相同為0,不同為1
2)作用:加解密
3)異或運算最大特征:具有還原功能,只要其中有一個值發生了變化,都可通過相互異或檢測出來。
即a^b=c; b^c=a; c^a=b;
4)案例:
麟江湖是一個單機游戲,其中變數diamond代表鑽石,變數vip_exp代表累計鑽石消費數。設計一個演算法,使得能夠發現,用戶使用單機修改器修改了鑽石或者累計鑽石數這樣的做必須行為。
思路:將鑽石diamond和累計消費數vip_exp放在a、b的位置,只要將兩個值進行異或操作生成C,只要使用C和其中任何一個值異或計算,就可判斷出第三個值是否發生改變,進而檢測出用戶有無作弊
#include <iostream>
int main() {
unsigned int diamond{ 6000 }; //鑽石數量
unsigned int vip_exp{ 80000 }; //VIP充值經驗
unsigned xbase = diamond ^ vip_exp;
std::cout << "修改鑽石數量:";
std::cin >> diamond;
std::cout << "修改累計消費:";
std::cin >> vip_exp;
//模擬檢測
unsigned realDiamond = xbase ^ vip_exp;
unsigned realvip_exp = xbase ^ diamond;
std::cout << "你應該的鑽石數量為:" << realDiamond << std::endl;
std::cout << "你應該的累計消費為:" << realvip_exp << std::endl;
}
只要修改一個值,就可還原出來原來的數據;如果修改兩個值,值雖然不會還原出來,但是也可以確認用戶作弊了
7、自定義數據類型(結構體)
自己創建數據類型,解決基本數據類型解決不了的問題。
基本數據類型問題:假如要創建一個汽車管理系統,要定義多個品牌的車,每個品牌的屬性都不一樣,若只用基本數據類型,就需要將每種品牌的車都進行定義,很麻煩
#include <iostream>
int main()
{
int wheel {19};
unsigned price{ 100000 };
char logo{ 'B' };
unsigned gls{ 100 };
std::cout << "車輛商標:" << logo << " 車輪大小:" << wheel << " 車輛售價:" << price << std::endl;
int wheelA{ 20 };
unsigned priceA{ 900000 };
char logoA{ 'C' };
unsigned glsA{ 200 };
std::cout << "車輛商標:" << logoA << " 車輪大小:" << wheelA << " 車輛售價:" << priceA << std::endl;
}
1)結構體定義及使用
//結構體的定義方法
struct 名稱
{
類型 名稱;
}
//結構體類型使用
結構體名稱 變數名{初始化值};
//簡單案例
struct CAR //結構體定義
{
char logo{ 'X'};
unsigned short whell{ 19 };
unsigned price{ 90000 };
};
CAR carA{'A',20,80000} //結構體變數初始化
std::cout<<carA::log<<std::endl; //結構體變數的使用
3)結構體使用
#include <iostream>
int main() {
struct Car //結構體類型的定義
{
char logo{ 'X' };
unsigned short whell{ 19 };
unsigned price{ 90000 };
};
Car carA{ 'X',25,5000000 }; //結構體類型變數的定義及初始化
Car carB{ 'Y',30,4000000 };
Car carC{ 'Z',15,200000 };
//結構體變數的使用
std::cout << "A車輛logo:" << carA.logo << ",A車輛輪子:" << carA.whell << ",A車輛售價:" << carA.price << std::endl;
std::cout << "B車輛logo:" << carB.logo << ",B車輛輪子:" << carB.whell << ",B車輛售價:" << carB.price << std::endl;
std::cout << "C車輛logo:" << carC.logo << ",C車輛輪子:" << carC.whell << ",C車輛售價:" << carC.price << std::endl;
}
2)結構體的本質
①結構體的本質是按照我們自己定義的方式定義一塊連續的記憶體的結構
②聲明一個結構體變數的本質是向電腦申請一塊記憶體,而這塊記憶體的大小,至少是我們定義的結構成員需要占用的記憶體之和(某些情況記憶體會虛高)
③使用結構體,則是按照我們定義好的方式從這塊記憶體讀取和寫入數據
8、案例:設計游戲角色數據
為麟江湖游戲設計角色的基本屬性,角色包括一下屬性:
①等級(1-100級)
②門派(武當、峨眉、少林、葵花、唐門)
③武器(0-15階,0-15強化),護甲(0-15階,0-15強化),首飾(0-15階,0-15強化)
④經驗值 ⑤生命值 ⑥生命最大值 ⑦內力值 ⑧內力最大值 ⑨坐標 ⑩金幣 ⑪ 鑽石 ⑫ 幸運值 ⑬ 累計消費
#include <iostream>
//門派定義
enum class SCHOOL :char {
wudang,
emei,
kuihua,
tangmen,
shaolin,
};
//裝備定義
struct Equip
{
unsigned char lv{ 0 }; //裝備等級
unsigned char ev{ 0 }; //裝備強化等級
};
//角色狀態定義
struct RoleState
{
int value{ 1000 }; //角色生命值
unsigned maxValue{ 1000 }; //角色最大生命值
};
//角色定義
struct Role {
unsigned char lv{ 1 }; //角色等級
SCHOOL school{ SCHOOL::tangmen }; //門派
Equip weapon{ 1,1 }; //武器等級、強化等級
Equip army{ 1,10 }; //布甲等級、強化等級
Equip neck{ 1,10 }; //
long long exp{ 0 };
RoleState HP{ 1000,1000 }; //角色血量、最大生命值
RoleState MP{ 1000,1000 }; //角色藍量、最大藍量
unsigned x{ 500 }; //橫坐標
unsigned y{ 500 }; //縱坐標
unsigned Money{ 1000 }; //金幣數
unsigned Diamond{ 100 }; //鑽石數
unsigned char luck{ 2 };//幸運值
unsigned vip_exp{ 0 }; //充值經驗
};
int main() {
Role user;
std::cout << "生命:" << user.HP.value << "/" << user.HP.maxValue << std::endl;
std::cout << "內力:" << user.MP.value << "/" << user.MP.maxValue << std::endl;
std::cout << "坐標:【" << user.x << "】【" << user.y << "】" << std::endl;
}