linux 剪刀石头布c语言,C语言小游戏:剪刀石头布

#include

#include

#include

/*

游戏规则表,以游戏人类玩家为基准,1代表胜利,0代表平局,-1代表失败,具体逻辑如下所示:

+------+------+------+----+

|      | 剪刀 | 石头 | 布 |

+------+------+------+----+

| 剪刀 |  平  |  败  | 胜 |

+------+------+------+----+

| 石头 |  胜  |  平  | 败 |

+------+------+------+----+

| 布   |  败  |  胜  | 平 |

+------+------+------+----+

*/

const char game[3][3] =

{

{ 0,-1,1 },

{ 1,0,-1 },

{ -1,1,0 }

};

/*

这是游戏的打印信息,通过查表输出道具名称

*/

const char *mess[5] = { "剪刀","石头","布" ,"炸弹","护身符" };

/*

卡牌信息,总共30张牌,剪刀,石头,布各10张,将在init函数中进行初始化

*/

char cards[30];

/*

player1表示人类玩家,player2表示电脑玩家。

这是一个数组,其中索引0保存剪刀牌的数量,索引1保存石头牌的数量,索引2保存布牌数量,索引3保存炸弹牌数量,索引4保存护身符牌数量

*/

char player1[5];

char player2[3];

/*

初始化卡牌信息,逻辑如下:

设定一个30次的循环,每一次循环体里面,都将循环次数除以3,并把结果赋值给数组的某个索引。

由于是整型除法,i小于10,结果为0,表示剪刀;i大于10,小于20,结果为1,表示石头;i大于20,小于30,结果为2,表示布。

洗牌逻辑如下:

1.以当前时间为随机数种子,初始化随机数

2.设定100次的循环次数

3.每次循环,获取a和b两个随机数,用整数30取模后,作为数组索引把卡组的两处牌交换

*/

void init_cards()

{

int a, b, c, i;

for (i = 0; i<30; i++)

cards[i] = i / 10;

srand((unsigned int)time(NULL));

for (i = 0; i<100; i++)

{

a = rand() % 30;

b = rand() % 30;

c = cards[a];

cards[a] = cards[b];

cards[b] = c;

}

}

/*

发牌函数,前15张给玩家1,后15张给玩家2。

*/

void give_cards()

{

int a, i;

for (i = 0; i<15; i++)

{

a = cards[i];

player1[a]++;

}

player1[3] = 3;

player1[4] = 3;

for (i = 15; i<30; i++)

{

a = cards[i];

player2[a]++;

}

}

/*

获取玩家1出的牌,可以出示的牌,分别是剪刀,石头,布和炸弹,对应编号分别是1,2,3,4.

当输入1,2,3,4以外的数字时,会报输入信息错误

如果输入为合法信息,则判断对应牌信息是否为0,为0则提示玩家没有这张牌,并让玩家重新输入

由于输入的是字符串,在ascii码中,0到9的十六进制码分别是0x30到0x39,所以返回的时候减去0x31

*/

char get_player1_card()

{

char card=0;

//while (card = getchar())

while(card!=EOF)

{

scanf("%c",&card);

fflush(stdin);//fflush()函数,包含于stdio.h 此处为清空输入缓冲区

if (card != '1' && card != '2' && card != '3' && card != '4')

{

printf("输入错误,请重新出牌\n");

continue;

}

if (player1[card - 0x31] <= 0)

{

printf("你没有这张牌,请重新出牌\n");

continue;

}

break;

}

return card - 0x31;

}

/*

玩家2出牌,由于玩家2是电脑玩家,出牌通过随机数推进,过程与玩家1出牌类似

*/

char get_player2_card()

{

char card;

while (card = rand() % 3)

{

if (card != 0 && card != 1 && card != 2)

{

continue;

}

if (player1[card] <= 0)

{

continue;

}

break;

}

return card;

}

/*

护身符牌,当玩家1遇到失败或者平局时,如果玩家1拥有护身符牌,则会自动询问是否使用护身符牌,如果选择是,则消耗一张护身符牌,把失败的牌拿回手中。

*/

void amulet(char card)

{

char ch;

if (player1[4] > 0)

{

printf("你有%d张护身符,是否使用?(y/N)\n", player1[4]);

a:

scanf("%c",&ch);

fflush(stdin);//fflush()函数,包含于stdio.h 此处为清空输入缓冲区

if (ch == 'y' || ch == 'Y')

{

player1[card]++;

player1[4]--;

getchar();

}

else if (ch == 'n' || ch == 'N')

{

getchar();

}

else

{

if (ch == '\n')

return;

printf("输入错误,请重新输入!\n");

goto a;

}

}

}

/*

运行游戏,在运行前,先初始化游戏信息,包括洗牌和发牌。

游戏开始时,先获取双方出的牌,如果玩家1出了炸弹,则这一局按平局算

如果玩家1遇到失败或者平局,当手上有护身符牌时,会询问是否使用,如果玩家1选择使用,则可把失败的那一张牌拿回,并消耗一张护身符牌

当任意一方的牌数为0时,则那一方算失败方

*/

void run_game()

{

char a, b;

init_cards();

give_cards();

printf("你剩余15张牌\n");

printf("对方剩余15张牌\n");

printf("\n");

while (1)

{

printf("剪刀:%d\n", player1[0]);

printf("石头:%d\n", player1[1]);

printf("布:%d\n", player1[2]);

printf("炸弹:%d\n", player1[3]);

printf("护身符:%d\n", player1[4]);

printf("\n");

printf("请出牌:\n");

printf("\t1.剪刀\n");

printf("\t2.石头\n");

printf("\t3.布\n");

printf("\t4.炸弹\n");

a = get_player1_card();

b = get_player2_card();

system("cls");

printf("%s vs %s\n", mess[a], mess[b]);

if (a == 3)

{

player1[a]--;

player2[b]--;

printf("你使用了炸弹!\n");

goto a;

}

switch (game[a][b])

{

case -1:

player1[a]--;

printf("败!\n");

amulet(a);

break;

case 0:

player1[a]--;

player2[b]--;

printf("平!\n");

amulet(a);

break;

case 1:

player2[b]--;

printf("胜!\n");

break;

default:

break;

}

a:

a = player1[0] + player1[1] + player1[2];

b = player2[0] + player2[1] + player2[2];

if (a <= 0)

{

printf("你输了!\n");

break;

}

else if (b <= 0)

{

printf("你赢了!\n");

break;

}

else

{

printf("\n");

printf("你剩余%d张牌\n", a);

printf("对方剩余%d张牌\n", b);

printf("\n");

}

}

}

/*

main函数,游戏的入口函数

*/

int main()

{

run_game();

system("pause");

return 0;

}

个人编译环境

win10 MinGW+codeblocks c99

已知的部分问题:

1、for函数内声明变量c99及之前的编译器可能不支持。

2、读取用户输入的卡片序号及用户输入的护身符y\n有复数不正确字符时会出现各种情况,之后会存在缓冲区字符滞留问题。

修改了问题1相关部分。

问题2只改动部分,选择了scanf函数读入字符并使用stdio.h包含的fflush()函数一定程度缓解字符缓冲滞留问题(百度真是个好东西),但是错误、复数字符导致的错误识别这方面,相关代码恕个人太菜,没有更好的解决方式,也许可以用switch case语句进行输入识别解决。

其他方面的优化因个人水平,无法给出更可靠的建议。

但是fflush()函数于不同编译器有不同作用方式,也可以使用while函数不断循环读取的方式解决····(好麻烦的感觉)

[此贴子已经被作者于2018-9-4 11:23编辑过]

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值