UVa227:Puzzle

題目名稱:謎題

題目描述:

有一個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);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章