將以上游戲雙方倒一下,請人想一個(gè)四位的整數(shù),計(jì)算機(jī)來猜,人給計(jì)算機(jī)提示信息,最終看計(jì)算機(jī)用幾次猜出一個(gè)人“想”的數(shù)。請編程實(shí)現(xiàn)。
*問題分析與算法設(shè)計(jì)
解決這類問題時(shí),計(jì)算機(jī)的思考過程不可能象人一樣具完備的推理能力,關(guān)鍵在于要將推理和判斷的過程變成一種機(jī)械的過程,找出相應(yīng)的規(guī)則,否則計(jì)算機(jī)難以完成推理工作。
基于對問題的分析和理解,將問題進(jìn)行簡化,求解分為兩個(gè)步聚來完成:首先確定四位數(shù)字的組成,然后再確定四位數(shù)字的排列順序??梢粤谐鋈缦乱?guī)則:
1)分別顯示四個(gè)1,四個(gè)2,......,四個(gè)0,確定四位數(shù)字的組成。
2)依次產(chǎn)生四位數(shù)字的全部排列(依次兩兩交換全部數(shù)字的位置)。
3)根據(jù)人輸入的正確數(shù)字及正確位置的數(shù)目,進(jìn)行分別處理:
(注意此時(shí)不出現(xiàn)輸入的情況,因?yàn)樵谒膫€(gè)數(shù)字已經(jīng)確定的情況下,若有3個(gè)位置正確,則第四個(gè)數(shù)字的位置必然也是正確的)
若輸入4:游戲結(jié)束。
判斷本次輸入與上次輸入的差值
若差為2:說明前一次輸入的一定為0,本次輸入的為2,本次交換的兩個(gè)數(shù)字的位置是正確的,只要交換另外兩個(gè)沒有交換過的數(shù)字即可結(jié)束游戲。
若差為-2:說明前一次輸入的一定為2,本次的一定為0。說明剛交換過的兩個(gè)數(shù)字的位置是錯(cuò)誤的,只要將交換的兩個(gè)數(shù)字位置還原,并交換另外兩個(gè)沒有交換過的數(shù)字即可結(jié)束游戲。
否則:若本次輸入的正確位置數(shù)<=上次的正確位置數(shù)
則恢復(fù)上次四位數(shù)字的排列,控制轉(zhuǎn)3)
否則:將本次輸入的正確位置數(shù)作為“上次輸入的正確位置數(shù)”,控制轉(zhuǎn)3)。
*程序與程序注釋
#include
#include
void bhdy(int s,int b);
void prt();
int a[4],flag,count;
void main()
{
int b1,b2,i,j,k=0,p,c;
printf("Game guess your number in mind is # # # #.\n");
for(i=1;i<10&&k<4;i++) /*分別顯示四個(gè)1~9確定四個(gè)數(shù)字的組成*/
{
printf("No.%d:your number may be:%d%d%d%d\n",++count,i,i,i,i);
printf("How many digits have bad correctly guessed:");
scanf("%d",&p); /*人輸入包含幾位數(shù)字*/
for(j=0;j
a[k+j]=i; /*a[]:存放已確定數(shù)字的數(shù)組*/
k+=p; /*k:已確定的數(shù)字個(gè)數(shù)*/
}
if(k<4) /*自動(dòng)算出四位中包的個(gè)數(shù)*/
for(j=k;j<4;j++)
a[j]=0;
i=0;
printf("No.%d:your number may be:%d%d%d%d\n",++count,a[0],a[1],a[2],a[3]);
printf("How many are in exact positions:"); /*順序顯示四位數(shù)字*/
scanf("%d",&b1); /*人輸入有幾位位置是正確的*/
if(b1==4){prt();exit(0);} /*四位正確,打印結(jié)果。結(jié)束游戲*/
for(flag=1,j=0;j<3&&flag;j++) /*實(shí)現(xiàn)四個(gè)數(shù)字的兩兩(a[j],a[k]交換*/
for(k=j+1;k<4&&flag;k++)
if(a[j]!=a[k])
{
c=a[j];a[j]=a[k];a[k]=c; /*交換a[j],a[k]*/
printf("No.%d:Your number may be: %d%d%d%d\n",++count,a[0],a[1],a[2],a[3]);
printf("How many are in exact positins:");
scanf("%d",&b2); /*輸入有幾個(gè)位置正確*/
if(b2==4){prt();flag=0;} /*若全部正確,結(jié)束游戲*/
else if(b2-b1==2)bhdy(j,k); /*若上次與本次的差為2,則交換兩個(gè)元素即可結(jié)束*/
else if(b2-b1==-2) /*若上次與本次的差為-2,則說明已交換的(a[j],a[k])是錯(cuò)誤的
將(a[j],a[k]還原后,只要交換另外兩個(gè)元素即可結(jié)束游戲*/
{
c=a[j];a[j]=a[k];a[k]=c;
bhdy(j,k);
}
else if(b2<=b1)
{
c=a[j];a[j]=a[k];a[k]=c; /*恢復(fù)交換的兩個(gè)數(shù)字*/
}
else b1=b2; /*其它情況則將新輸入的位置信息作為上次的位置保存*/
}
if(flag) printf("You input error!\n"); /*交換結(jié)果仍沒結(jié)果,只能是人輸入的信息錯(cuò)誤*/
}
void prt() /*打印結(jié)果,結(jié)束游戲*/
{
printf("Now your number must be %d%d%d%d.\n",a[0],a[1],a[2],a[3]);
printf("Game Over\n");
}
void bhdy(int s,int b)
{
int i,c=0,d[2];
for(i=0;i<4;i++) /*查找s和b以外的兩個(gè)元素下標(biāo)*/
if(i!=s&&i!=b) d[c++]=i;
i=a[d[1>;a[d[1>=a[d[0>; a[d[0>=i; /*交換除a[s]和a[b]以外的兩個(gè)元素*/
prt(); /*打印結(jié)果,結(jié)束游戲*/
flag=0;
}
*運(yùn)行示例假設(shè)人想的四位數(shù)是:7215
Game Begin
Now guess your number in mind is # # # #.
No.1:your number may be:1111
*問題的進(jìn)一步討論
本程序具有邏輯結(jié)構(gòu)清析、算法簡單正確的優(yōu)點(diǎn),但在接受人的輸入信息時(shí)缺少必要的出錯(cuò)保護(hù)功能,同時(shí)在進(jìn)行第三步推理過程中沒有保留每次猜出的數(shù)字位置信息及人輸入的回答,這樣對于每次人輸入的信息就無法進(jìn)行合法性檢查,即無法檢查人的輸入信息是否自相矛盾;同晨也無法充分利用前面的結(jié)果。
這些缺陷是可以改進(jìn)的,但最后一個(gè)問題改進(jìn)難度較大,留給大家自己去完成。
*思考題
“一條龍游戲”。在一個(gè)3×3的棋盤上,甲乙雙方進(jìn)行對棄,雙方在棋盤上輪流放入棋子,如果一方的棋子成一直線(橫、豎或斜線),則該方贏。請編寫該游戲程序?qū)崿F(xiàn)人與機(jī)器的比賽。比賽結(jié)果有三種:輸、贏或平。
在編程過程中請首先分析比賽中怎樣才能獲勝,找出第一步走在什么位置就最可能贏。