博文

90.搬山游戏(2005-09-10 15:19:00)

摘要:90.搬山游戏 设有n座山,计算机与人为比赛的双方,轮流搬山。规定每次搬山的数止不能超 过k座,谁搬最后一座谁输。游戏开始时。计算机请人输入山的总数(n)和每次允许搬山的最大数止(k)。然后请人开始,等人输入了需要搬走的山的数目后,计算机马上打印出它搬多少座山,并提示尚余多少座山。双方轮流搬山直到最后一座山搬完为止。计算机会显示谁是赢家,并问人是否要继续比赛。若人不想玩了,计算机便会统计出共玩了几局,双方胜负如何。 *问题分析与算法设计 计算机参加游戏时应遵循下列原则: 1) 当: 剩余山数目-1<=可移动的最大数k 时计算机要移(剩余山数目-1)座,以便将最后一座山留给人。 2)对于任意正整数x,y,一定有: 0<=x%(y+1)<=y 在有n座山的情况下,计算机为了将最后一座山留给人,而且又要控制每次搬山的数目不超过最大数k,它应搬山的数目要满足下列关系: (n-1)%(k+1) 如果算出结果为0,即整除无余数,则规定只搬1座山,以防止冒进后发生问题。 按照这样的规律,可编写出游戏程序如下: #include<stdio.h> void main() { int n,k,x,y,cc,pc,g; printf("More Mountain Game\n"); printf("Game Begin\n"); pc=cc=0; g=1; for(;;) { printf("No.%2d game \n",g++); printf("---------------------------------------\n"); printf("How many mpuntains are there?"); scanf("%d",&n); if(!n) break; printf("How many mountains are allowed to each time?"); do{ scanf("%d",&k); if(k>n||k<1) printf("Repeat again!\n"); }while(k>n||k<1);......

阅读全文(4567) | 评论:0

89.抢 30(2005-09-10 15:19:00)

摘要:89.抢 30 这是中国民间的一个游戏。两人从1开始轮流报数,每人每次可报一个数或两个连续的数,谁先报到30,谁就为胜方。 *问题分析与算法设计 本题与上题类似,算法也类似,所不同的是,本谁先走第一步是可选的。若计算机走第一步,那么计算机一定是赢家。若人先走一步,那么计算机只好等待人犯错误,如果人先走第一步且不犯错误,那么人就会取胜;否则计算机会抓住人的一次错误使自己成为胜利者。 *程序与程序注释 #include<stdio.h> #include<time.h> #include<stdlib.h> int input(int t); int copu(int s); void main() { int tol=0; printf("\n* * * * * * * *catch thirty* * * * * * * \n"); printf("Game Begin\n"); randomize(); /*初始化随机数发生器*/ if(random(2)==1) /*取随机数决定机器和人谁先走第一步*/ tol=input(tol); /*若为1,则余元走第一步*/ while(tol!=30) /*游戏结束条件*/ if((tol=copu(tol))==30) /*计算机取一个数,若为30则机器胜利*/ printf("I lose! \n"); else if((tol=input(tol))==30) /*人取一个数,若为30则人胜利*/ printf("I lose! \n"); printf(" * * * * * * * *Game Over * * * * * * * *\n"); } int input(int t) { int a; do{ printf("Please count:"); scanf("%d",&a); if(a>2||a<1||t+a>30) printf("Error input,again!"); else printf("You count:%d\n",t+a); }while(......

阅读全文(5182) | 评论:0

88.常胜将军(2005-09-10 15:18:00)

摘要:88.常胜将军 现有21根火柴,两人轮流取,每人每次可以取走1至4根,不可多取,也不能不取,谁取最后一楰火柴谁输。请编写一个程序进行人机对弈,要求人先取,计算机后取;计算机一方为“常胜将军”。 *问题分析与算法设计 在计算机后走的情况下,要想使计算机成为“常胜将军”,必须找出取 关键。根据本题的要求枷以总结出,后走一方取子的数量与对方刚才一步取子的数量之和等于,就可以保证最后一个子是留给先取子的那个人的。 据此分析进行算法设计就是很简单的工作,编程实现也十分容易。 *程序与程序注释 #include<stdio.h> void main() { int a=21,i; printf("Game begin:\n"); while(a>0) { do{ printf("How many stick do you wish to take(1~%d)?",a>4?4:a); scanf("%d",&i); }while(i>4||i<1||i>a); /*接收正在确的输入*/ if(a-i>0) printf(" %d stick left in the pile.\n",a-i); if((a-i)<=0) { printf(" You have taken the last stick.\n"); printf(" * * * You lose! \nGame Over.\n"); /*输出取胜标记*/ break; } else printf(" Compute take %d stick.\n",5-i); /*输出计算机取的子数*/ a-=5; printf(" %d stick left in the pile.\n",a); } } *思考题 改变题目中火柴的数量(如为22根),则后走的一方就不一定能够保持常胜了,很可能改变成“常败”。此时后走一方的胜负就与火柴的初始数量和每次允许取的火柴数量的最大值有直接关系,请编写程序解决这一问题。 ......

