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

📄 09.txt

📁 CC++语言程序百例精解 非常经典的C
💻 TXT
📖 第 1 页 / 共 2 页
字号:
printf("\n\006 "); /*打印黑桃标记*/
for(i=0;i<13;i++) /*将数组中的值转换为相应的花色*/
if(b[i]/13==0) printf("%c ",n[b[i]%13]); /*该花色对应的牌*/
printf("\n\003 "); /*打印红桃标记*/

for(i=0;i<13;i++)
if((b[i]/13)==1) printf("%c ",n[b[i]%13]);
printf("\n\004 "); /*打印方块标记*/
for(i=0;i<13;i++)
if(b[i]/13==2) printf("%c ",n[b[i]%13]);
printf("\n\005 "); /*打印梅花标记*/
for(i=0;i<13;i++)
if(b[i]/13==3||b[i]/13==4) printf("%c ",n[b[i]%13]);
printf("\n");
}

int comp(const void *j,const void *i) /*qsort调用的排序函数*/
{
return(*(int*)i-*(int*)j);
}

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);
int 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) /*判断游戏是否结束
若还没有完成棋子的交换则继续进行循环*/
{
flag=1; /*flag 为棋子移动一步的标记1:尚未移动棋子 0:已经移动棋子*/
for(i=0;flag&&i<5;i++) /*若白子可以向右跳过黑子,则白子向右跳*/
if(t[i]==1&&t[i+1]==2&&t[i+2]==0)
{change(&t[i],&t[i+2]); print(t); flag=0;}
for(i=0;flag&&i<5;i++) /*若黑子可以向左跳过白子,则黑子向左跳*/
if(t[i]==0&&t[i+1]==1&&t[i+2]==2)
{change(&t[i],&t[i+2]); print(t); flag=0;}
for(i=0;flag&&i<6;i++) /*若向右移动白子不会产生阻塞,则白子向右移动*/
if(t[i]==1&&t[i+1]==0&&(i==0||t[i-1]!=t[i+2]))
{change(&t[i],&t[i+1]); print(t);flag=0;}
for(i=0;flag&&i<6;i++) /*若向左移动黑子不会产生阻塞,则黑子向左移动*/
if(t[i]==0&&t[i+1]==2&&(i==5||t[i-1]!=t[i+2]))
{ change(&t[i],&t[i+1]); print(t);flag=0;}
}
}
void print(int a[])
{
int i;
printf("No. %2d:………………………..\n",number++);
printf(" ");
for(i=0;i<=6;i++)
printf(" | %c",a[i]==1?'*':(a[i]==2?'@':' '));
printf(" |\n ………………………..\n\n");
}
void change(int *n,int *m)
{
int term;
term=*n; *n=*m; *m=term;
}

*问题的进一步讨论
本题中的规则不仅适用于三个棋子的情况,而且可以推而广之,适用于任意N个棋子的情况。读者可以编程验证,按照本规则得到的棋子移动步数是最少的。
事实上,制定规则是解决这类问题的关键。一个游戏程序“思考水平的高低,完全取决于使用规则的好坏。”

*思考题
有两个白子和两个黑子如下左图布置:

○ . ○
. . .
● . ●

棋盘中的棋子按”马步“规则行走,要求用最少的步数将图中白子和黑子的位置进行交换,最终结果如下一幅图所示。
● . ●
. . .
○ . ○

88.常胜将军

现有21根火柴,两人轮流取,每人每次可以取走1至4根,不可多取,也不能不取,谁取最后一楰火柴谁输。请编写一个程序进行人机对弈,要求人先取,计算机后取;计算机一方为“常胜将军”。

*问题分析与算法设计
在计算机后走的情况下,要想使计算机成为“常胜将军”,必须找出取 关键。根据本题的要求枷以总结出,后走一方取子的数量与对方刚才一步取子的数量之和等于,就可以保证最后一个子是留给先取子的那个人的。
据此分析进行算法设计就是很简单的工作,编程实现也十分容易。

*程序说明与注释
#include<stdio.h>
int 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根),则后走的一方就不一定能够保持常胜了,很可能改变成“常败”。此时后走一方的胜负就与火柴的初始数量和每次允许取的火柴数量的最大值有直接关系,请编写程序解决这一问题。

89.抢30

这是中国民间的一个游戏。两人从1开始轮流报数,每人每次可报一个数或两个连续的数,谁先报到30,谁就为胜方。

*问题分析与算法设计
本题与上题类似,算法也类似,所不同的是,本谁先走第一步是可选的。若计算机走第一步,那么计算机一定是赢家。若人先走一步,那么计算机只好等待人犯错误,如果人先走第一步且不犯错误,那么人就会取胜;否则计算机会抓住人的一次错误使自己成为胜利者。

*程序说明与注释
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int input(int t);
int copu(int s);
int 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(a>2||a<1||t+a>30);
return t+a; /*返回当前的已经取走的数累加和*/
}
int copu(int s)
{
int c;
printf("Computer count:");
if((s+1)%3==0) /*若剩余的数的模为1,则取1*/
printf(" %d\n",++s);
else if((s+2)%3==0)
{
s+=2; /*若剩余的数的模为2,则取2*/
printf(" %d\n",s);
}
else
{
c=random(2)+1; /*否则随机取1或2*/
s+=c;
printf(" %d\n",s);
}
return s;
}

*思考题
巧夺偶数。桌子上有25颗棋子,游戏双方轮流取子,每人每次最少取走一颗棋子,最多可取走3颗棋子。双方照这样取下去,直到取光所有的棋子。于是双方手中必然一方为偶数,一方为奇数,偶数方为胜者。请编程实现人机游戏。

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>
int 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);
do{
printf("How many mountains do you wish movw away?");
scanf("%d",&x);
if(x<1||x>k||x>n) /*判断搬山数是否符合要求*/
{
printf("IIIegal,again please!\n");
continue;
}
n-=x;
printf("There are %d mountains left now.\n",n);
if(!n)
{
printf("……………I win. You are failure……………\n\n");cc++;
}
else
{
y=(n-1)%(k+1); /*求出最佳搬山数*/
if(!y) y=1;
n-=y;
printf("Copmputer move %d mountains away.\n",y);
if(n) printf(" There are %d mountains left now.\n",n);
else
{
printf("……………I am failure. You win………………\n\n");
pc++;
}
}
}while(n);

}
printf("Games in total have been played %d.\n",cc+pc);
printf("You score is win %d,lose %d.\n",pc,cc);
printf("My score is win %d,lose %d.\n",cc,pc);
}

*思考题
取石子游戏。将石子分成若干堆,每堆有若干粒,参加游戏的甲乙两方轮流从任意一堆中取走任意个石子,甚至可以全部取走,但每次只能在一堆中取,不允许从这堆取一些,再从另一堆中取一些。直到谁取走最后一粒石子谁就获胜。请编程进行人机对弈。

⌨️ 快捷键说明

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