请你编程

Author: 阮锡光 Date: 1997-01-01

#3  题目:编制一个小游戏,在屏幕上给出四张扑克牌,牌上显示由用户任意输入的点数(11.12.13.1分别用J.Q.K.A表示),将牌翻转,把纸牌的位置作若干次互换,屏幕上给出互换的顺序,在限定时间内请用户判定哪张牌的点数最大。
  下面先介绍中国纺织大学黄剑的程序中的一个函数:
  procedure swap-card(start-card,end-card:byte);
  {在这个展示换牌动画的过程中,选用切换显示页的方法,纸牌的移动速度和用户选的等级呈正比关系,并且纸牌的移动曲线为SIN函数曲线。}
  var i:integer;{循环变量}    
  x,{所要交换的两张纸牌的横坐标距离}    
  x1,y1:integer;            {当前将要画纸牌的坐标}    
  t,{SIN函数变量} 
  omega,step:real;  {omega为SIN函数参数,step为其变量每次的增量}
  page:integer;             {用page对2取模的值作为显示页号}
  frame-number:integer;     {动画的帧数,也可以看作动画的速度}
  delay-time:integer;       {每帧动画之间的延迟}
  begin x:=(end-card-start-card)*1{计算横坐标距离} 
  frame-number:=11+(end-card-start-card)*2-2*(level div 10);
  if(frame-number mod 2)=0 then inc(frame-number);{帧数调整}
  delay-time:=(3-(x div 100))*5+10; 
  omega:=pi/x;step:=x/frame-number; 
  t:=0;page:=1;{初始化变量}  
  while (t<=x) do begin
  {动画循环}     
  setactivepage(page mod 2); {选择当前不可见页为活动页}
  cleardevice;  
  for i:=0 to 3 do           {画出不作交换的两纸牌}   
  if (i<>start-card) and (i<>end-card)    
  then place-card(i,1,down-side);    
  x1:=120+start-card*100+round(t);     
  y1:=130-round(80*sin(omega*t));   
  draw-card(x1,y1,1,down-side);{画出由左向右移动的一张纸牌}
  x1:=120+end-card*100-round(t);     
  y1:=130+round(80*sin(omega*t));   
  draw-card(x1,y1,1,down-side);{画出由右向左移动的一张纸牌}
  setvisualpage(page mod 2);{选择刚才输出动画的活动页为可见页}
  t:=t+step; inc(page);       {变量各自加上增量}
  delay(delay-time);end;end  {视觉延迟}
  另外,宁夏张永强编制的程序很有特色,他设计的扑克牌不仅有点数,而且有花色,并有大小王,画面漂亮。如:
#3  梅花:
  fillellipse(xx,y+60,10*size,10);
  fillellipse(xx+8*size,y+75,10*size,10);
  fillellipse(xx-8*size,y+75,10*size,10);
  line(xx,y+75,xx-3*size,y+90);
  line(xx,y+75,xx+3*size,y+90);
  line(xx-3*size,y+90,xx+3*size,y+90);
  floodfill(xx,y+89,BLACK);
#3  黑桃:
  line(xx,y+50,xx+15*size,y+70);
  line(xx,y+50,xx-15*size,y+70);      
  fillellipse(xx+5*size,y+75,12*size,12);
  fillellipse(xx-5*size,y+75,12*size,12);
  line(xx,y+75,xx-3*size,y+100);
  line(xx,y+75,xx+3*size,y+100);   
  line(xx-3*size,y+100,xx+3*size,y+100);
  floodfill(xx,y+52,BLACK);
  floodfill(xx,y+99,BLACK);
