⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpg.c

📁 用共享内存
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <pthread.h>
#include <time.h> 

pthread_mutex_t  lock=PTHREAD_MUTEX_INITIALIZER;
int APmid,peomid,boutmid,def_mid;
int * pAP,*pp,*pn,i;
float *pd;
const int attack=100,develop=50; 

void ACT_Attack(int country_num);          //攻击线程
void ACT_Defend(int country_num);     //防御线程
void ACT_Develop(int country_num);    //发展线程

int  init( );                              //信号灯初始化程序
void p( int );                       //信号灯实现的P操作
void v( int );                            //信号灯实现的V操作

union semun {
         int              val;    /* Value for SETVAL */
         struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
         unsigned short  *array;  /* Array for GETALL, SETALL */
         struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux specific) */
};

int main() { 
	int attack=100,develop=50; 
	float defend=0.2;
    int status;
	pthread_t AttackThread,DefendThread,DevelopThread;

	printf("\n模拟开始!\n\n");
    printf("初始状态(三国相同):兵力300,攻击力100,防御力0.2(防御20%的伤害),发展能力50\n\n ");


    //建立共享内存
	APmid = shmget(0x911, 3*4, IPC_CREAT|0600 ); 
	pAP = (int *)shmat( APmid, NULL, 0 );            //每回合的行动点数

	peomid= shmget( 0x985, 3*4, IPC_CREAT|0600 );
	pp=(int *)shmat( peomid, NULL, 0 );       //每个进程的兵力

	boutmid=shmget( 0x995, 3*4, IPC_CREAT|0600 );  //回合数
	pn=(int *)shmat( boutmid, NULL, 0 );
	
	def_mid=shmget( 0x923, 3*sizeof(float), IPC_CREAT|0600 );
	pd=(float *)shmat( def_mid, NULL, 0 );      //每个进程的防御力

	for(i=0;i<3;i++) //共享内存初始化
	{
		*(pAP+i)=10,*(pp+i)=300;
		*(pd+i)=0.2;
		*(pn+i)=0;
	} 

	int pid1,pid2; pid1=fork();                //生成子进程
	if(pid1==0) pid2=fork();         //生成孙进程
 
	int  semid;
    semid = init( );             //初始化信号灯


	while((*pp)*(*(pp+1))+(*pp)*(*(pp+2))+(*(pp+1))*(*(pp+2))!=0) //当有2个国家以上兵力不为0时
	{
		for(i=0;i<3;i++) *(pAP+i)=10;	   //初始化每回合的行动点数

		if(pid1!=0 )
	    {

 	       p( semid );
			while(*pAP>=1 && (*pp)!=0  )
		   {   
			pthread_create( &AttackThread, NULL,(void *)&ACT_Attack, (void *)0 );
			if(*(pd)<0.5)pthread_create( &DefendThread, NULL,(void *)&ACT_Defend, (void *)0 );
			pthread_create( &DevelopThread, NULL,(void *)&ACT_Develop, (void *)0 );

			
			// 等待线程结束
			pthread_join( AttackThread, NULL );
			if(*(pd)<0.5)pthread_join( DefendThread, NULL );
			pthread_join( DevelopThread, NULL );
		    }
            

			if ((*pp)!=0) printf("**魏行动结束\n\n");
			else printf("\n魏国已亡!\n\n");
			(*pn)++;
//			 printf("pn=%d\n",*pn);
			 v( semid );
	     }
		 else if(pid2!=0 )
		{
	
		   p( semid );
			while(*(pAP+1)>=1 && (*(pp+1))!=0 )
		   {   
			pthread_create( &AttackThread, NULL,(void *)&ACT_Attack, (void *)1 );
			if(*(pd+1)<0.5)pthread_create( &DefendThread, NULL,(void *)&ACT_Defend, (void *)1 );
			pthread_create( &DevelopThread, NULL,(void *)&ACT_Develop, (void *)1 );
	
			// 等待线程结束
			pthread_join( AttackThread, NULL );
			if(*(pd+1)<0.5)pthread_join( DefendThread, NULL );
			pthread_join( DevelopThread, NULL );
	       }
     		if ((*(pp+1))!=0) printf("**蜀行动结束\n\n");
			else printf("\n蜀国已亡!\n\n");
			(*(pn+1))++;
//			 printf("pn+1=%d\n",*(pn+1));
            v( semid );
	     }
	     else
	    {          
		   p( semid );
           while (*(pAP+2)>=1 && (*(pp+2))!=0)
		  {		
		    pthread_create( &AttackThread, NULL,(void *)&ACT_Attack, (void *)2 );
	   		if(*(pd+2)<0.5)pthread_create( &DefendThread, NULL,(void *)&ACT_Defend, (void *)2 );
			pthread_create( &DevelopThread, NULL,(void *)&ACT_Develop, (void *)2 );

			
			// 等待线程结束
			pthread_join( AttackThread, NULL );
			if(*(pd+2)<0.5)pthread_join( DefendThread, NULL );
			pthread_join( DevelopThread, NULL );
 		   }
       		if ((*(pp+2))!=0) printf("**吴国行动结束\n\n");
			else printf("\n吴国已亡!\n\n");
		   (*(pn+2))++;
//		   printf("pn+2=%d\n",*(pn+2));
	        v( semid );
		 }
//        printf("pn=%d,pn+1=%d,pn+2=%d\n",*pn,*(pn+1),*(pn+2));
	    
		if((*pp)*(*(pp+1))+(*pp)*(*(pp+2))+(*(pp+1))*(*(pp+2))!=0)   //此if防止陷入死循环
		{
		   while((*pn>*(pn+1) || *pn>*(pn+2)) && pid1!=0);      //3个循环用来同步进程
		   while((*(pn+1)>*pn || *(pn+1)>*(pn+2)) && (pid1==0 && pid2!=0));
           while((*(pn+2)>*pn || *(pn+2)>*(pn+1)) && (pid1==0 && pid2==0));
        }
		if(*pn==*(pn+1) && *pn==*(pn+2)){                    //每回合结束
			printf("第%d回合结束!\n",*pn);
			printf("魏兵力:%d,蜀兵力:%d,吴兵力:%d\n",*pp,*(pp+1),*(pp+2));
			printf("------------------------------------\n\n");
		}
	}
	while( wait( &status ) != -1 );  //等待所有子进程结束
	
	if(*pp>0 && pid1!=0) printf("*************魏国统一了三国!**********\n");
	else if (*(pp+1)>0 && pid1!=0) printf("*************蜀国统一了三国!**********\n");
	else if (*(pp+2)>0 && pid1!=0) printf("*************吴国统一了三国!**********\n");

	
  // 释放共享内存
  shmdt( pn );
  shmctl( boutmid, IPC_RMID, 0 );  
  shmdt( pp );
  shmctl( peomid, IPC_RMID, 0 );  
  shmdt( pd );
  shmctl( def_mid, IPC_RMID, 0 );  
  shmdt( pAP );
  shmctl( APmid, IPC_RMID, 0 );
  
  //删除信号灯
  semctl( semid, 0, IPC_RMID, 0 );                              
  
	if(pid1!=0)printf("\n模拟结束!\n");

}


