题目:
思路:
27张牌,分成3行,每行9张。对于这随机生成的27张牌,每个牌设置一个属性cv:被选中的次数。
初始27张牌每张牌的被选中次数为 0 ;
第一***作:
三行中被选中行的牌的次数+1,此时有9张牌的cv是1,28张牌的cv是0
第二***作:
将cv为1的牌平均分成3行,剩下的随意放置,再次让用户选择,此时被选中的行的牌的次数+1,此时有3张牌的cv是2,其余牌的cv<2。
第三***作:
将3张cv是2的牌平均分成3行,其余的随意放置,再次让用户选择,此时被选中的行的牌的次数+1,此时有1张牌的cv是3,其余牌的cv<3。这张牌就是用户选中的牌。
代码:
#include <stdio.h>
#include <time.h>
#include<stdlib.h>
struct poker{
int val ; // 1(A),2,3,4,5,6,7,8,9,10,11(J),12(Q),13(K)
int kind ; // 0 , 1 , 2 , 3
int is_joker ; // 0不是王, 1小王,2大王
int cv ; // 被选中次数
};
const char kind_name[5][20] = { " ", "Spade", "Heart", "Diamond", "Club" } ; // 黑,红,片,花
const char val_name[20][3] = { " ", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" } ;
int history_num = 0 ; // 一共玩了多少轮游戏
int pos[4][20] ; // 此次输出每个位置的扑克是哪一张
poker history[100] ; // 记录每次游戏的选择
poker card[27] ; // 被选出的27张扑克
poker card_list[54] ; // 所有54张扑克
void printPoker( struct poker p ) { // 输出扑克p信息
if ( p.is_joker == 1 ) { // 是小王
printf( "joker 1 " ) ;
}
else if ( p.is_joker == 2 ) { // 是大王
printf( "JOKER 2 " ) ;
}
else { // 其他牌
printf("%s %s ", kind_name[p.kind], val_name[p.val] ) ;
}
}
void outInfermation() { // 输出个人信息
int T=100;
while ( T-- ) { // 输出上边框
printf( "*" ) ;
}
printf("\n姓名:%s\t学号:%s\t班级:%s\t完成时间:", "小明","222018????","通信工程一班" ) ;
time_t timep; time (&timep); printf("%s\n",ctime(&timep)); // 输出当前时间
T = 100 ;
while ( T-- ) { // 输出下边框
printf( "*" ) ;
}
printf( "\n" ) ;
}
void outMenu() { // 输出功能菜单
printf( "\n\n\n\*****************游戏菜单*********************************\n" ) ;
printf( "1.开始游戏\n" ) ;
printf( "2.查看历史记录\n" ) ;
printf( "3.退出游戏\n" ) ;
printf( "**********************************************************\n\n" ) ;
}
void outHistory() { // 输出历史记录(每次游戏用户选中的牌)
int i;
if ( history_num == 0 ) {
printf( "历史记录为空\n" ) ;
}
for (i=0; i<history_num; i++ ) {
printf( "第%d次游戏玩家选择的扑克是:", i+1 ) ;
printPoker( history[i] ) ;
printf( "\n" ) ;
}
}
void Init() { // 初始化信息
history_num = 0 ; // 历史记录清零
int i, j, n=0 ;
for (i=1; i<=4; i++) { // 为card_list数组的52张牌初始化
for (j=1; j<=13; j++) {
card_list[n].val = j ;
card_list[n].kind = i ;
card_list[n].is_joker = 0 ;
card_list[n].cv = 0 ;
n++ ;
}
}
card_list[n].cv = 0 ; card_list[n++].is_joker = 1 ; // 小王
card_list[n].cv = 0 ; card_list[n++].is_joker = 2 ; // 大王
for(i=0;i<54;i++){
printPoker( card_list[i] ) ;
}
}
void creatCardList() { // 随机从54张牌中选出27张,被选出的牌存在card数组中
//每次选择的策略为:随机生成一个数字x,从当前余剩的牌中,数到第x张牌,就是此次被选中的牌。重复27次即可
int vis[54] = {0}, i, j, rest = 54 ;
for (i=0; i<27; i++) { // 进行27次选择
int pos = rand()%rest, now = 0 ;
for (j=0; j<54; j++) {
if ( now == pos && vis[j]==0 ) { // 数到了第pos张牌
break ;
}
if ( vis[j] == 0 ) { // 该牌未被选择
now++ ;
}
}
vis[j] = 1 ; // 标记次张牌已被选中
card[i] = card_list[j] ; // 把这张牌放入选中的27张牌中
rest-- ;
}
}
poker getCard( int turn , int num ) { // 猜用户选中的扑克牌(turn 表示是第几轮猜牌,num表示这一轮每行需要放置多少张cv值为turn-1的牌 )
int i, j, k=0 ;
printf( "第%d轮游戏开始!\n", history_num+1 ) ;
printf( "第%d波筛选:\n" , turn ) ;
///按照规则放置扑克(3行,每行只能放num张choose_cnt值为turn-1的牌)
int vis[27] = {0} ; // vis[i]表示第i张牌是否已经为其分配位置
for (i=1; i<=3; i++) {
int rest = num , rest2 = 9-num ; // 当前行还需要放rest张cv值为turn-1的牌,还需要放rest2张cv值小于turn-1的牌
k = 0 ; // k表示当前第i行已经放了多少张牌
for (j=0; j<27; j++) { // 考察第j张牌是否可以放入第i行
if ( vis[j] == 1 ) continue ;
if ( card[j].cv == turn-1 ) { // vc==true-1的牌
if ( rest>0 ) {
k++ ;
pos[i][k] = j ;
vis[j] = 1 ;
rest--;
}
}
else { // vc<true-1的牌
if ( rest2>0 ) {
k++;
pos[i][k] = j ;
vis[j] = 1 ;
rest2--;
}
}
}
}
///输出摆放情况并等待用户选择
printf( "请从下列扑克中选出一张,并输入它的所在行数\n" ) ;
for (i=1; i<=3; i++) {
printf( "# line %d : ", i ) ;
for (j=1; j<=9; j++) {
printPoker( card[pos[i][j]] ) ;
printf(" ");
}
printf("\n");
}
int choose_line = 0 ;
scanf( "%d", &choose_line ) ;
/// 标记被选中的行数的扑克
for (i=1; i<=9; i++) {
card[ pos[choose_line][i] ].cv++ ;
}
///返回答案
if ( turn == 3 ) { // 如果是最后一轮就返回标记次数为3的唯一一张牌
for (i=0; i<27; i++) {
if ( card[i].cv == 3 ) return card[i] ;
}
}
else { // 否则继续进行下一轮游戏
return getCard( turn+1 , num/3 ) ;
}
}
poker playGame() { // 玩游戏
creatCardList(); // 随机选出27个卡片
struct poker ret ;
ret = getCard( 1 , 9 ) ; // 进行第一轮游戏
return ret ;
}
int main()
{
outInfermation(); // 输出个人信息
Init(); // 扑克信息初始化
int op = 0 ;
while ( op != 3 ) {
outMenu(); // 输出功能菜单
scanf( "%d", &op ) ;
if ( op == 1 ) { // 开始游戏
history[history_num] = playGame() ;
printf("游戏结束:\n你选择的扑克是:");
printPoker( history[history_num] ) ;
printf( "\n" ) ;
history_num++ ;
}
else if ( op == 2 ) { // 输出历史游戏信息
outHistory();
}
else if ( op == 3 ) { // 退出游戏
return 0 ;
}
else { // 输入不合法
printf( "输入功能标号不合法,请重新输入:\n" ) ;
}
}
return 0;
}