阅读全文(3406) | 评论:0

87.黑白子交换(2005-09-10 15:19:00)

摘要:87.黑白子交换 有三个白子和三个黑子如下图布置: ○ ○ ○ . ● ● ● 游戏的目的是用最少的步数将上图中白子和黑子的位置进行交换: ● ● ● . ○ ○ ○ 游戏的规则是:(1)一次只能移动一个棋子; (2)棋子可以向空格中移动,也可以跳过一个对方的棋子进入空格,但不能向后跳,也不能跳过两个子。请用计算机实现上述游戏。 *问题分析与算法设计 计算机解决胜这类问题的关键是要找出问题的规律,或者说是要制定一套计算机行动的规则。分析本题,先用人来解决问题,可总结出以下规则: (1) 黑子向左跳过白子落入空格,转(5) (2) 白子向右跳过黑子落入空格,转(5) (3) 黑子向左移动一格落入空格(但不应产生棋子阻塞现象),转(5) (4) 白子向右移动一格落入空格(但不应产生棋子阻塞现萌),转(5) (5) 判断游戏是否结束,若没有结束,则转(1)继续。 所谓的“阻塞”现象就是:在移动棋子的过程中,两个尚未到位的同色棋子连接在一起,使棋盘中的其它棋子无法继续移动。例如按下列方法移动棋子: 0 ○ ○ ○ . ● ● ● 1 ○ ○ . ○ ● ● ● 2 △ ○ ○ ● ○ . ● ● 3 ○ ○ ● . ○ ● ● 4 两个●连在一起产生阻塞 ○ ○ ● ● ○ . ● 或4 两个白连在一起产生阻塞 ○ . ● ○ ○ ● ● 产生阻塞的现象的原因是在第2步(△状态)时,棋子○不能向右移动,只能将●向左移动。 总结产生阻塞的原因,当棋盘出现“黑、白、空、黑”或“白、空、黑、白”状态时,不能向左或向右移动中间的棋子,只移动两边的棋子。 按照上述规则,可以保证在移动棋子的过程中,不会出现棋子无法移动的现象,且可以用最少的步数完成白子和黑子的位置交换。 *程序与程序注释 #include<stdio.h> int number; void print(int a[]); void change(int *n,int *m); void main() { int t[7]={1,1,1,0,2,2,2}; /*初始化数组1:白子 2:黑子 0:空格*/ int i,flag; print(t); while(t[0]+t[1]+t[2]!=6||t[4]+t[5]+t[6]!=3) /*判断游戏是否结束 若还没有完成棋子的交换则继续进行......

阅读全文(4862) | 评论:0

86.自动发牌(2005-09-10 15:18:00)

摘要:86.自动发牌注:本程序根据反映发现有点错,我调试了一下,只把语法错误改了一下(红色部分),至于逻辑错误,因为是转载的,我并不清楚现在又比较忙,所以没有更正。现在提供两个链接,或许对于理解问题有点帮助:http://bbs.cpcw.com/archiver/?tid-391664.html和http://cpcw.cnbbbs.com/tid-393278.html一副扑克有52张牌,打桥牌时应将牌分给四个人。请设计一个程序完成自动发牌的工作。要求:黑桃用S(Spaces)表示;红桃用H(Hearts)表示;方块用D(Diamonds)表示;梅花用C(Clubs)表示。*问题分析与算法设计按照打桥牌的规定,每人应当有13张牌。在人工发牌时,先进行洗牌,然后将洗好的牌按一定的顺序发给每一个人。为了便于计算机模拟,可将人工方式的发牌过程加以修改:先确定好发牌顺序:1、2、3、4;将52张牌顺序编号:黑桃2对应数字0,红桃2对应数字1,方块2对应数字2,梅花2对应数字3,黑桃3对应数字4,红桃3对应数字5,...然后从52 张牌中随机的为每个人抽牌。这里采用C语言库函数的随机函数,生成0到51之间的共52个随机数,以产生洗牌后发牌的效果。*程序与程序注释 #include<stdlib.h>#include<stdio.h>int comp(const void *j,const void *i);void p(int b[],char n[]); int main(void){    static char n[]={'2','3','4','5','6','7','8','9','T','J','Q','K','A'};    int a[53],b1[13],b2[13],b3[13],b4[13];    int b11=0,b22=0,b33=0,b44=0,t=1,m,flag,i;    while(t<=52) /*控制发52张牌*/    {        m=rand()%52; /*产生0到51之间......

阅读全文(8309) | 评论:4

85.回文数的形成(2005-09-10 15:18:00)

摘要:85.回文数的形成 任取一个十进制整数,将其倒过来后与原来的整数相加,得到一个新的整数后重复以上步聚,则最终可得到一个回文数。请编程验证。 *问题分析与算法设计 回文数的这一形成规则目前还属于一个猜想,尚未得到数学上的证明。有些回文数要经历上百个步聚才能获得。这里通过编程验证。 题目中给出的处理过程很清楚,算法不需要特殊设计。可按照题目的叙述直接进行验证。 *程序与程序注释 #include<stdio.h> #define MAX 2147483647 long re(long int); int nonres(long int s); void main() { long int n,m; int count=0; printf("Please enetr a number optionaly:"); scanf("%ld",&n); printf("The generation process of palindrome:\n"); while(!nonres((m=re(n))+n)) /*判断整数与其反序数相加后是否为回文数*/ { if(m+n>=MAX) { printf(" input error,break.\n"); break; } else { printf("[%d]:%ld+%ld=%ld\n",++count,n,m,m+n); n+=m; } } printf("[%d]:%ld+%ld=%ld\n",++count,n,m,m+n); /*输出最后得到的回文数*/ printf("Here we reached the aim at last!\n"); } long re(long int a) /*求输入整数的反序数*/ { long int t; for(t=0;a>0;a/=10) /*将整数反序*/ t=t*10+a%10; return t; } int nonres(long int s) /*判断给定的整数是否是回文数*/ { if(re(s)==s) return 1; /*若是回文数则返回1*/ else return 0; /*否则返回 0*......

阅读全文(4122) | 评论:0

84.尼科彻斯定理(2005-09-10 15:18:00)

摘要:84.尼科彻斯定理 验证尼科彻斯定理,即:任何一个整数的立方都可以写成一串连续奇数的和。×× *问题分析与算法设计 本题是一个定理,我们先来证明它是成立的。 对于任一正整数a,不论a是奇数还是偶数,整数(a×a-a+1)必然为奇数。 构造一个等差数列,数列的首项为(a×a-a+1),等差数列的差值为2(奇数数列),则前a项的和为: a×((a×a-a+1))+2×a(a-1)/2 =a×a×a-a×a+a+a×a-a =a×a×a 定理成立。证毕。 通过定理的证明过程可知L所要求的奇数数列的首项为(a×a-a+1),长度为a。编程的算法不需要特殊设计,可按照定理的证明过直接进行验证。 *程序与程序注释 #include<stdio.h> void main() { int a,b,c,d; printf("Please enter a number:"); scanf("%d",&a); /*输入整数*/ b=a*a*a; /*求整数的三次方*/ printf("%d*%d*%d=%d=",a,a,a,b); for(d=0,c=0;c<a;c++) /*输出数列,首项为a*a-a+1,等差值为2*/ { d+=a*a-a+1+c*2; /*求数列的前a项的和*/ printf(c?"+%d":"%d",a*a-a+1+c*2); } if(d==b)printf(" Y\n"); /*若条件满足则输出“Y”*/ else printf(" N\n"); /*否则输出“N”*/ } *运行结果 1) Please enter a number:13 13*13*13=2197=157+159+161+163+165+167+169+171+173+175+177+179+181 Y 2) Please enter a number:14 14*14*14=2744=183+185+187+189+191+193+195+197+199+201+203+205+207+209 Y *思考题 本题的求解方法是先证明,在证明的过程中找到编程的算法,然后实现编程。实际上我们也可以不进行证明,直接使用编程中常用......