void ACT_Attack(int country_num)
{
	if(*(pAP+country_num)<1)return;
	if((*pp)*(*(pp+1))+(*pp)*(*(pp+2))+(*(pp+1))*(*(pp+2))==0)    //此if防止死循环
	{
		pthread_mutex_lock( &lock );       //锁住互斥锁
	    *(pAP+country_num)-=1;
	    pthread_mutex_unlock( &lock );        //解锁互斥锁
		return ;
	}
    pthread_mutex_lock( &lock );              //锁住互斥锁
	int aim;

//    srand((int)time(0));              //设置随机种子
    do{ aim=rand()%3; }while(aim==country_num || *(pp+aim)==0);      //随机攻击对像
	switch(country_num)
	{
		case 0: printf("魏攻击"); break;
		case 1: printf("蜀攻击"); break;
		case 2: printf("吴攻击"); break;
	}
	switch(aim)
	{
		case 0: printf("魏。魏"); break;
		case 1: printf("蜀。蜀"); break;
		case 2: printf("吴。吴"); break;
	}
	int damage;                            //计算伤害值
	damage= attack * (1-*(pd+aim));
    
	*(pp+aim)-=damage;
    if(*(pp+aim)<0) *(pp+aim)=0;
	
	printf("伤亡%d万,其现在兵力为%d.\n",damage,*(pp+aim));
    
	*(pAP+country_num)-=1;
	pthread_mutex_unlock( &lock );        //解锁互斥锁
}

void ACT_Defend(int country_num)
{
	if(*(pAP+country_num)<4)return;
	
    pthread_mutex_lock( &lock );              //锁住互斥锁

	switch(country_num)
	{
		case 0: printf("魏加固防御,"); break;
		case 1: printf("蜀加固防御,"); break;
		case 2: printf("吴加固防御,"); break;
	}
	
    *(pd+country_num)+=0.1;
  		
	
	printf("防御值为%2f.\n",*(pd+country_num));
    if(*(pd+country_num)>=0.5)printf("防御值已经达上限(0.5)!\n");
	*(pAP+country_num)-=4;
	pthread_mutex_unlock( &lock );        //解锁互斥锁
}

void ACT_Develop(int country_num)
{
	if(*(pAP+country_num)<2)return;
	
    pthread_mutex_lock( &lock );              //锁住互斥锁

	switch(country_num)
	{
		case 0: printf("魏发展生产,"); break;
		case 1: printf("蜀发展生产,"); break;
		case 2: printf("吴发展生产,"); break;
	}
   
	*(pp+country_num)+=develop;

	printf("兵力达到%d.\n",*(pp+country_num));
    
	*(pAP+country_num)-=2;
	pthread_mutex_unlock( &lock );        //解锁互斥锁
}

void  p( int semid )
{
  struct sembuf buf;

  buf.sem_num = 0;
  buf.sem_op = -1;
  buf.sem_flg = SEM_UNDO;

  semop( semid, &buf, 1 );
}

void  v( int semid )
{
  struct sembuf buf;

  buf.sem_num = 0;
  buf.sem_op = 1;
  buf.sem_flg = SEM_UNDO;

  semop( semid, &buf, 1 );
}

int  init()
{
  int semid;
  union semun s;
  s.val=1;
  if( (semid = semget( 0x555, 1, IPC_CREAT|IPC_EXCL|0666 )) == -1 )
{
     semid = semget( 0x555, 1, 0 );
} 
 else
{
     semctl( semid, 0, SETVAL, s );     //初始化
}
  return( semid );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -