C++學習(三十七)(C語言部分)之 鏈式棧(推箱子實現)

来源:https://www.cnblogs.com/Yuuki-/archive/2019/04/01/10639157.html
-Advertisement-
Play Games

用鏈表實現棧一開始在表頭插入,就要一直在表頭插入一開始在表尾插入,就要一直在表頭插尾表頭當棧底 也可以把表尾當棧底 實現的測試代碼筆記如下: 附: 推箱子實現,代碼筆記如下所示: 最後實現效果如下所示; 2019-04-01 21:33:15 ...


用鏈表實現棧
一開始在表頭插入,就要一直在表頭插入
一開始在表尾插入,就要一直在表頭插尾
表頭當棧底 也可以把表尾當棧底

實現的測試代碼筆記如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 
  5 //節點的結構體
  6 typedef struct Node
  7 {
  8     char *name;
  9     struct Node *pNext;
 10 }LIST, *PLIST;
 11 
 12 //1.創建“火車頭”  創建一個表頭
 13 void CreateListHead(PLIST *p_list)  //傳入頭結點指針 給他分配記憶體
 14 {
 15     //一級指針 形參和實參結合時
 16     //PLIST p_list = p_head;  形參和實參結合時候的賦值
 17     //p_list 改變 是不影響到p_head  就好像是A給B發送了一個文件 B對文件進行了修改,是不會影響A手中的文件
 18 
 19     //要改變一級指針的實參 函數要傳入一級指針的地址 保存一級指針的地址 要使用二級指針
 20     *p_list = (PLIST)malloc(sizeof(LIST));
 21     (*p_list)->pNext = NULL;
 22 
 23 }
 24 
 25 //實現一個棧 
 26 //2.寫入棧函數
 27 void Push_Stack(PLIST p_list, char *name)
 28 {
 29     //頭插法
 30     PLIST node = (PLIST)malloc(sizeof(LIST));
 31     //node->name - name;  可以這麼寫 但是如果存入得扇區記憶體,會被釋放掉 就會出錯
 32     node->name = (char *)malloc(sizeof(char)*strlen(name) + 1);
 33     strcpy(node->name, name);
 34     node->pNext = p_list->pNext;
 35     p_list->pNext = node;
 36 }
 37 
 38 //3.獲取棧頂元素
 39 char * GetStackTop(PLIST p_list)
 40 {
 41     //如果不是空 就返回頭結點的下一個節點的name
 42     PLIST p_Temp = p_list->pNext;
 43     if (p_Temp != NULL)
 44     {
 45         return p_Temp->name;
 46     }
 47     return NULL;  //說明棧是空
 48 }
 49 
 50 //4.出棧
 51 void Pop_Stack(PLIST p_list)
 52 {
 53     //相當於刪除結點  之前是頭插法  那麼最後一個在最前面
 54     PLIST p_Temp = p_list->pNext;
 55     if (p_Temp != NULL)
 56     {
 57         //p_remp保存第一個節點的地址
 58         p_Temp = p_list->pNext;
 59         //讓頭結點的pnext連接到第二個節點
 60         p_list->pNext = p_Temp->pNext;
 61     }
 62     free(p_Temp);  //釋放記憶體  釋放掉第一個節點 是釋放p_temp裡面所保存的記憶體 而不是釋放指針變數
 63 }
 64 
 65 //5.判斷棧是否為空
 66 int isEmpty(PLIST p_list)
 67 {
 68     //如果棧為空 返回1
 69     return p_list->pNext == NULL;
 70 }
 71 
 72 int main()
 73 {
 74     PLIST p_head = NULL;  //作為鏈表的標記
 75     CreateListHead(&p_head);
 76     /*if (NULL == p_head)
 77     {
 78         printf("記憶體分配失敗!\n");
 79     }
 80     else
 81     {
 82         printf("記憶體分配成功!\n");
 83     }*/
 84 
 85     Push_Stack(p_head, "");
 86     Push_Stack(p_head, "");
 87     Push_Stack(p_head, "");
 88     Push_Stack(p_head, "");
 89     Push_Stack(p_head, "");
 90     Push_Stack(p_head, "");
 91     Push_Stack(p_head, "");
 92     Push_Stack(p_head, "");
 93     Push_Stack(p_head, "");
 94     Push_Stack(p_head, "");
 95     Push_Stack(p_head, "");
 96     Push_Stack(p_head, "");
 97     while (!isEmpty(p_head))
 98     {
 99         printf("%s", GetStackTop(p_head));
100         Pop_Stack(p_head);
101     }
102 
103     getchar();
104     return 0;
105 }

附:

 

 

推箱子實現,代碼筆記如下所示:

 

  1 1、main.cpp文件
  2 
  3 //推箱子
  4 //操作說明 WASD表示上下左右移動 空格鍵可以退回到上一步
  5 #if 1
  6 #include<graphics.h>
  7 #include<stdio.h>
  8 #include <conio.h>
  9 
 10 #include "Stack.h"
 11 //地圖
 12 int Map[9][8] = {
 13     0, 0, 1, 1, 1, 1, 1, 0,
 14     1, 1, 1, 0, 0, 0, 1, 0,
 15     1, 3, 5, 4, 0, 0, 1, 0,
 16     1, 1, 1, 0, 4, 3, 1, 0,
 17     1, 3, 1, 1, 4, 0, 1, 0,
 18     1, 0, 1, 0, 3, 0, 1, 1,
 19     1, 4, 0, 7, 4, 4, 3, 1,
 20     1, 0, 0, 0, 3, 0, 0, 1,
 21     1, 1, 1, 1, 1, 1, 1, 1
 22 };
 23 
 24 //實現退回操作
 25 void Retrogress(PLIST p_list)
 26 {
 27     //1.獲取棧頂數據
 28     PLIST p_Temp = GetStackTop(p_list);
 29     if (NULL == p_Temp)
 30     {
 31         return;
 32     }
 33     for (int i = 0; i < 9; i++)
 34     {
 35         for (int j = 0; j < 8; j++)
 36         {
 37             Map[i][j] = p_Temp->p[i][j];
 38         }
 39     }
 40     Pop_Stack(p_list);  //出棧
 41 }
 42 
 43 //對於一個游戲1.初始化  載入圖片
 44 IMAGE g_box, g_dbox, g_people, g_point, g_wall, g_blank;
 45 void Init_Game()
 46 {
 47     loadimage(&g_box, L"./source/box.jpg");  //相對路徑
 48     loadimage(&g_dbox, L"./source/dbox.jpg");
 49     loadimage(&g_people, L"./source/people.jpg");
 50     loadimage(&g_point, L"./source/point.jpg");
 51     loadimage(&g_wall, L"./source/wall.jpg");
 52     loadimage(&g_blank, L"./source/blank.jpg");
 53 }
 54 
 55 //2.載入圖片
 56 void Paint_Game()
 57 {
 58     for (int i = 0; i < 9; i++)
 59     {
 60         for (int j = 0; j < 8; j++)
 61         {
 62             switch (Map[i][j])
 63             {
 64             case 0: //0表示空地
 65                 putimage(j * 45, i * 45, &g_blank);
 66                 break;
 67             case 1: // 1表示牆壁
 68                 putimage(j * 45, i * 45, &g_wall);
 69                 break;
 70             case 3: // 3表示目的地
 71                 putimage(j * 45, i * 45, &g_point);
 72                 break;
 73             case 4: // 4表示箱子
 74                 putimage(j * 45, i * 45, &g_box);
 75                 break;
 76             case 5: // 5表示人
 77                 putimage(j * 45, i * 45, &g_people);
 78                 break;
 79             case 7: // 7表示箱子在目的地   4+3
 80                 putimage(j * 45, i * 45, &g_dbox);
 81                 break;
 82             case 8: // 8表示人在目的地   5+3
 83                 putimage(j * 45, i * 45, &g_people);
 84                 break;
 85             }
 86         }
 87     }
 88 }
 89 
 90 //3.實現人物移動
 91 void MovePeople(PLIST p_list)
 92 {
 93     int i, j;
 94     for (i = 0; i < 9; i++)
 95     {
 96         for (j = 0; j < 8; j++)
 97         {
 98             //找到人的位置
 99             if (Map[i][j] == 5 || Map[i][j] == 8)
100             {
101                 //if成立說明找到人
102                 break;
103             }
104         }
105         if (Map[i][j] == 5 || Map[i][j] == 8)
106         {
107             //if成立說明找到人
108             break;
109         }
110     }
111     switch (getch())
112     {
113 //表示往左邊移動
114     case 'a':  
115         //人的左邊是空地 或者 是目的
116         if (Map[i][j - 1] == 0 || Map[i][j - 1] == 3)
117         {
118             Map[i][j - 1] += 5;  //人往左邊移動
119             Map[i][j] -= 5;  //人離開了當前位置
120         }//人的左邊是箱子或者是箱子在目的
121         else if (Map[i][j - 1] == 4 || Map[i][j - 1] == 7)
122         {
123             if (Map[i][j - 2] == 0 || Map[i][j - 2] == 3)
124             {
125                 Map[i][j - 2] += 4;
126                 Map[i][j - 1] += 1;
127                 Map[i][j] -= 5;
128             }
129         }
130         //每次移動都要入棧
131         Push_Stack(p_list, Map);
132         break;
133 
134 //表示往右邊
135     case 'd': 
136         //人的右邊是空地 或者 是目的
137         if (Map[i][j + 1] == 0 || Map[i][j + 1] == 3)
138         {
139             Map[i][j + 1] += 5;  //人往左邊移動
140             Map[i][j] -= 5;  //人離開了當前位置
141         }//人的右邊是箱子或者是箱子在目的
142         else if (Map[i][j + 1] == 4 || Map[i][j + 1] == 7)
143         {
144             if (Map[i][j + 2] == 0 || Map[i][j + 2] == 3)
145             {
146                 Map[i][j + 2] += 4;
147                 Map[i][j + 1] += 1;
148                 Map[i][j] -= 5;
149             }
150         }
151         //每次移動都要入棧
152         Push_Stack(p_list, Map);
153         break;
154 
155 //表示往上邊移動
156     case 'w':  
157         //人的上邊是空地 或者 是目的
158         if (Map[i - 1][j] == 0 || Map[i - 1][j] == 3)
159         {
160             Map[i - 1][j] += 5;  //人往上邊移動
161             Map[i][j] -= 5;  //人離開了當前位置
162         }//人的上邊是箱子或者是箱子在目的
163         else if (Map[i - 1][j] == 4 || Map[i - 1][j] == 7)
164         {
165             if (Map[i - 2][j] == 0 || Map[i - 2][j] == 3)
166             {
167                 Map[i - 2][j] += 4;
168                 Map[i - 1][j] += 1;
169                 Map[i][j] -= 5;
170             }
171         }
172         //每次移動都要入棧
173         Push_Stack(p_list, Map);
174         break;
175 
176 //表示什麼往下邊移動
177     case 's':  
178         //人的下邊是空地 或者 是目的
179         if (Map[i + 1][j] == 0 || Map[i + 1][j] == 3)
180         {
181             Map[i + 1][j] += 5;  //人往左邊移動
182             Map[i][j] -= 5;  //人離開了當前位置
183         }//人的下邊是箱子或者是箱子在目的
184         else if (Map[i + 1][j] == 4 || Map[i + 1][j] == 7)
185         {
186             if (Map[i + 2][j] == 0 || Map[i + 2][j] == 3)
187             {
188                 Map[i + 2][j] += 4;
189                 Map[i + 1][j] += 1;
190                 Map[i][j] -= 5;
191             }
192         }
193         //每次移動都要入棧
194         Push_Stack(p_list, Map);
195         break;
196     case VK_SPACE: //空格
197         if (!isEmpty(p_list))
198         {
199             Retrogress(p_list);
200             Paint_Game();
201         }
202     }
203 }
204 
205 //4.判斷游戲是否結束
206 int  isWin()
207 {
208     for (int i = 0; i < 9; i++)
209     {
210         for (int j = 0; j < 8; j++)
211         {
212             if (Map[i][j] == 4)
213             {
214                 return 0;
215             }
216         }
217     }
218     return 1;
219 }
220 
221 int main()
222 {
223     initgraph(360, 405);  //初始化圖形界面
224     Init_Game();
225     PLIST p_head = NULL;
226     CreateListHead(&p_head);
227     Paint_Game();
228     while (!isWin())
229     {
230         Paint_Game();
231         MovePeople(p_head);
232     }
233     Paint_Game();
234     getchar();//防止運行到closegraph() 直接退出 看不到效果
235     closegraph(); //關閉圖形界面
236 
237     return 0;
238 }
239 
240 
241 *********************分割線************************
242 
243 
244 2、Stack.h文件
245 #include <stdlib.h>
246 #include <stdio.h>
247 /*
248 以後  頭文件是用來聲明函數 或者類
249 */
250 typedef struct Node
251 {
252     //char *name;   //前面是不是講過動態分配二維數組
253     //通過指針數組來實現
254     int **p;  //目的:分配二維數組用來保存我的地圖信息
255     struct Node * pNext; 
256 }LIST, *PLIST;
257 
258 void CreateListHead(PLIST *p_list);
259 
260 void Push_Stack(PLIST p_list, int(*pArr)[8]);
261 
262 //返回整個結點的內容
263 PLIST  GetStackTop(PLIST p_list);  
264 
265 void Pop_Stack(PLIST p_list);
266 
267 int isEmpty(PLIST p_list);
268 
269 
270 *********************分割線************************
271 
272 
273 3、Stack.cpp文件
274 #include "Stack.h"
275 
276 void Push_Stack(PLIST p_list, int(*pArr)[8])
277 {
278     PLIST node = (PLIST)malloc(sizeof(LIST));
279     //先給二級指針申請記憶體   
280     node->p = (int **)malloc(sizeof(int)* 9); // p就相當於是一個  指針數組  int *p[9]
281     for (int i = 0; i < 9; i++)
282     {
283         //通過這個就能夠分配一個二維數組
284         node->p[i] = (int*)malloc(sizeof(int)* 8);
285     }
286     for (int i = 0; i < 9; i++)
287     {
288         for (int j = 0; j < 8; j++)
289         {
290             node->p[i][j] = pArr[i][j];
291         }
292         //代碼  提升寫代碼能  語法有關
293         //思路  實現功能 首先你要有思路
294         //邏輯   你的方法的邏輯性是否可以
295         // 棧  鏈表
296     }
297     //連接指針
298     node->pNext = p_list->pNext;
299     p_list->pNext = node;
300     // int a[5] 
301     // int *a[5]  a二級指針  
302 }
303 
304 PLIST  GetStackTop(PLIST p_list)
305 {
306     if (p_list->pNext != NULL)
307     {
308         return p_list->pNext;
309     }
310     return NULL;
311 }
312 
313 void Pop_Stack(PLIST p_list)
314 {
315     PLIST p_Temp = NULL;
316     if (p_list->pNext != NULL)
317     {
318         //p_temp保存第一節點的地址
319         p_Temp = p_list->pNext;
320 
321         //讓頭節點的pnext連接到第二個結點
322         p_list->pNext = p_Temp->pNext;
323     }
324     //釋放掉第一個結點
325     free(p_Temp);  //會釋放p_temp裡面所保存的記憶體 而不是釋放指針變數
326 }
327 
328 int isEmpty(PLIST p_list)
329 {
330     return p_list->pNext == NULL;
331 }
332 
333 void CreateListHead(PLIST *p_list) //傳入頭節點指針 給它分配記憶體
334 {
335     *p_list = (PLIST)malloc(sizeof(LIST));
336     (*p_list)->pNext = NULL;
337 }

 

