首页 linux下多线程扑克游戏框架

linux下多线程扑克游戏框架

举报
开通vip

linux下多线程扑克游戏框架linux下多线程扑克游戏框架 /* * rc.c * 文件描述: * 1)提供了linux下“升级”(北方常见的一种扑克玩法)游戏的框架。 * 2)库:glibc2.15;编译环境:gcc4.7.2;内核:3.8.4 * 3) 编译:gcc -pthread -DDEBUG -o rc rc.c * 作者:漂流骑士 * 发布时间:2013.4.3 */ #include #include #include #include #include #include #...

linux下多线程扑克游戏框架
linux下多线程扑克游戏框架 /* * rc.c * 文件描述: * 1)提供了linux下“升级”(北方常见的一种扑克玩法)游戏的框架。 * 2)库:glibc2.15;编译环境:gcc4.7.2;内核:3.8.4 * 3) 编译:gcc -pthread -DDEBUG -o rc rc.c * 作者:漂流骑士 * 发布时间:2013.4.3 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PLAYERCOUNT 4 #define PLAYED_CARDS_NO 4 #define PLAYING_WAITING 10 #define BUFFER_RECV 128 #ifdef DEBUG #define DPRINTF(s) printf s #else #define DPRINTF(s) #endif #define ERR_HANDLER(s) {perror s; exit(-1);} typedef enum { STAGE_HANPAI = 0, STAGE_CALC }stage_t; typedef struct barrier_hanpai_tag { int mailbox_hanpai; /*空闲标志。0为空闲,1为繁忙*/ pthread_mutex_t m_hanpai[2]; /*m_hanpai[0]与同步信号配套的互斥量 m_hanpai[1]确保喊牌期间运行控制线程(RC线程)首先执行*/ pthread_cond_t c_hanpai_P2RC; /*喊牌期间,玩家发给运行控制线程的同步信号*/ }barrier_hanpai_t, *barrier_hanpai_p; typedef struct barrier_calc_tag { int mailbox_calc; /*空闲标志。0为空闲,1为繁忙*/ pthread_mutex_t m_calc[2]; /*m_calc[0]与同步信号配套的互斥量 m_calc[1]确保出牌(计算)期间运行控制线程首先执行*/ pthread_cond_t c_calc_P2RC; /*计算期间,玩家发给运行控制线程的同步信号*/ }barrier_calc_t, *barrier_calc_p; typedef struct barrier_tag { int sqno; /*玩家序号*/ pthread_t player[PLAYERCOUNT]; global; /*确保运行控制线程每局均能首先运行*/ pthread_mutex_t m_ pthread_mutex_t m_interplayer; /*玩家线程间的互斥*/ pthread_cond_t c_RC2P; /*喊牌、计算期间,RC线程发给玩家线程的信号*/ pthread_cond_t c_ready_P2RC; /*每局牌开始时的同步*/ struct barrier_hanpai_tag barrier_hanpai; struct barrier_calc_tag barrier_calc; }barrier_t, *barrier_p; typedef void (*sighandler_t)(int); sigset_t signal_set; int repeatflag_hanpai = 1, repeatflag_calc = 1, quitflag = 0; int player_hanpai_decision = 0xca; char player_status_play = 0; char player_status_hanpai = 0; sigjmp_buf jmpbuf_hanpai[4]; sigjmp_buf jmpbuf_calc[4]; void hanpai(int counter, int sqno, barrier_p mybarrier) { char buffer[10]; /*若为第二次喊牌则采取激进策略*/ if(counter >= 1) { DPRINTF(("采取激进策略\n")); sleep(2); } else sleep(1); if(sqno == 0) { tcflush(fileno(stdin), TCIFLUSH); read(fileno(stdin), buffer, 10); } pthread_mutex_lock(&mybarrier->m_interplayer); player_status_hanpai |= 1 << sqno; //player_hanpai_decision = 0xaa; /* 0x00:没资格;0x11:喊牌; 0x10: 有资格但不喊 */ pthread_mutex_unlock(&mybarrier->m_interplayer); } int calculate(int sqno, barrier_p mybarrier) { char buffer[10]; DPRINTF(("玩家 %d 正在计算...\n", sqno)); sleep(1); if(sqno == 1) { tcflush(fileno(stdin), TCIFLUSH); read(fileno(stdin), buffer, 10); } if(sqno == 3) { tcflush(fileno(stdin), TCIFLUSH); read(fileno(stdin), buffer, 10); } pthread_mutex_lock(&mybarrier->m_interplayer); player_status_play |= 1 << sqno; pthread_mutex_unlock(&mybarrier->m_interplayer); return 0xff; } void sigrtmin_0(int signo) { printf("玩家 0 未及时喊牌,系统自动计算\n"); siglongjmp(jmpbuf_hanpai[0], 1); } void sigrtmin_1(int signo) { printf("玩家 1 未及时喊牌,系统自动计算\n"); siglongjmp(jmpbuf_hanpai[1], 1); } void sigrtmin_2(int signo) { 3 未及时喊牌,系统自动计算\n"); printf("玩家 siglongjmp(jmpbuf_hanpai[2], 1); } void sigrtmin_3(int signo) { printf("玩家 3 未及时喊牌,系统自动计算\n"); siglongjmp(jmpbuf_hanpai[3], 1); } void sigrtmax_0(int signo) { printf("玩家 0 太慢了,系统帮助计算\n"); siglongjmp(jmpbuf_calc[0], 1); } void sigrtmax_1(int signo) { printf("玩家 1 太慢了,系统帮助计算\n"); siglongjmp(jmpbuf_calc[1], 1); } void sigrtmax_2(int signo) { printf("玩家 2 太慢了,系统帮助计算\n"); siglongjmp(jmpbuf_calc[2], 1); } void sigrtmax_3(int signo) { printf("玩家 3 太慢了,系统帮助计算\n"); siglongjmp(jmpbuf_calc[3], 1); } void player_entry(void *barrier_param) { int sqno; int card; int err; int i; int counter = 0; int sig_number; pthread_t tid_temp; barrier_p mybarrier = (barrier_p) barrier_param; tid_temp = pthread_self(); sqno = ((mybarrier->player[0] == tid_temp) ? 0 : ((mybarrier->player[1] == tid_temp) ? 1 : ((mybarrier->player[2] == tid_temp) ? 2 : ((mybarrier->player[3] == tid_temp) ? 3 : 0xffff)))); if(sqno == 0xffff) { printf("未能确认玩家序号\n"); exit(-1); } DPRINTF(("玩家 %d 已被正确创建\n", sqno)); while(1) { /*响应退出*/ RUN_OR_QUIT: DPRINTF(("player %d jumped\n", sqno)); sigwait (&signal_set, &sig_number); if (sig_number == SIGUSR1) { DPRINTF(("player %d got signal\n", sqno)); pthread_mutex_lock(&mybarrier->m_global); err = pthread_cond_signal(&mybarrier->c_ready_P2RC); if(err != 0) ERR_HANDLER(("in player_entry: send signal to R&C")); pthread_mutex_unlock(&mybarrier->m_global); } /*喊牌*/ while(1) { pthread_mutex_lock(&mybarrier->barrier_hanpai.m_hanpai[1]); if(quitflag == 1) { pthread_mutex_unlock(&mybarrier->barrier_hanpai.m_hanpai[1]); goto RUN_OR_QUIT; } pthread_mutex_unlock(&mybarrier->barrier_hanpai.m_hanpai[1]); if(repeatflag_hanpai == 0) break; /*玩家不能在规定时间内喊牌,则强制退出喊牌*/ if(!sigsetjmp(jmpbuf_hanpai[sqno], 1)) { hanpai(counter, sqno, mybarrier); printf("玩家 %d 已做决定\n", sqno); } /*检测信号量是否被锁住(siglongjmp跳至此处时可能已经获得了互斥锁)*/ if(pthread_mutex_trylock(&mybarrier->m_interplayer) == EBUSY) pthread_mutex_unlock(&mybarrier->m_interplayer); else pthread_mutex_unlock(&mybarrier->m_interplayer); /*与RC线程同步运行速度*/ pthread_mutex_lock(&mybarrier->barrier_hanpai.m_hanpai[0]); while(mybarrier->barrier_hanpai.mailbox_hanpai == 1) { DPRINTF(("玩家 %d 正在等待信号\n", sqno)); err = pthread_cond_wait(&mybarrier->c_RC2P, &mybarrier->barrier_hanpai.m_hanpai[0]); DPRINTF(("in player_entry, err = %d, player %d\n", err, sqno)); if(err != 0) ERR_HANDLER(("HANPAI: pthread_cond_wait error, in player_entry")); } mybarrier->barrier_hanpai.mailbox_hanpai = 1; pthread_cond_signal(&mybarrier- >barrier_hanpai.c_hanpai_P2RC); DPRINTF(("玩家 %d 发送信号\n", sqno)); pthread_mutex_unlock(&mybarrier->barrier_hanpai.m_hanpai[0]); counter++; } counter = 0; /*打牌*/ while(1) { for(i = 0; i < PLAYED_CARDS_NO; i++) { DPRINTF(("waiting for m_calc[1]\n")); pthread_mutex_lock(&mybarrier->barrier_calc.m_calc[1]); pthread_mutex_unlock(&mybarrier- >barrier_calc.m_calc[1]); if(repeatflag_calc == 0) goto RUN_OR_QUIT; /*玩家不能在规定时间内出牌,则强制退出出牌过程*/ if(!sigsetjmp(jmpbuf_calc[sqno], 1)) { DPRINTF(("玩家 %d 开始计算\n", sqno)); card = calculate(sqno, mybarrier); printf("玩家 %d 计算完毕\n", sqno); } /*检测信号量是否被锁住(siglongjmp跳至此处时可能已经获得了互斥锁)*/ if(pthread_mutex_trylock(&mybarrier->m_interplayer) == EBUSY) pthread_mutex_unlock(&mybarrier->m_interplayer); else pthread_mutex_unlock(&mybarrier->m_interplayer); /*与RC线程同步运行速度*/ pthread_mutex_lock(&mybarrier->barrier_calc.m_calc[0]); while(mybarrier->barrier_calc.mailbox_calc == 1) { DPRINTF(("玩家 %d 正在等待信号\n", sqno)); err = pthread_cond_wait(&mybarrier->c_RC2P, &mybarrier->barrier_calc.m_calc[0]); DPRINTF(("in player_entry, err = %d, player %d\n", err, sqno)); if(err != 0) ERR_HANDLER(("CALC: pthread_cond_wait error, in player_entry")); } mybarrier->barrier_calc.mailbox_calc = 1; pthread_cond_signal(&mybarrier->barrier_calc.c_calc_P2RC); DPRINTF(("玩家 %d 发送信号\n", sqno)); pthread_mutex_unlock(&mybarrier->barrier_calc.m_calc[0]); } } } } /*检测玩家是否继续游戏*/ int goon_or_not(int *flag, char *buffer) { int playagainflag = 1; int count; while(1) { count = read(fileno(stdin), buffer, BUFFER_RECV); if(buffer[count - 1] == '\n') { if(count == 1) { if(*flag == 0) break; else { DPRINTF(("%d\n", __LINE__)); printf("error! input y(if yes) or n(if no)\n"); continue; } } else if(count == 2) { if(*flag == 0 && buffer[0] == 'y') { DPRINTF(("here, %d\n", __LINE__)); break; } else if(*flag == 0 && buffer[0] == 'n') { playagainflag = 0; return playagainflag; } else { DPRINTF(("%d\n", __LINE__)); printf("error! input y(if yes) or n(if no)\n"); continue; } } else { DPRINTF(("%d\n", __LINE__)); *flag = 0; printf("error! input y(if yes) or n(if no)\n"); continue; } } else { *flag = 1; continue; } } memset(buffer, '\0', BUFFER_RECV); *flag = 0; return playagainflag; } int calc_circle_result() { printf("本轮结果:玩家 1 获胜\n"); return 1; } void calcsuit() { printf("计算花色...\n"); } void help_slow_player(stage_t stg, char status, pthread_t *tid) { int i; int err; int signo_hanpai[PLAYERCOUNT] = {SIGRTMIN, SIGRTMIN+1, SIGRTMIN+2, SIGRTMIN+3}; int signo_calc[PLAYERCOUNT] = {SIGRTMAX, SIGRTMAX-1, SIGRTMAX- 2, SIGRTMAX-3}; DPRINTF(("处理慢速玩家\n")); switch(stg) { case STAGE_HANPAI: for(i = 0; i < PLAYERCOUNT; i++) { if(!((status >> i) & 1)) { printf("嘿,玩家 %d,别磨叽了\n", i); err = pthread_kill(tid[i], signo_hanpai[i]); if(err != 0) ERR_HANDLER(("HANPAI: send signal error, in main")); } } break; case STAGE_CALC: for(i = 0; i < PLAYERCOUNT; i++) { if(!((status >> i) & 1)) { printf("嘿,玩家 %d,别磨叽了\n", i); err = pthread_kill(tid[i], signo_calc[i]); if(err != 0) ERR_HANDLER(("HANPAI: send signal error, in main")); } } break; default: DPRINTF(("error, no such stage\n")); break; } } void deal() { printf("分牌...\n"); } sighandler_t signal_intr(int signo, sighandler_t func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif if(sigaction(signo, &act, &oact) < 0) return(oact.sa_handler); } void process_control_init(barrier_t *mybarrier) { int err = 0; err = pthread_mutex_init(&mybarrier->barrier_hanpai.m_hanpai[0], NULL); if(err != 0) ERR_HANDLER(("initilize m_hanpai[0] error")); err = pthread_mutex_init(&mybarrier->barrier_hanpai.m_hanpai[1], NULL); if(err != 0) ERR_HANDLER(("initilize m_hanpai[1] error")); err = pthread_cond_init(&mybarrier->barrier_hanpai.c_hanpai_P2RC, NULL); if(err != 0) ERR_HANDLER(("initilize c_hanpai_P2RC error")); err = pthread_mutex_init(&mybarrier->barrier_calc.m_calc[0], NULL); if(err != 0) ERR_HANDLER(("initilize m_calc[0] error")); err = pthread_mutex_init(&mybarrier->barrier_calc.m_calc[1], NULL); if(err != 0) ERR_HANDLER(("initilize m_calc[1] error")); err = pthread_cond_init(&mybarrier->barrier_calc.c_calc_P2RC, NULL); if(err != 0) ERR_HANDLER(("initilize c_calc_P2RC error")); err = pthread_mutex_init(&mybarrier->m_global, NULL); if(err != 0) ERR_HANDLER(("initilize m_global error")); err = pthread_mutex_init(&mybarrier->m_interplayer, NULL); if(err != 0) ERR_HANDLER(("initilize m_interplayer error")); err = pthread_cond_init(&mybarrier->c_RC2P, NULL); if(err != 0) ERR_HANDLER(("initilize c_RC2P error")); err = pthread_cond_init(&mybarrier->c_ready_P2RC, NULL); if(err != 0) ERR_HANDLER(("initilize c_ready_P2RC error")); mybarrier->barrier_hanpai.mailbox_hanpai = 0; mybarrier->barrier_calc.mailbox_calc = 0; } int main(int argc, char **argv) { char rcvbuffer[BUFFER_RECV] = {'\0'}; ssize_t count; err; int int i, j, circle = 0; int preparedno_ready = 0; int preparedno_hanpai = 0; int preparedno_calc = 0; int winner; int temp; int hanpaipno = 0; int dealflag = 1; int badluckcounter = 0, negativecounter = 0; int totaljuno = 0; int rcvbufferflag = 0; int *retval; sigset_t signal_set_old; stage_t stage; barrier_t barrier; printf("\n********************************************\n"); printf("*All work and no play makes Jack a dull boy*\n"); printf("*Enjoy yourself *\n"); printf("********************************************\n"); process_control_init(&barrier); sigemptyset(&signal_set); sigaddset(&signal_set, SIGUSR1); err = pthread_sigmask(SIG_BLOCK, &signal_set, &signal_set_old); if (err != 0) ERR_HANDLER(("Set signal mask")); signal_intr(SIGRTMIN, &sigrtmin_0); signal_intr(SIGRTMIN+1, &sigrtmin_1); signal_intr(SIGRTMIN+2, &sigrtmin_2); signal_intr(SIGRTMIN+3, &sigrtmin_3); signal_intr(SIGRTMAX, &sigrtmax_0); signal_intr(SIGRTMAX-1, &sigrtmax_1); signal_intr(SIGRTMAX-2, &sigrtmax_2); signal_intr(SIGRTMAX-3, &sigrtmax_3); pthread_mutex_lock(&barrier.barrier_calc.m_calc[0]); pthread_mutex_lock(&barrier.barrier_calc.m_calc[1]); pthread_mutex_lock(&barrier.barrier_hanpai.m_hanpai[0]); pthread_mutex_lock(&barrier.barrier_hanpai.m_hanpai[1]); for(i = 0; i < PLAYERCOUNT; i++) { err = pthread_create(&barrier.player[i], NULL, (void *)player_entry, (void *)&barrier); if(err != 0) ERR_HANDLER(("create player thread error")); } sleep(1); while(1) { /*同步初始进度*/ pthread_mutex_lock(&barrier.m_global); for(i = 0; i < PLAYERCOUNT; i++) { pthread_kill(barrier.player[i], SIGUSR1); err = pthread_cond_wait (&barrier.c_ready_P2RC, &barrier.m_global); if (err != 0) ERR_HANDLER( ("Wait for player ready")); } pthread_mutex_unlock(&barrier.m_global); if(totaljuno != 0) pthread_mutex_lock(&barrier.barrier_calc.m_calc[1]); /*分牌,喊牌*/ stage = STAGE_HANPAI; while(1) { if(dealflag == 1) deal(); printf("请各玩家喊牌\n"); pthread_mutex_unlock(&barrier.barrier_hanpai.m_hanpai[1]); /*等待玩家喊牌结束*/ for(i = 0; i < PLAYING_WAITING; i++) { sleep(1); /*若所有玩家均已做出决定,则不再等待*/ if(player_status_hanpai == 0xf) break; } player_status_hanpai = 0xe; /*此处为演示本程序的效果而设置,可更改*/ if(player_status_hanpai != 0xf) help_slow_player(stage, player_status_hanpai, barrier.player); /*与玩家线程同步速度*/ while(preparedno_hanpai < PLAYERCOUNT) { if(preparedno_hanpai == 0) _lock(&barrier.barrier_hanpai.m_hanpai[1]); pthread_mutex err = pthread_cond_wait(&barrier.barrier_hanpai.c_hanpai_P2RC, &barrier.barrier_hanpai.m_hanpai[0]); if(err != 0) ERR_HANDLER(("HANPAI: pthread_cond_wait error, in main")); barrier.barrier_hanpai.mailbox_hanpai = 0; if(preparedno_hanpai < PLAYERCOUNT - 1) pthread_cond_signal(&barrier.c_RC2P); preparedno_hanpai++; DPRINTF(("控制线程接收到 %d 个信 号\n", preparedno_hanpai)); } preparedno_hanpai = 0; player_hanpai_decision = 0xc0; /*此处模拟各玩家喊牌情况*/ /*若连续3次四个玩家均无资格喊牌,退出。*/ if(player_hanpai_decision == 0x0) { badluckcounter++; if(badluckcounter >= 3) { printf("咦,今天运气怎么这么差,~休息一下再来玩吧:-)\n"); pthread_mutex_unlock(&barrier.barrier_hanpai.m_hanpai[1]); quitflag = 1; goto BYE; } printf("各玩家均无喊牌资格,重新发牌...\n"); continue; } for(i = 0; i < PLAYERCOUNT; i++) { temp = (player_hanpai_decision >> (i * 2)) & 0x3; DPRINTF(("temp = %x\n", temp)); if(temp == 0x3) { hanpaipno++; printf("玩家 %d 喊牌: %s\n", i, "joker"); } } /*若连续3次四个玩家均消极喊牌,退出。*/ if(hanpaipno == 0) { negativecounter++; if(negativecounter >= 3) { printf("大家太消极了,下次再玩吧\n"); quitflag = 1; pthread_mutex_unlock(&barrier.barrier_hanpai.m_hanpai[1]); goto BYE; } printf("没有玩家喊牌。请有资格的玩家积极喊牌\n"); dealflag = 0; continue; } else { repeatflag_hanpai = 0; pthread_mutex_unlock(&barrier.barrier_hanpai.m_hanpai[1]); break; } } negativecounter = 0; badluckcounter = 0; dealflag = 1; hanpaipno = 0; calcsuit(); printf("主牌花色已确定\n"); printf("\n开战~~~\n"); /*运行每局牌*/ stage = STAGE_CALC; while(1) { printf("\n\n第 %d 轮...\n", circle++); /*同步每轮的 4 次计算*/ for (j = 0; j < PLAYED_CARDS_NO; j++) { pthread_mutex_unlock(&barrier.barrier_calc.m_calc[1]); /*给玩家 15s 的出牌时间*/ for(i = 0; i < 5; i++) { /*这里为缩短演示时间,修改为5s*/ sleep(1); /*若出牌玩家已经出牌,则不再等待*/ if(player_status_play == 0xf) break; } player_status_play = 0x5; if(player_status_play != 0xf) help_slow_player(stage, player_status_play, barrier.player); /*与玩家线程同步速度*/ while(preparedno_calc < PLAYERCOUNT) { if(preparedno_calc == 0) pthread_mutex_lock(&barrier.barrier_calc.m_calc[1]); err = pthread_cond_wait(&barrier.barrier_calc.c_calc_P2RC, &barrier.barrier_calc.m_calc[0]); if(err != 0) ERR_HANDLER(("CALC: pthread_cond_wait error, in main")); barrier.barrier_calc.mailbox_calc = 0; if(preparedno_calc < PLAYERCOUNT - 1) pthread_cond_signal(&barrier.c_RC2P); preparedno_calc++; DPRINTF(("控制线程接收到 %d 个信号\n", preparedno_calc)); } preparedno_calc = 0; printf("所有玩家计算完毕, 玩家已出牌\n"); } /*计算本轮赢家*/ winner = calc_circle_result(); if(circle == 3) { repeatflag_calc = 0; pthread_mutex_unlock(&barrier.barrier_calc.m_calc[1]); break; } } circle = 0; pthread_mutex_lock(&barrier.barrier_hanpai.m_hanpai[1]); printf("Go on playing?(y/n). Press Enter key directly if continue\n"); tcflush(fileno(stdin), TCIFLUSH); if(goon_or_not(&rcvbufferflag, rcvbuffer) == 0) break; repeatflag_hanpai = 1; repeatflag_calc = 1; totaljuno++; } BYE: printf("R&C say bye to players\n"); for(i = 0; i < PLAYERCOUNT; i++) { pthread_cancel(barrier.player[i]); pthread_join(barrier.player[i], (void **)&retval); if(retval == PTHREAD_CANCELED) DPRINTF(("thread %d exit\n", i)); } pthread_mutex_unlock(&barrier.barrier_hanpai.m_hanpai[1]); pthread_mutex_unlock(&barrier.barrier_calc.m_calc[0]); pthread_mutex_unlock(&barrier.barrier_calc.m_calc[1]); pthread_mutex_unlock(&barrier.barrier_hanpai.m_hanpai[0]); exit(0); }
本文档为【linux下多线程扑克游戏框架】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_321575
暂无简介~
格式:doc
大小:61KB
软件:Word
页数:0
分类:企业经营
上传时间:2017-11-11
浏览量:7