用到多线程的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 PLAYERCOUNT4

#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];

pthread_mutex_t m_global;/*确保运行控制线程每局均能首先运行*/

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)

{

printf("玩家 3 未及时喊牌,系统自动计算\n");

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;

#ifdefSA_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;

int err;

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)

pthread_mutex_lock(&barrier.barrier_hanpai.m_hanpai[1]);

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);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值