最後實現效果如下所示;

 

2019-04-01  21:33:15


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • slice 是 Go 語言一個很重要的數據結構。網上已經有很多文章寫過了,似乎沒必要再寫。但是每個人看問題的視角不同,寫出來的東西自然也不一樣。我這篇會從更底層的彙編語言去解讀它,這是一個新的世界。 ...
  • 線程簡介 什麼是線程 現代操作系統調度的最小單元是線程,也叫輕量級進程(Light Weight Process),在一個進程里可以創建多個線程,這些線程都擁有各自的計數器、堆棧和局部變數等屬性,並且能夠訪問共用的記憶體變數。 線程生命周期 java.lang.Thread.State 中定義了 6  ...
  • 目錄: 一、JDK安裝 1.1、JDK下載 1.2、環境變數配置 1.3、測試 二、ANDROID-SDK安裝 2.1、下載 2.2、環境變數配置 三、Flutter安裝 3.1、下載 3.2、環境變數配置 3.3、測試 四、IDE安裝 4.1、下載 4.2、插件安裝 五、錯誤解決 5.1、Andr ...
  • 早在介紹多態的時候,曾經提到公雞實例的性別屬性可能被篡改為雌性,不過面向對象的三大特性包含了封裝、繼承和多態,只要把性別屬性設置為private私有級別,也不提供setSex這樣的性別修改方法,那麼性別屬性就被嚴嚴實實地封裝了起來,不但外部無法修改性別屬性,連公雞類的子類都無法修改。如此一來,公雞實 ...
  • 1.不要在常量和變數中出現易混淆的數字 個人感覺這條在於編程命名的規範性。代碼除了給機器看,也要給人看。要寫能夠結構清晰,命名規範,讓人看懂的代碼。 字母l作為長整型標誌時務必大寫 L 2.莫讓常量蛻變成變數 java的常量有編譯期常量和運行期常量。他們都被static final修飾。引用被sta ...
  • 1.JVM運行時數據區 (1)程式計數器:線程私有,可以看做是當前線程所執行的位元組碼的行號指示器。選取下一條位元組碼指令、分支、線程恢復等都需要程式計數器來完成。 (2)虛擬機棧:同樣是線程私有,它描述的是java方法執行的記憶體模型:每個方法在執行的同時,都會創建一個棧幀,用來存放局部變數表、操作數棧 ...
  • 死磕 java集合之LinkedHashMap源碼分析 你瞭解它的存儲結構嗎? 你知道它為什麼可以用來實現LRU緩存嗎? 它真的可以直接拿來實現LRU緩存嗎? ...
  • 通常GC採用有向圖的方式記錄和管理堆區中的所有對象 JVM將堆記憶體劃分為 Eden、Survivor 和 Tenured/Old 空間。 1. 年輕代 所有新生成的對象首先都是放在Eden區。 年輕代的目標就是儘可能快速的收集掉那些生命周期短的對象,對應的是Minor GC,每次 Minor GC ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...