1. 程式人生 > >C語言寫的“鬥牛”遊戲原始碼

C語言寫的“鬥牛”遊戲原始碼

/*建立二人鬥牛遊戲的程式*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/*牌的資料結構*/
typedef struct
{
 char face[4];
 int num;
}FACE;
/*建立返回牌結果的資料結構*/
typedef struct
{
 int result;    //點數
 int max;     //最大的那張牌
 int number;    //如果多張牌時返回
 int numberzhi;
}PAIRESULT;
/*建立總共紙牌初始函式*/
void inition(FACE zong[])
{
 int i;
 for(i=1;i<=4;i++)
 {
  strcpy(zong[i].face,"3");
  zong[i].num=0;
 }
 for(i=5;i<=8;i++)
 {
  strcpy(zong[i].face,"4");
  zong[i].num=1;
 }
 for(i=9;i<=12;i++)
 {
  strcpy(zong[i].face,"5");
  zong[i].num=2;
 }
    for(i=13;i<=16;i++)
 {
  strcpy(zong[i].face,"6");
  zong[i].num=3;
 }
 for(i=17;i<=20;i++)
 {
  strcpy(zong[i].face,"7");
  zong[i].num=4;
 }
 for(i=21;i<=24;i++)
 {
  strcpy(zong[i].face,"8");
  zong[i].num=5;
 }
 for(i=25;i<=28;i++)
 {
  strcpy(zong[i].face,"9");
  zong[i].num=6;
 }
 for(i=29;i<=32;i++)
 {
  strcpy(zong[i].face,"10");
  zong[i].num=7;
 }
 for(i=33;i<=36;i++)
 {
  strcpy(zong[i].face,"J");
  zong[i].num=8;
 }
 for(i=37;i<=40;i++)
 {
  strcpy(zong[i].face,"Q");
  zong[i].num=9;
 }
 for(i=41;i<=44;i++)
 {
  strcpy(zong[i].face,"K");
  zong[i].num=10;
 }
 for(i=45;i<=48;i++)
 {
  strcpy(zong[i].face,"A");
  zong[i].num=11;
 }
 for(i=49;i<=52;i++)
 {
  strcpy(zong[i].face,"2");
  zong[i].num=12;
 }
}
/*建立輸出函式*/
void output(int n,FACE zong[],int k)
{
 int i;
 printf("/n");
 if(k==2)
  printf("這是玩家的牌/n");
 else
  printf("這是莊家的牌/n");
 for(i=1;i<=n;i++)
  printf("%s ",zong[i].face);
 printf("/n");
}
/*建立洗牌函式*/
void xipai(FACE zong[])
{
 int i,j;
 long k;
 FACE temp;
 srand(time(NULL));
 for(k=1;k<1000;k++)
 {
  i=1+rand()%52;
  j=1+rand()%52;
  temp=zong[i];
  zong[i]=zong[j];
  zong[j]=temp;
 }
}

/*建立發牌函式*/
void fapai(FACE zong[],FACE player1[],FACE player2[])
{
 int i=1,c1=1,c2=1;
 for(i=1;i<=10;)
 {
  player1[c1++]=zong[i++];
  player2[c2++]=zong[i++];
 }
}
/*建立牌的排序函式*/
void paisort(FACE player[])
{
 FACE temp;
 int i,j;
 for(i=0;i<4;i++)
  for(j=1;j<=4-i;j++)
   if(player[j].num>player[j+1].num)
   {
    temp=player[j];
    player[j]=player[j+1];
    player[j+1]=temp;
   }
}
/*建立只有三張非紙牌的函式*/
int san(int a2[])
{
 if((a2[0]+a2[1]+a2[2])%10==0)//三張牌和為十的倍數時
        return 10;
 else   //沒有牛時
 {  
  /*以下是有兩張牌和為10時*/
  if(a2[0]+a2[1]==10)  return a2[2]; 
  if(a2[0]+a2[2]==10)    return a2[1];
  if(a2[1]+a2[2]==10)    return a2[0];
  else
   return 0;
 }
}

