這篇是針對推箱子游戲而寫的,某個時候在學C語言,最近轉到windows設計,不知道是否有同樣的感受,后面的東西學了,前面的就有點生疏了。其實,我的理解是,注意力轉移了,當集中於當前問題的時候就會忽略以前的某些知識。這也說明,人的注意力是隨着時間,學習內容的不同在起變化。但是,只要稍微復習一下就能很快恢復。
問題:比如一個文本文件的內容如下:
[1]
0000000000000000
0000000000000000
0000000000000000
0000011100000000
0000013100000000
0000012111100000
0001114243100000
0001324611100000
0001111410000000
0000001310000000
0000001110000000
0000000000000000
0000000000000000
0000000000000000
[2]
0000000000000000
0000000000000000
0001111100000000
0001622100000000
0001244101110000
0001242101310000
..................(截選)
[]內是序號,往下延伸,每個[]下面是14行16列的數據,我想獲取給定的某個序號下面的這個二維數組數據,比如說,序號[10]下面的14*16列的數據。
————————————————————————————————————————————————————————————
在這個問題之前,首先理解一下流的概念,簡易記錄一下:
流有很多種,包括輸入流,輸出流等,這里只說輸入流,比如stdin,在調用scanf函數讀取這個流的時候,有幾個需要注意的要點:
首先,scanf忽略前面的空格,回車等等字符
其次,在讀取的時候,流中還有一個指針在不停的移動,也就是游標。做個圖來說明:
想輸入一個數據ABCD到字符串中,在開始的時候,故意敲入空格+回車鍵,這對scanf無影響,它會忽略,一直讀取ABCD,又遇到一個回車,游標最終停留在回車這個字符上。
這個回車鍵被scanf獲取了嗎?其實是沒有的,比如接下來可以用c=getchar(),就可以捕捉到這個回車字符。
同理,將stdin換成文件fp,一樣遵循這個規則。因為不是專項整理流的問題,所以只簡單概括到這。
————————————————————————————————————————————————————————
對於上題的解法是,從fp中讀取一個字符串,然后和待匹配的序號比較,比如和字符串"[10]"比較,如果相等,則游標就定位在[10]之后的位置。
觀察上面的文本文件,每一行之后就是一個回車,所以每次從fp中讀取一個串,要么讀的是[xx],要么讀的就是二維數組的一行數據,當然,這個串的存儲長度也至少大於一行的數據,至少為16個。
具體
首先獲取要取的序號,定義一個字符串,將之寫入其中。
char str[10]; sprintf(str,"[%d]",n);
接着,按串讀取fp,與之相比較。
FILE *fp=fopen("map.txt","rb"); //打開文本文件 if(fp==NULL) return; char data[20]; fscanf(fp,"%s",data);//先讀入一個串 while(strncmp(str,data,strlen(str))!=0)//相等返回0 { if(fscanf(fp,"%s",data)==NULL)//循環讀取,游標也在移動 break; }
假如讀取到[10],符合題意了,則游標就正停留在[10]的后面,下面就是[10]序號下的14*16的數據。這個地方還有一個用處,比如說,一共有40關,假如玩家通關了,再掃描文件肯定找不到[41]的序號,就可以判定玩家通關了。
因為要讀取14*16,相當於二維數組,處理如下:
for(int y=0;y<14;y++) //行 { fscanf(fp,"%s",data);//讀取一行 for(int x=0;x<16;x++)//列 { map[y][x]=data[x]-'0';//字符變整型,填充map[][],map[][]是一個整型的二維數組,所以需要轉換 ...... } }
這樣,問題就解決了。
完整的示例代碼
void LoadMap(int n) //載入地圖,主要負責填充map[][]的二維數組,map[][]是操縱畫圖的關鍵 { char str[10]; sprintf(str,"[%d]",n); FILE *fp=fopen("map.txt","rb"); //打開文件,讀取地圖數據,所謂地圖,就是用數字來(標示)操縱位圖塊 if(fp==NULL) return; char data[20]; fscanf(fp,"%s",data);//先讀入一個串 while(strncmp(str,data,strlen(str))!=0)//相等返回0 { if(fscanf(fp,"%s",data)==NULL)//循環讀取,游標也在移動 break; } for(int y=0;y<14;y++) //行 { fscanf(fp,"%s",data);//讀取14行 for(int x=0;x<16;x++)//列 { map[y][x]=data[x]-'0';//字符變整型,填充map[][] if(map[y][x]==MANATROAD||map[y][x]==MANATDESTINATION) { manposition.x=x;//人的位置 manposition.y=y; } } } fclose(fp); }
*注:這段程序,每次都要掃描整個文件,獲取與序號相同的串,由於文件比較小,影響也不是太大。