題目名稱:謎題
題目描述:
有一個55的網格,其中恰好有一個格子是空的,其他格子各有一個字母,一共有四種指令:A,B,L,R,分別表示把空格上、下、左、右的相鄰字母移到空格中。輸入初始網格和指令序列(分別以數字0結束),輸出指令執行完畢後的網格。如果有非法指令,應輸出”This puzzle has no final configuration.”
1.第一遍理解題意測試程序:
1)沒有考慮輸出輸入
2)將char類型先替換成int類型
3)沒有考慮多次輸出輸入
#include<stdio.h>
#include<string.h>
#define maxn 10000
int S[maxn][maxn];
int ope[maxn];
int main () {
int i,j,m,n;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
scanf("%d",&S[i][j]);
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(S[i][j] == 9 )
{
m=i;
n=j;
break;
}
printf("=====================================\n");
printf("m=%d\nn=%d\n",m,n);
printf("=====================================\n");
int e;
for(e=0;e<7;e++){
scanf("%c",&ope[e]);
}
printf("=====================================\n");
int d;
char temp;
for(d=0;d<7;d++){
if(ope[d]=='A')
{
temp=S[m][n];
S[m][n]=S[m-1][n];
S[m-1][n]=temp;
m--;
}
else if(ope[d]=='B')
{
temp=S[m][n];
S[m][n]=S[m+1][n];
S[m+1][n]=temp;
m++;
}
else if(ope[d]=='R')
{
temp=S[m][n];
S[m][n]=S[m][n+1];
S[m][n+1]=temp;
n++;
}
else if(ope[d]=='L')
{
temp=S[m][n];
S[m][n]=S[m][n-1];
S[m][n-1]=temp;
n--;
}
}
for(i=0;i<5;i++) {
for(j=0;j<5;j++)
printf("%5d",S[i][j]);
printf("\n");
}
printf("=====================================\n");
return 0;
}
從運行結果可知大體空位(此處以數字9代替)移動方位正確。
存在問題:
1)操作序列變成了ARRBBLL,多了一個L才使9位置移動正確。並且通過試驗知道,最後一個L不起作用。
2)嘗試用char替換int類型,可是運行結果卻在m,n定位就出錯了。
2.第二次調整代碼:
參考文章:
http://blog.csdn.net/to_xidianhph_youth/article/details/36623797
(第一次寫的時候沒保存,結果中間好多錯誤也忘記了,但是最終錯誤在於使用scanf()函數,和gets()函數,gets()使得讀入字符和操作數正確,整個程序也就正確啦)
#include<stdio.h>
#include<string.h>
#define maxn 20
#define command 10000
char S[maxn][maxn];
char ope[command];
int main () {
int i,j,m=0,n=0;
gets(S[0]);
gets(S[1]);
gets(S[2]);
gets(S[3]);
gets(S[4]);
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(S[i][j] == ' ' )
{
m=i;
n=j;
break;
}
gets(ope);
int len ;
len = strlen(ope);
int d;
char temp=' ';
for(d=0;d<len;d++){
if(ope[d]=='A' && m!=0)
{
temp=S[m][n];
S[m][n]=S[m-1][n];
S[m-1][n]=temp;
--m;
}
if(ope[d]=='B' && m!=4)
{
temp=S[m][n];
S[m][n]=S[m+1][n];
S[m+1][n]=temp;
++m;
}
if(ope[d]=='R' && n!=4)
{
temp=S[m][n];
S[m][n]=S[m][n+1];
S[m][n+1]=temp;
++n;
}
if(ope[d]=='L' && n!=0)
{
temp=S[m][n];
S[m][n]=S[m][n-1];
S[m][n-1]=temp;
--n;
}
}
for(i = 0; i < 5; i++)
{
printf("%c %c %c %c %c\n", S[i][0], S[i][1], S[i][2], S[i][3], S[i][4]);
}
return 0;
}
運行結果:(截圖總上傳不上,先將就看看這個)
AAAAA
BBBBB
C CCC
DDDDD
EEEEE
ARRBBL
A A A A A
B B B C B
C B C D C
D D D D
E E E E E
3.優化代碼:
根據題目要求要以0爲結尾,改動如下:
gets(ope);
int len ;
int flag=1;
len = strlen(ope);
int d;
char temp=' ';
for(d=0;d<len;d++){
if(s[len-1] == '0' || s[i] == 'A' || s[i] == 'R' || s[i] == 'B' || s[i] == 'L' ) {
if(ope[d]=='A' && m!=0)
{
temp=S[m][n];
S[m][n]=S[m-1][n];
S[m-1][n]=temp;
--m;
}
if(ope[d]=='B' && m!=4)
{
temp=S[m][n];
S[m][n]=S[m+1][n];
S[m+1][n]=temp;
++m;
}
if(ope[d]=='R' && n!=4)
{
temp=S[m][n];
S[m][n]=S[m][n+1];
S[m][n+1]=temp;
++n;
}
if(ope[d]=='L' && n!=0)
{
temp=S[m][n];
S[m][n]=S[m][n-1];
S[m][n-1]=temp;
--n;
}
}
else
flag=0;
}
if(flag)
{
for(i = 0; i < 5; i++)
printf("%c %c %c %c %c\n", S[i][0], S[i][1], S[i][2], S[i][3], S[i][4]);
}
else
printf("This puzzle has no final configuration.\n");
5.//預留:以後再想想可以不間斷的輸入等等和格式優化
6.總結:
參考文章:http://www.cnblogs.com/qinjunni/archive/2012/03/03/2378323.html
http://www.cnblogs.com/JMDWQ/archive/2012/03/06/2381302.html
*****gets
【1】函數:gets(字符指針)
【2】頭文件:stdio.h(c中),c++不需包含此頭文件
【3】原型:char*gets(char*buffer);
【4】功能:從stdin流中讀取字符串,直至接受到換行符或EOF時停止,並將讀取的結果存放在buffer指針所指向的字符數組中。換行符不作爲讀取串的內容,讀取(接受)的換行符被轉換爲null值,並由此來結束字符串。
【5】返回值:讀入成功,返回與參數buffer相同的指針;讀入過程中遇到EOF(End-of-File)或發生錯誤,返回NULL指針。所以在遇到返回值爲NULL的情況,要用ferror或feof函數檢查是發生錯誤還是遇到EOF。
【6】注意:本函數可以無限讀取,不會判斷上限,所以程序員應該確保buffer的空間足夠大,以便在執行讀操作時不發生溢出。如果溢出,多出來的字符將被寫入到堆棧中,這就覆蓋了堆棧原先的內容,破壞一個或多個不相關變量的值,爲了避免這種情況,我們可以用fgets()來替換gets()。這個事實導致gets函數只適用於玩具程序。在V7的手冊(1979年)中說明:爲了向後兼容,gets刪除換行符,gets並不將換行符存入緩衝區。
========================================================
【1】scanf() 會忽略行開頭的所有空格,並以空格、換行符結束輸入;
使用getchar()讀取scanf語句執行後,緩衝區留下的換行符,
gets讀入以任何字符開始的字符串,以換行符結束,但之後會丟棄換行符並以’\0’代替;
【2】在數據大量的情況下,用gets讀取快於scanf()10倍以上(注:來自pudn,只有一段開頭話)
【3】第一:要注意不同的函數是否接受空格符、是否捨棄最後的回車符的問題!
讀取字符時:
scanf()以Space、Enter、Tab結束一次輸入,不會捨棄最後的回車符(即回車符會殘留在緩衝區中);
getchar()以Enter結束輸入,也不會捨棄最後的回車符;
讀取字符串時:
scanf()以Space、Enter、Tab結束一次輸入
gets()以Enter結束輸入(空格不結束),接受空格,會捨棄最後的回車符!
第二:爲了避免出現上述問題,必須要清空緩衝區的殘留數據,可以用以下的方法解決:
方法1:C語言裏提供了函數清空緩衝區,只要在讀數據之前先清空緩衝區就沒問題了!
這個函數是fflush(stdin)。
方法2:自己取出緩衝區裏的殘留數據。
scanf(“%[^\n]”,string);