/*建立有四張非花牌時的函式*/
int si(int a[])
{
 if((a[0]+a[1]+a[2])%10==0)   //其中有三張牌和為10的倍數時
  return a[3];
    if((a[0]+a[1]+a[3])%10==0)
     return a[2];
       if((a[0]+a[2]+a[3])%10==0)
     return a[1];
    if((a[3]+a[1]+a[2])%10==0)
     return a[0];
    /*以下是有兩張牌和為1*/
    else
    {
     if(a[0]+a[1]==10&&a[2]+a[3]==10)
      return 10;
     if(a[0]+a[1]==10&&a[2]+a[3]!=10)
      return (a[2]+a[3])%10;
     if(a[0]+a[2]==10&&a[1]+a[3]==10)
      return 10;
     if(a[0]+a[2]==10&&a[1]+a[3]!=10)
      return (a[1]+a[3])%10;
     if(a[0]+a[3]==10&&a[2]+a[1]==10)
      return 10;
           if(a[0]+a[3]==10&&a[2]+a[1]!=10)
      return (a[2]+a[1])%10;
     if(a[1]+a[2]==10&&a[0]+a[3]==10)
      return 10;
     if(a[1]+a[2]==10&&a[0]+a[3]!=10)
      return (a[0]+a[3])%10;
     if(a[1]+a[3]==10&&a[0]+a[2]==10)
      return 10;
           if(a[1]+a[3]==10&&a[0]+a[2]!=10)
      return (a[2]+a[0])%10;
     if(a[2]+a[3]==10&&a[0]+a[1]==10)
      return 10;
           if(a[2]+a[3]==10&&a[0]+a[1]!=10)
      return (a[0]+a[1])%10;
     /*若無法湊出十時,點為零*/
     else
      return 0;
    } 
}
/*若無張牌都為非花牌,即五張非花牌時,若要有點數,必須用三張牌來湊點數*/
int wu(int a[])
{
 if((a[0]+a[1]+a[2])%10==0&&a[3]+a[4]==10)
  return 10;
 if((a[0]+a[1]+a[2])%10==0&&a[3]+a[4]!=10)
  return (a[3]+a[4])%10;
 
 if((a[0]+a[1]+a[3])%10==0&&a[2]+a[4]==10)
  return 10;
 if((a[0]+a[1]+a[3])%10==0&&a[2]+a[4]!=10)
  return (a[2]+a[4])%10;
 
 if((a[0]+a[1]+a[4])%10==0&&a[2]+a[3]==10)
  return 10;
 if((a[0]+a[1]+a[4])%10==0&&a[2]+a[3]!=10)
  return (a[2]+a[3])%10;
 
 if((a[0]+a[2]+a[3])%10==0&&a[1]+a[4]==10)
  return 10;
 if((a[0]+a[2]+a[3])%10==0&&a[1]+a[4]!=10)
  return (a[1]+a[4])%10;
 
 if((a[0]+a[2]+a[4])%10==0&&a[1]+a[3]==10)
  return 10;
 if((a[0]+a[2]+a[4])%10==0&&a[1]+a[3]!=10)
  return (a[1]+a[3])%10;
 
 if((a[0]+a[4]+a[3])%10==0&&a[2]+a[1]==10)
  return 10;
 if((a[0]+a[4]+a[3])%10==0&&a[2]+a[1]!=10)
  return (a[2]+a[1])%10;
 
 if((a[2]+a[1]+a[3])%10==0&&a[4]+a[0]==10)
  return 10;
 if((a[2]+a[1]+a[3])%10==0&&a[0]+a[4]!=10)
  return (a[0]+a[4])%10;
 
 if((a[2]+a[1]+a[4])%10==0&&a[0]+a[3]==10)
  return 10;
 if((a[2]+a[1]+a[4])%10==0&&a[0]+a[3]!=10)
  return (a[0]+a[3])%10;
 
 if((a[4]+a[1]+a[3])%10==0&&a[2]+a[0]==10)
  return 10;
 if((a[4]+a[1]+a[3])%10==0&&a[2]+a[0]!=10)
  return (a[2]+a[0])%10;
 
 if((a[2]+a[4]+a[3])%10==0&&a[0]+a[1]==10)
  return 10;
 if((a[2]+a[4]+a[3])%10==0&&a[0]+a[1]!=10)
  return (a[0]+a[1])%10;
 else
  return 0;
}
/*建立求最大值的函式*/
int searchmaxpai(FACE player[])
{
 int a[7]={0},i,max;
 for(i=1;i<=5;i++)
 {
  if(player[i].num>=11)
   a[i]=player[i].num-13;
  else
   a[i]=player[i].num;
 }
 for(max=a[1],i=1;i<=5;i++)
  if(max<a[i])
   max=a[i];
  return max;
}
/*建立計算有幾張重複牌的函式*/
void countrepeat(int a[],int n,int b[])
{
 int k[5]={0},i=0,j=0,temp=0;
 for(i=0;i<n;i++)
 {
  temp=a[i];
  for(j=0;j<n;j++)
   if(temp==a[j])
    k[i]++;
 }
 for(i=0;i<n;i++)
 {
  if(k[i]>=3)
  {
   b[0]=k[i];   //b[0]儲存重複數目
   b[1]=a[i];
   break;//b[1]儲存對應的值
  }
  
 }
}
/*建立計算牌的點數的函式,這是遊戲的核心演算法*/
PAIRESULT jisuan(FACE player[],PAIRESULT finalresult)
{
 int a1[5]={0},c1=0;//用於儲存10,J,Q,K的花牌表示的值
 int a[2]={-1,-1};
 int a2[5]={0},c2=0; //用於儲存非花牌表示的值
 int i;
 for(i=1;i<=5;i++)  //總共5次
 {
  if(player[i].num>=7&&player[i].num<=10)  //如果是花牌時
   a1[c1++]=player[i].num+3;
  else
   if(player[i].num>=0&&player[i].num<=6)//如果是3-9時
    a2[c2++]=player[i].num+3;
   else
    a2[c2++]=player[i].num-10;  //如果是A或2時
 } //完成對牌的分類儲存
 /*以下對非花牌進行計算點數*/
 switch(c2)
 {
 case 0 : finalresult.result=10;break; //都是花牌時
 case 1 : finalresult.result=a2[0];break;  //只有一張非花牌時
  /*只有二張非零牌時*/
 case 2 : {if(a2[0]+a2[1]==10)
     finalresult.result=10;
  else
   finalresult.result=(a2[0]+a2[1])%10;
    }break;
  /*以下是由三張非花牌時*/
 case 3 : finalresult.result=san(a2);break;
  /*以下是四張非花牌時*/
 case 4 : finalresult.result=si(a2);break;
  /*以下是五張非花牌時*/
 case 5 : finalresult.result=wu(a2);break;
 }
 finalresult.max=searchmaxpai(player);       //最大牌的值,便於點數相同時比較大小
 /*以下對有可能有的多張牌進行處理,儲存最多的牌*/
 if(c1>=3)
 {
  countrepeat(a1,c1,a);
  if(a[0]>=3)
  {
   finalresult.number=a[0]+1;   //如果是花牌有多張時倍數更大
   finalresult.numberzhi=a[1];
  }
 }
 else
    if(c2>=3)
    {
     countrepeat(a2,c2,a);
     if(a[0]>=3)
     {
      finalresult.number=a[0];
      finalresult.numberzhi=a[1];
     }
    }
    else
     finalresult.number=finalresult.numberzhi=-1;
    return finalresult;
}
PAIRESULT build()
{
 PAIRESULT final;
 final.max=-1,
  final.number=-1;
 final.result=final.numberzhi=-1;
 return final;
}
/*建立牌的比較函式,a[0]總金錢,a[1]表示押金*/
int  compare(PAIRESULT final1,PAIRESULT final2,int a[])
{
 int t=a[0];
 /*做如下規定,四張相同牌,20,三張相同牌15倍,五張即四張花牌時25被*/
 /*相同牌時莊家牌大*/
 switch(final1.number)
 {
    case 5 :  {if(final2.number==5&&final1.numberzhi>=final2.numberzhi)
     {
      a[0]=a[0]-a[1]*25;
      break;
     }
     if(final2.number==5&&final1.numberzhi<final2.numberzhi)
     {
      a[0]=a[0]+a[1]*25;
      break;
     }
     else
     {
      a[0]=a[0]-a[1]*25;
      break;
     }
     };
    case 4 :  { if(final2.number==5)
     {
      a[0]=a[0]+a[1]*25;
      break;
     }
     if(final2.number==4&&final1.numberzhi>=final2.numberzhi)
     {
      a[0]=a[0]-a[1]*20;
      break;
     }
     if(final2.number==4&&final1.numberzhi<final2.numberzhi)
     {
      a[0]=a[0]+a[1]*20;
      break;
     }
     else
     {
      a[0]=a[0]-a[1]*20;
      break;
     }
     }
    case 3 :  {   if(final2.number==5)
     {
      a[0]=a[0]+a[1]*25;
      break;
     }
     if(final2.number==4)
     {
      a[0]=a[0]+a[1]*20;
      break;
     }
     if(final2.number==3&&final1.numberzhi<final2.numberzhi)
     {
      a[0]=a[0]+a[1]*15;
      break;
     }
     else
     {
      a[0]=a[0]-a[1]*15;
      break;
     }
     };
    case -1 : {
     if(final2.number==5)
     {
      a[0]=a[0]+a[1]*25;
      break;
     }
     if(final2.number==4)
     {
      a[0]=a[0]+a[1]*20;
      break;
     }
     if(final2.number==3)
     {
      a[0]=a[0]+a[1]*15;
      break;
     }
     if(final1.result>final2.result)//莊家牌大時
     {
      if(final1.result==10)
      {
       a[0]=a[0]-a[1]*3;
       break;
      }
      if(final1.result>=7&&final1.result<=9)
      {
       a[0]=a[0]-a[1]*2;
       break;
      }
      if(final1.result<7)
      {
       a[0]=a[0]-a[1];
       break;
      }
     }
     else
      if(final1.result<final2.result)//玩家牌大時
      {
       if(final2.result==10)
       {
        a[0]=a[0]+a[1]*3;
        break;
       }
       if(final2.result>=7&&final2.result<=9)
       {
        a[0]=a[0]+a[1]*2;
        break;
       }
       if(final2.result<7)
       {
        a[0]=a[0]+a[1];
        break;
       }
      }
      else
      {  if(final1.result==10&&final1.max>=final2.max)
      {    
       a[0]=a[0]-a[1]*3;
       break;
      }
      if(final1.result==10&&final1.max<final2.max)
      {    
       a[0]=a[0]+a[1]*3;
       break;
      }
      if(final1.result>=7&&final1.result<=9&&final1.max>=final2.max)
      { 
       a[0]=a[0]-a[1]*2;
       break;
      }
      if(final1.result>=7&&final1.result<=9&&final1.max<final2.max)
      { 
       a[0]=a[0]+a[1]*2;
       break;
      }
      if(final1.result<7&&final1.max>=final2.max)
      { 
       a[0]=a[0]-a[1];
       break;
      }
      if(final1.result<7&&final1.max<final2.max)
      { 
       a[0]=a[0]+a[1];
       break;
      }
      }
     }
  }
  return a[0]-t;
}
void menu()
{
 printf("/t/t/t歡迎來到“歡樂鬥牛”遊戲/n");
 printf("請按數字鍵選擇/n");
 printf("/t1:開始遊戲/n");
 printf("/t2:遊戲規則/n");
 printf("/t3:離開遊戲/n");
}
/*建立遊戲規則函式*/
void instruction()
{
 printf("/t鬥牛也屬於紙牌遊戲,該遊戲中游戲為莊家,你為玩家./n");
 printf("/t遊戲開始時系統送你100遊戲幣,輸完時遊戲結束.");
    printf("/t規則簡要如下:/n");
 printf( "/t每人有五張牌,比較點數,點數大者勝。計算點數時10、J、Q、/n");
 printf("/tK為花牌,用非花牌計算點數,若五張牌中沒有一張花牌,任意用/n");
 printf("/t其中三張湊成10的倍數,如果不能,則點數為零,如果能湊成,用/n");
 printf("/t另外兩張之和除以十,餘數為點數。若有花牌時,可以用其中兩張/n");
 printf("/t或三張牌湊成10的倍數,如果能,結果為其餘牌之和除以10的餘數/n");
 printf("/t(餘數為零點數為10)。不能時,點數為零。當點數相同時,以牌/n");
 printf("/t面值大者勝./n");
 printf("/t0-6點倍率為1,7-9點倍率為2,10點倍率為3/n");
 printf("/t三張相同面值的非花牌,倍率15,四張20/n");
 printf("/t三張相同面值的花牌,倍率20,四張25/n");
 printf("/t賭博有害家庭健康,該遊戲僅供娛樂/n");
}
int main()
{
 FACE zong[52];//總共的48張紙牌
 PAIRESULT final1=build(),final2=build();//牌的結果
 FACE player1[5],player2[5];  //用於儲存兩個玩家的牌,player1是莊家,player2是玩家
 inition(zong);
 int flag,a[2]={100,0},count=1,defen;
 char ch;
    /*以下是遊戲選單*/
 menu();
 scanf("%d",&flag);
 while(flag<1||flag>3)
 {
  printf("數字輸入錯誤,請重新輸入/n");
  scanf("%d",flag);
 }
    while(flag!=1)
 {
  if(flag==3)
   exit(0);
  else
   if(flag==2)
   {
    instruction();
    menu();
    scanf("%d",&flag);
   }
 }
 if(flag==1)
 {
  printf("/t/t現在開始遊戲/n");
  printf("/t/t系統先送你100遊戲幣,當遊戲幣不大於零時遊戲結束/n");
  while(1)
  {
   printf("/t/t/t/t第%d局/n",count);
   printf("請下注(1-10遊戲幣),目前你的遊戲幣為%d/n",a[0]);
   while(1)
   {
    scanf(" %d",&a[1]);
    if(a[1]>0&&a[1]<=10)
     break;
    else
     printf("輸入資料範圍不對,請重新選擇/n");
   }
   xipai(zong);  //洗牌
   fapai(zong,player1,player2);  //發牌
   paisort(player1);  output(5,player1,1);  //莊家的牌,先排序在現實牌
   paisort(player2);   output(5,player2,2);  //玩家的牌,先排序在顯現牌
   final1=jisuan(player1,final1);    //計算點數
   final2=jisuan(player2,final2);   //計算點數
   defen=compare(final1,final2,a);
   if(final1.number>=3&&final1.numberzhi>=11)
    printf("/t莊家有%d張牌相同/n",(final1.number-1));
   else
    if(final1.number>=3&&final1.numberzhi<11)
     printf("/t莊家有%d張牌相同/n",final1.number);
    else
     printf("/t莊家牌的點數: %d/n",final1.result);

    if(final2.number>=3&&final2.numberzhi>=11)
     printf("恭喜你,你有%d張牌相同/n",(final2.number-1));
    else
     if(final2.number>=3&&final2.numberzhi<11)
      printf("恭喜你,你有%d張牌相同/n",final2.number);
     else
      if(final2.result==10)
       printf("/t/t你牛了,牛氣沖天/n");
      else
       if(final2.result>=7&&final2.result<=9)
        printf("/t/t你進套了,點數:%d/n",final2.result);
       else
        printf("/t/t你的點數:%d/n",final2.result);
       if(defen>0)
        printf("/t本局你勝,得分:%d/n",defen);
       else
        if(defen==0)
         printf("/t本局平局/n");
        else
         printf("/t本局你輸了,再接再厲,得分:%d/n",defen);
        printf("/t/t/t/t總遊戲幣:%d/n",a[0]);
        if(a[0]<=0)
         break;
        else
        {
         printf("/t/t繼續C(continue)/t/t退出遊戲E(end)/n");
         scanf(" %c",&ch);
         if(ch=='e')
          break;
         else
         {
          count++;
          final1=final2=build();
         }
         
        }
  }
 }
 if(a[0]==100)
  printf("/t遊戲結果平局/n");
 else
  if(a[0]>100)
   printf("/t恭喜你,你贏的遊戲幣%d/n",a[0]-100);
  else
   printf("/t再接再厲,你輸了遊戲幣%d/n",100-a[0]);
  return 0;
}