阅读全文(3523) | 评论:0

83.卡布列克常数(2005-09-10 15:17:00)

摘要:83.卡布列克常数 验证卡布列克运算。任意一个四位数,只要它们各个位上的数字是不全相同的,就有这样的规律: 1)将组成该四位数的四个数字由大到小排列,形成由这四个数字构成的最大的四位数; 2)将组成该四位数的四个数字由小到大排列,形成由这四个数字构成的最小的四位数(如果四个数中含有0,则得到的数不足四位); 3)求两个数的差,得到一个新的四位数(高位零保留)。 重复以上过程,最后得到的结果是6174,这个数被称为卡布列克数。 *问题分析与算法设计 题目中给出的处理过程很清楚,算法不需要特殊设计,可按照题目的叙述直接进行验证。 *程序与程序注释 #include<stdio.h> void vr6174(int); void parse_sort(int num,int *each); void max_min(int *each,int *max,int *min); void parse_sort(int num,int *each); int count=0; void main() { int n; printf("Enter a number:"); scanf("%d", &n); /*输入任意正整数*/ vr6174(n); /*调用函数进行验证*/ } void vr6174(int num) { int each[4],max,min; if(num!=6174&&num) /*若不等于74且不等于0则进行卡布列克运算*/ { parse_sort(num,each); /*将整数分解,数字存入each数组中*/ max_min(each,&max,&min); /*求数字组成的最大值和最小值*/ num=max-min; /*求最大值和最小值的差*/ printf("[%d]: %d-%d=%d\n",++count,max,min,num); /*输出该步计算过程*/ vr6174(num); /*递归调用自身继续进行卡布列克运算*/ } } void parse_sort(int num,int *each) { int i,*j,*k,temp; for(i=0;i<=4;i++) /*将NUM分解为数字*/ { j=ea......

阅读全文(4784) | 评论:0

82.四方定理(2005-09-10 15:18:00)

摘要:82.四方定理 数论中著名的“四方定理”讲的是:所有自然数至多只要用四个数的平方和就可以表示。 请编程证此定理。 *问题分析与算法设计 本题是一个定理,我们不去证明它而是编程序验证。 对四个变量采用试探的方法进行计算,满足要求时输出计算结果。 *程序与程序注释 #include<stdio.h> #include<stdlib.h> void main() { int number,i,j,k,l; printf("Please enter a number="); scanf("%d",&number); /*输入整数*/ for(i=1;i<number/2;i++) /*试探法。试探i,j,k,k的不同值*/ for(j=0;j<=i;j++) for(k=0;k<=j;k++) for(l=0;l<=k;l++) if(number==i*i+j*j+k*k+l*l) /*若满足定理要求则输出结果*/ { printf(" %d=%d*%d+%d*%d+%d*%d+%d*%d\n",number,i,i,j,j,k,k,l,l); exit(0); } } *运行结果 1) Please enter a number = 110 110=7*7+6*6+4*4+3*3 2) Please enter a number = 211 211=8*8+7*7+7*7+7*7 3) Please enter a number = 99 99=7*7+5*5+4*4+3*3 ......

阅读全文(4243) | 评论:5

81.角谷猜想(2005-09-10 15:18:00)

摘要:81.角谷猜想 日本一位中学生发现一个奇妙的“定理”,请角谷教授证明,而教授无能为力,于是产生角谷猜想。猜想的内容是:任给一个自然数,若为偶数除以2,若为奇数则乘3加1,得到一个新的自然数后按照上面的法则继续演算,若干次后得到的结果必然为1。请编程验证。 *问题分析与算法设计 本题是一个沿未获得一般证明的猜想,但屡试不爽,可以用程序验证。 题目中给出的处理过程很清楚,算法不需特殊设计,可按照题目的叙述直接进行证。 *程序与程序注释 #include<stdio.h> void main() { int n,count=0; printf("Please enter number:"); scanf("%d",&n); /*输入任一整数*/ do{ if(n%2) { n=n*3+1; /*若为奇数,n乘3加1*/ printf("[%d]:%d*3+1=%d\n",++count,(n-1)/3,n); } else { n/=2; /*若为偶数n除以2*/ printf("[%d]: %d/2=%d\n",++count,2*n,n); } }while(n!=1); /*n不等于1则继续以上过程*/ } ......

阅读全文(3354) | 评论:5