#3  红桃和方片用同样方法也可实现,用
  settextstyle(TRIPLEX-FONT,0,4);
  outtextxy(xx-45*size,y+5,CARD-title[title])语句显示点数。将54张牌放入一个数组,使用者选择牌时,54张牌可随机显示,用户通过按回车选牌,限于版面,不能一一登出。下面另给出一个完整的程序,虽其结果不够理想,但比较简单,也能够达到要求。
  /*Turbo C 2.0*/
  #include <conio.h>
  #include <math.h>
  #include <stdio.h>
  #include <dos.h>
  #include <bios.h>
  #include <ctype.h>
  #include <stdlib.h>
  #include <time.h>
  static char s[11][15]={{"            "},
          {"            "},
          {"            "},
          {"            "},
          {"            "},
          {"            "},
          {"            "}};
  void cocp(int co) /*光标开关函数*/
  {union REGS regs; 
  regs.h.ah=1; 
  regs.h.ch=6; 
  regs.h.cl=co; 
  int86(0x10,&regs,&regs);}
  char inkey() /*键值读取函数*/
  {union REGS regs; 
  regs.h.ah=0; 
  int86(0x16,&regs,&regs); 
  return(regs.h.al);}
  int timeinkey(int t) /*定时读取键值函数*/
  {union REGS regs; 
  int i,j,m; 
  for(t=9;t>0;t--)    
  {gotoxy(12,23);     
  printf("%d",t);     
  gotoxy(10,23);     
  for(j=1;j<10;j++)      
  {delay(500);       
  regs.h.ah=1;       
  int86(0x16,&regs,&regs);
  if ((regs.x.flags & 0x60)==0)                  
  /*是否按键*/        
  {m=inkey();         
  if(m>48 && m<53)        
  {gotoxy(10,23);         
  m=m-48;         
  printf("%d    ",m);
  return(m);}}}} 
  return(0); }
  void display(ldx,ldy,dx,dy,x,y)/*显示纸牌函数*/
  int ldx,ldy,dx,dy,x,y;
  {int i,j; 
  for(i=0;i<dy;i++)  
  {gotoxy(x,y+i);
  for(j=0;j<dx;j++)    
  putchar(s[ldy+i][ldx+j]); }}
  void move(a,b)/*移动纸牌函数*/
  int a,b;
  {int ldx,ldy,dx,dy,x,y,i,m,n; 
  m=(b-a)*15; /*未移动两纸牌之间距离*/
  for(i=13;i>2;i--)    
  {display(1,1,12,10,a*15,i);     
  display(1,1,12,10,b*15,i);  } 
  for(i=0;i<m;i++)
  {n=m-2*i-2; /*移动中那两个纸牌之间距离*/   
  display(0,1,13,9,a*15+i,3);  
  if(abs(n)<12)/*两牌相遇时B牌显示范围调整*/     
  if(n>=0)      
  display(12-n,1,n+2,9,a*15+i+13,3);      
  else display(1,1,-n,9,b*15-i-1,3);     
  else display(1,1,13,9,b*15-i-1,3); } 
  for(i=3;i<14;i++)    
  {display(1,0,12,10,a*15,i);     
  display(1,0,12,10,b*15,i); }}
  main()
  {int i,j,ka,kb,a[4]; 
  char m; 
  clrscr();/*清屏*/ 
  cocp(0);/*消隐光标*/ 
  for(i=1;i<5;i++)    
  {display(1,1,12,9,i*15,14);     
  gotoxy(i*15+6,18);     
  putchar(' '); } 
  gotoxy(1,23); 
  cocp(7);/*显示光标*/ 
  printf("input(2-9,a,j,q,k)"); 
  for(i=0;i<4;i++)    
  {gotoxy(i*15+21,18);     
  m=inkey(1);     
  if (m>49 && m<58)     
  {a[i]=m-48;putchar(m);continue;}     
  if (m==' a'|| m=='A')     
  { a[i]=1;putchar(m);continue;}     
  if (m=='j' || m=='J')     
  {a[i]=11;putchar(m);continue;}     
  if (m==' q'|| m==' Q')
  {a[i]=12;putchar(m);continue;}     
  if (m=='k'|| m=='K')     
  {a[i]=13;putchar(m);continue;}     
  i--; } 
  gotoxy(1,23); 
  printf("                     "); 
  cocp(0); 
  delay(1800); 
  for(i=1;i<5;i++) 
  {gotoxy(i*15+6,18);putchar(176);}/*盖牌*/ 
  randomize(); 
  for(i=1;i<11;i++)/*随机调换两只纸牌十次*/     
  {ka=random(4)+1;      
  kb=ka+random(3)+1;      
  if(kb>4){j=ka;ka=kb-4;kb=j;}      
  move(ka,kb); } 
  gotoxy(1,23); 
  cocp(7); 
  printf("maxnaber:"); 
  j=timeinkey(9); 
  if(j==0){clrscr();exit(0);} 
  gotoxy(1,24); 
  for(i=0;i<4;i++)     
  {if(a[j-1]<a[i])       
  {printf("NO");        
  exit(0);} } 
  printf("YES");}