一、背景
马上过春节了,在家闲暇时间,看到了别人php写的一个命令行游戏,直接拿过来用c语音实现了一下哈。
二、相关知识
1、CLI颜色打印方法,使用printf控制就行,以下从网上收录了一些常用的颜色码:
打印格式为:
printf("\033[字背景颜色;字体颜色m字符串\033[0m");
40: 黑 30: 黑
41: 红 31: 红
42: 绿 32: 绿
43: 黄 33: 黄
44: 蓝 34: 蓝
45: 紫 35: 紫
46: 深绿 36: 深绿
47: 白色 37: 白色
2、CLI的控制码
\033[0m 关闭所有属性
\033[1m 设置高亮度
\03[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m -- \033[37m 设置前景色
\033[40m -- \033[47m 设置背景色
\033[nA 光标上移n行
\03[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\33[?25h 显示光标
三、实现
其实这个idea是网上参考的哦,梳理出来思路如下:
1、定义血量HP、魔法MP,勇士发动攻击则需要消耗MP;
2、战斗方式为回合制,勇士和恶龙分别选择攻击方式进行PK;
基础定义:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define HP_MAX 20
#define MP_MAX 20
#define LOGGREEN(fmt, args...) printf("\033[40;32m"fmt"\033[0m", ##args);
#define LOGYELLOW(fmt, args...) printf("\033[40;33m"fmt"\033[0m", ##args);
#define LOGBLUE(fmt, args...) printf("\033[40;36m"fmt"\033[0m", ##args);
#define LOGD(fmt, args...); printf(fmt, ##args);
#define LOGX(fmt, args...); offset += snprintf(msg + offset, 1000 - offset, fmt, ##args);
static char msg[1000] = {0};
static int offset = 0;
typedef enum cmd_enum
{
ROLE_YOU = 1,
ROLE_DRAGON = 2,
CMD_ENUM_MIN = '0',
CMD_ENUM_ATTACK = '1',
CMD_ENUM_POWER = '2',
CMD_ENUM_DODGE = '3',
CMD_ENUM_THUMP = '4',
CMD_ENUM_MAX,
} CMD_ENUM;
typedef struct instance_t
{
char name[16];
int role;
int dodge;
int hp;
int mp;
struct instance_t *peer;
} INSTANCE_T;
void dsp_usage()
{
LOGD("\n\n选项:\n");
LOGD("\t1.攻击:使用攻击需消耗1MP 伤害1HP\n");
LOGD("\t2.蓄力:使用蓄力可增加1MP 伤害0HP\n");
LOGD("\t3.闪避:使用躲闪需消耗0MP 伤害0HP 躲避攻击\n");
LOGD("\t4.重击:使用重击需消耗2MP 伤害2HP 防御无效\n");
}
int main(void)
{
char str_opt = 0;
int opt = 0;
int ret = 0;
void (*do_callback)(INSTANCE_T *pinst);
INSTANCE_T inst1 = {{0}, 0};
INSTANCE_T inst2 = {{0}, 0};
strcpy(inst1.name, "勇士");
inst1.hp = 10;
inst1.mp = 0;
inst1.peer = &inst2;
inst1.role = ROLE_YOU;
strcpy(inst2.name, "恶龙");
inst2.hp = 20;
inst2.mp = 3;
inst2.peer = &inst1;
inst2.role = ROLE_DRAGON;
srandom((unsigned int)time(NULL));
dsp_usage();
while ( (str_opt = getchar()) != EOF ) {
switch ( str_opt ) {
case CMD_ENUM_ATTACK:
do_attack(&inst1);
break;
case CMD_ENUM_POWER:
do_power(&inst1);
break;
case CMD_ENUM_DODGE:
do_dodge(&inst1);
break;
case CMD_ENUM_THUMP:
do_thump(&inst1);
break;
case 'q':
LOGD("Game over\n");
exit(0);
default:
continue;
}
switch ( (random() & 0x3) + '1' ) {
case CMD_ENUM_ATTACK:
do_attack(&inst2);
break;
case CMD_ENUM_POWER:
do_power(&inst2);
break;
case CMD_ENUM_DODGE:
do_dodge(&inst2);
break;
case CMD_ENUM_THUMP:
do_thump(&inst2);
break;
default:
break;
}
dsp_title(&inst1, &inst2);
dsp_usage();
}
LOGD("Game over\n");
exit(0);
}
四种攻击模式的实现:
void do_attack(INSTANCE_T *pinst)
{
LOGX("%s准备攻击,", pinst->name);
if ( 0 == pinst->mp ) {
LOGX("MP不足!\n");
return;
}
pinst->mp--;
if ( 0 == pinst->peer->dodge ) {
pinst->peer->hp--;
LOGX("发动攻击!造成掉血1点!\n");
}
else {
LOGX("我勒个去!攻击被%s闪避了!\n", pinst->peer->name);
}
pinst->peer->dodge = 0;
}
void do_power(INSTANCE_T *pinst)
{
LOGX("%s准备蓄力,", pinst->name);
pinst->mp++;
LOGX("MP:%d\n", pinst->mp);
}
void do_dodge(INSTANCE_T *pinst)
{
LOGX("%s准备闪避,", pinst->name);
pinst->dodge = 0;
LOGX("下回合生效!\n");
}
void do_thump(INSTANCE_T *pinst)
{
LOGX("%s准备大招,", pinst->name);
if ( pinst->role == ROLE_YOU ) {
if ( pinst->mp < 2 ) {
LOGX("MP不足!\n");
}
else {
if ( 0 == pinst->peer->dodge ) {
pinst->peer->hp -= 2;
LOGX("Avada Kedavra!!!!\n");
}
else {
LOGX("我勒个去!大招你也躲避了!\n");
}
pinst->mp = 0;
}
}
else {
if ( pinst->mp < 3 ) {
LOGX("巨龙在发呆...\n");
}
else {
LOGX("发动火焰吐吸!无法闪避!\n");
pinst->mp = 0;
pinst->peer->hp -= 4;
}
}
pinst->peer->dodge = 0;
}
最后,再做一个屏幕输出的显示。
void dsp_title(INSTANCE_T *pinst1, INSTANCE_T *pinst2)
{
int ix = 0;
printf("\033[2J");
LOGGREEN("+----------------------------------------+");
LOGGREEN("+----------------------------------------+\n");
LOGGREEN("| YOU HP: %2d: ", pinst1->hp);
for ( ix = 1; ix <= HP_MAX; ix++ ) {
if ( ix <= pinst1->hp ) {
LOGGREEN("=");
}
else {
LOGGREEN(" ");
}
}
LOGGREEN(" |");
LOGGREEN("| DRANGON HP: %2d: ", pinst2->hp);
for ( ix = 1; ix <= HP_MAX; ix++ ) {
if ( ix <= pinst2->hp ) {
LOGGREEN("=");
}
else {
LOGGREEN(" ");
}
}
LOGGREEN(" |\n");
LOGGREEN("| MP: %2d: ", pinst1->mp);
for ( ix = 1; ix <= MP_MAX; ix++ ) {
if ( ix <= pinst1->mp ) {
LOGGREEN("=");
}
else {
LOGGREEN(" ");
}
}
LOGGREEN(" |");
LOGGREEN("| MP: %2d: ", pinst2->mp);
for ( ix = 1; ix <= MP_MAX; ix++ ) {
if ( ix <= pinst2->mp ) {
LOGGREEN("=");
}
else {
LOGGREEN(" ");
}
}
LOGGREEN(" |\n");
LOGGREEN("+----------------------------------------+");
LOGGREEN("+----------------------------------------+\n");
LOGYELLOW("%s", msg);
offset = 0;
if ( pinst1->hp <= 0 ) {
exit(0);
LOGD("噢,你挂了!\n");
}
else if ( pinst2->hp <= 0 ) {
exit(0);
LOGD("恭喜勇士,你获得了胜利\n");
}
}
四、总结
巨龙AI明显不太够,玩家太强了哈哈!好吧,这是个有趣的自娱自乐游戏!
大家新村快乐、鸡年吉祥!
大家新村快乐、鸡年吉祥!