2018年10月30日 星期二

[C語言 練習 2-1]串鍊連結 動態儲存 堆疊練習 迷宮

之前的迷宮是用副程式的遞迴寫出來的,想改成跌代的方式,努力了一陣子

但還只想得出  資料結構 (不過還是遞迴..) 串列連結 來改寫,也順便練習一下怎麼利用串列聯結來寫程式,我是打算用堆疊push pop來幫助
堆疊就像是放一個東西在桶內,先放進去在最下面,最後一個放的在最上面.
拿出來時放在最上面(最後放的)先拿出來,最先放的則在最底部.最後才拿出來.


_______________________________________
在查覺到 .cpp是c++的檔案後,我立即轉用.c來查驗
在C語言
我程式中犯的錯
1.宣告副程式時,void push(int data,temp_dir *head)內的 結構 宣告時忘記加上資料形態
正確版為void push(int data,struct temp_dir *head)
2.轉換形態 轉換為結構時 我也忘記要用struct
3.int 值不能是NULL
以下副程式皆有改過與注意
_______________________________________
另外有關打牆副程式
其實有過多的定義,在沒拜訪過的狀態下,打到變成無牆的情形只會有兩種
(會無牆的狀態只會出現在轉角處)
1.往下 打一次 下方點的上牆,此時(x,y)座標變換為下方點,往右 打一次(自己的)右牆  (此時無牆)
2.往左 打一次 左方點的右牆,此時(x,y)座標變換為左方點,往上 打一次(自己的)上牆 (此時無牆)

而 上述兩種情況的座標值為(x,y) 可以合併.
其餘 方式  無牆狀況不可能發生
_______________________________________
以下是流程圖
迷宮更改流程圖

以下是push 的副程式 練習

//串列聯結 push 
#include <stdio.h>
#include <stdlib.h>
struct temp_dir{ //push 的資訊 
 int data; //資訊 
 temp_dir *next; //指向下一個座標 
};
void push(int data,struct temp_dir *head){ 
 struct temp_dir *temp;  
 temp=(struct temp_dir* )malloc(sizeof(struct temp_dir*)); 
 //向系統要一塊  記憶體 
 if(temp!=NULL){  
 //如果temp有值代表有從記憶體要到空間 
  temp->next=head->next;
  //最後push進的一定會在最上面(第一位),
  //原本最上面(第一位)會變成第二位 
  head->next=temp;//push的最上面(第一位) 
  temp->data=data;
 }
}
int main()
{
 temp_dir head;
 head.data=0;
 head.next=0;
 push(5,&head); //第一個放進去 
 push(10,&head); //第二個放進去 
 printf("1.%d\n",(head.next)->data);
 //(head.next)->data 寫法可以寫成 *(head.next).data  
 printf("2.%d\n",((head.next)->next)->data); 
 system("pause");
 return 0;
}

_____________________________________

void start_go(int x,int y){ 
//以下部分printf是用來debug看看有沒有哪邊出錯 
 int limit=4,i,k,stop=5,dir[4];
 struct temp_infor head;
 //初始化 x,y,i,next的參數 ,
 head.x=0; //在C中,int 不能設定NULL,C++可以 
 head.y=0;
 head.i=0;
 for(i=0;i<4;i++)
  head.dir[i]=0;
 head.next=NULL;
 //亂數初始化 
 rand_dir(dir);
 //當pop沒法在發值時,結束,一開始stop先放著 
 while(stop>0){
  //printf("[%d,%d]",x,y); //檢查當前座標用 
  for(i=0;i<limit;i++){ //當嘗試剩餘的方向   
  // printf("%d",i); //方向測試了幾次 
   set_visted(x,y);//設定x,y座標值拜訪 
   if(visted_possible(next_x(x,dir[i]),next_y(y,dir[i]))){
   //如果 未被拜訪且下個點不是邊界的話 
   // printf("[%d,%d]",x,y); //顯示當前座標 
   // printf("+"); //用於查看是否進入下一次迴圈 
    try_wall(x,y,dir[i]);// 打掉牆壁副程式 
    //把當前x,y,i,dir方向陣列存起來,放進桶內 
    push(x,y,i,dir,&head);
    //x等於下個x,下方y同樣 
    x=next_x(x,dir[i]); 
    y=next_y(y,dir[i]); 
    limit=4; //初始化設定 ,因為 下個點後,可走方向限制為4 
    i=-1;  
    //在迴圈結束後,i會相加,所以這邊初始設定i為 -1,等等會加到0 
    rand_dir(dir);
    //亂數方向陣列 
   }  
  }
  //如果找不到方向
  stop=pop(&x,&y,&limit,dir,&head); //當pop彈不出來時,stop值為 0
  //printf("-\n"); //檢查彈出狀態 
 } 
}
_____________________________________
有關於打牆副程式修改 (順便與方向的判斷合併在一起)

void try_wall(int x,int y,int dir){//上0 左1 下2 右3
      //3上右牆 2上牆 1右牆 0無牆   
 if(dir==0&&maze[index_xy(x,y)].up_right_wall==3) //往上 且 右上牆 健在 
  maze[index_xy(x,y)].up_right_wall=1;
 else if(dir==1&&maze[index_xy(x-1,y)].up_right_wall==3) //往左 且 右上牆 健在 
  maze[index_xy(x-1,y)].up_right_wall=2;
 else if(dir==2&&maze[index_xy(x,y+1)].up_right_wall==3) //往下 且 右上牆 健在 
  maze[index_xy(x,y+1)].up_right_wall=1;
 else if(dir==3&&maze[index_xy(x,y)].up_right_wall==3) //往右 且 右上牆 健在 
  maze[index_xy(x,y)].up_right_wall=2; 
 else //其餘情況 
  maze[index_xy(x,y)].up_right_wall=0;
}

_____________________________________
https://drive.google.com/drive/folders/11A25adWcUSh9F1QNZpl9AelgS9wqK-ur?usp=sharing

沒有留言:

張貼留言

[C語言 練習 3]串鍊連結 創建-刪除-插入-檢視

如果程式沒有練習,有些小細節很容易錯過... 就像一開始我的串列連結  完全沒注意到要在 外面設定一個head 結構link data儲存 資料 *next 指標next指向 下個結構 struct link{ int data; struct link *nex...