• C++学习(三十七)(C语言部分)之 链式栈(推箱子实现)


    用链表实现栈
    一开始在表头插入,就要一直在表头插入
    一开始在表尾插入,就要一直在表头插尾
    表头当栈底 也可以把表尾当栈底

    实现的测试代码笔记如下:

      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("内存分配失败!
    ");
     79     }
     80     else
     81     {
     82         printf("内存分配成功!
    ");
     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

  • 相关阅读:
    VSFTP日志文件详解
    RocketMQ多master多salve集群搭建
    数据持久化之bind Mounting
    数据持久化之Data Volume
    gitLab 分支保护设置
    docker容器的端口映射
    docker命令之link
    NFS客户端挂载失败之authenticated unmount request from
    docke网络之bridge、host、none
    docke通信之Linux 网络命名空间
  • 原文地址:https://www.cnblogs.com/Yuuki-/p/10639157.html
Copyright © 2020-2023  润新知