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

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

 #include<stdio.h>
#include<stdlib.h>
#include<string.h> //节点的结构体
typedef struct Node
{
char *name;
struct Node *pNext;
}LIST, *PLIST; //1.创建“火车头” 创建一个表头
void CreateListHead(PLIST *p_list) //传入头结点指针 给他分配内存
{
//一级指针 形参和实参结合时
//PLIST p_list = p_head; 形参和实参结合时候的赋值
//p_list 改变 是不影响到p_head 就好像是A给B发送了一个文件 B对文件进行了修改,是不会影响A手中的文件 //要改变一级指针的实参 函数要传入一级指针的地址 保存一级指针的地址 要使用二级指针
*p_list = (PLIST)malloc(sizeof(LIST));
(*p_list)->pNext = NULL; } //实现一个栈
//2.写入栈函数
void Push_Stack(PLIST p_list, char *name)
{
//头插法
PLIST node = (PLIST)malloc(sizeof(LIST));
//node->name - name; 可以这么写 但是如果存入得扇区内存,会被释放掉 就会出错
node->name = (char *)malloc(sizeof(char)*strlen(name) + );
strcpy(node->name, name);
node->pNext = p_list->pNext;
p_list->pNext = node;
} //3.获取栈顶元素
char * GetStackTop(PLIST p_list)
{
//如果不是空 就返回头结点的下一个节点的name
PLIST p_Temp = p_list->pNext;
if (p_Temp != NULL)
{
return p_Temp->name;
}
return NULL; //说明栈是空
} //4.出栈
void Pop_Stack(PLIST p_list)
{
//相当于删除结点 之前是头插法 那么最后一个在最前面
PLIST p_Temp = p_list->pNext;
if (p_Temp != NULL)
{
//p_remp保存第一个节点的地址
p_Temp = p_list->pNext;
//让头结点的pnext连接到第二个节点
p_list->pNext = p_Temp->pNext;
}
free(p_Temp); //释放内存 释放掉第一个节点 是释放p_temp里面所保存的内存 而不是释放指针变量
} //5.判断栈是否为空
int isEmpty(PLIST p_list)
{
//如果栈为空 返回1
return p_list->pNext == NULL;
} int main()
{
PLIST p_head = NULL; //作为链表的标记
CreateListHead(&p_head);
/*if (NULL == p_head)
{
printf("内存分配失败!\n");
}
else
{
printf("内存分配成功!\n");
}*/ Push_Stack(p_head, "力");
Push_Stack(p_head, "努");
Push_Stack(p_head, "的");
Push_Stack(p_head, "人");
Push_Stack(p_head, "何");
Push_Stack(p_head, "任");
Push_Stack(p_head, "于");
Push_Stack(p_head, "亚");
Push_Stack(p_head, "不");
Push_Stack(p_head, "的");
Push_Stack(p_head, "出");
Push_Stack(p_head, "付");
while (!isEmpty(p_head))
{
printf("%s", GetStackTop(p_head));
Pop_Stack(p_head);
} getchar();
return ;
}

附:

推箱子实现,代码笔记如下所示:

 、main.cpp文件

 //推箱子
//操作说明 WASD表示上下左右移动 空格键可以退回到上一步
#if 1
#include<graphics.h>
#include<stdio.h>
#include <conio.h> #include "Stack.h"
//地图
int Map[][] = {
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , ,
}; //实现退回操作
void Retrogress(PLIST p_list)
{
//1.获取栈顶数据
PLIST p_Temp = GetStackTop(p_list);
if (NULL == p_Temp)
{
return;
}
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
Map[i][j] = p_Temp->p[i][j];
}
}
Pop_Stack(p_list); //出栈
} //对于一个游戏1.初始化 加载图片
IMAGE g_box, g_dbox, g_people, g_point, g_wall, g_blank;
void Init_Game()
{
loadimage(&g_box, L"./source/box.jpg"); //相对路径
loadimage(&g_dbox, L"./source/dbox.jpg");
loadimage(&g_people, L"./source/people.jpg");
loadimage(&g_point, L"./source/point.jpg");
loadimage(&g_wall, L"./source/wall.jpg");
loadimage(&g_blank, L"./source/blank.jpg");
} //2.加载图片
void Paint_Game()
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
switch (Map[i][j])
{
case : //0表示空地
putimage(j * , i * , &g_blank);
break;
case : // 1表示墙壁
putimage(j * , i * , &g_wall);
break;
case : // 3表示目的地
putimage(j * , i * , &g_point);
break;
case : // 4表示箱子
putimage(j * , i * , &g_box);
break;
case : // 5表示人
putimage(j * , i * , &g_people);
break;
case : // 7表示箱子在目的地 4+3
putimage(j * , i * , &g_dbox);
break;
case : // 8表示人在目的地 5+3
putimage(j * , i * , &g_people);
break;
}
}
}
} //3.实现人物移动
void MovePeople(PLIST p_list)
{
int i, j;
for (i = ; i < ; i++)
{
for (j = ; j < ; j++)
{
//找到人的位置
if (Map[i][j] == || Map[i][j] == )
{
//if成立说明找到人
break;
}
}
if (Map[i][j] == || Map[i][j] == )
{
//if成立说明找到人
break;
}
}
switch (getch())
{
//表示往左边移动
case 'a':
//人的左边是空地 或者 是目的
if (Map[i][j - ] == || Map[i][j - ] == )
{
Map[i][j - ] += ; //人往左边移动
Map[i][j] -= ; //人离开了当前位置
}//人的左边是箱子或者是箱子在目的
else if (Map[i][j - ] == || Map[i][j - ] == )
{
if (Map[i][j - ] == || Map[i][j - ] == )
{
Map[i][j - ] += ;
Map[i][j - ] += ;
Map[i][j] -= ;
}
}
//每次移动都要入栈
Push_Stack(p_list, Map);
break; //表示往右边
case 'd':
//人的右边是空地 或者 是目的
if (Map[i][j + ] == || Map[i][j + ] == )
{
Map[i][j + ] += ; //人往左边移动
Map[i][j] -= ; //人离开了当前位置
}//人的右边是箱子或者是箱子在目的
else if (Map[i][j + ] == || Map[i][j + ] == )
{
if (Map[i][j + ] == || Map[i][j + ] == )
{
Map[i][j + ] += ;
Map[i][j + ] += ;
Map[i][j] -= ;
}
}
//每次移动都要入栈
Push_Stack(p_list, Map);
break; //表示往上边移动
case 'w':
//人的上边是空地 或者 是目的
if (Map[i - ][j] == || Map[i - ][j] == )
{
Map[i - ][j] += ; //人往上边移动
Map[i][j] -= ; //人离开了当前位置
}//人的上边是箱子或者是箱子在目的
else if (Map[i - ][j] == || Map[i - ][j] == )
{
if (Map[i - ][j] == || Map[i - ][j] == )
{
Map[i - ][j] += ;
Map[i - ][j] += ;
Map[i][j] -= ;
}
}
//每次移动都要入栈
Push_Stack(p_list, Map);
break; //表示什么往下边移动
case 's':
//人的下边是空地 或者 是目的
if (Map[i + ][j] == || Map[i + ][j] == )
{
Map[i + ][j] += ; //人往左边移动
Map[i][j] -= ; //人离开了当前位置
}//人的下边是箱子或者是箱子在目的
else if (Map[i + ][j] == || Map[i + ][j] == )
{
if (Map[i + ][j] == || Map[i + ][j] == )
{
Map[i + ][j] += ;
Map[i + ][j] += ;
Map[i][j] -= ;
}
}
//每次移动都要入栈
Push_Stack(p_list, Map);
break;
case VK_SPACE: //空格
if (!isEmpty(p_list))
{
Retrogress(p_list);
Paint_Game();
}
}
} //4.判断游戏是否结束
int isWin()
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
if (Map[i][j] == )
{
return ;
}
}
}
return ;
} int main()
{
initgraph(, ); //初始化图形界面
Init_Game();
PLIST p_head = NULL;
CreateListHead(&p_head);
Paint_Game();
while (!isWin())
{
Paint_Game();
MovePeople(p_head);
}
Paint_Game();
getchar();//防止运行到closegraph() 直接退出 看不到效果
closegraph(); //关闭图形界面 return ;
} *********************分割线************************ 、Stack.h文件
#include <stdlib.h>
#include <stdio.h>
/*
以后 头文件是用来声明函数 或者类
*/
typedef struct Node
{
//char *name; //前面是不是讲过动态分配二维数组
//通过指针数组来实现
int **p; //目的:分配二维数组用来保存我的地图信息
struct Node * pNext;
}LIST, *PLIST; void CreateListHead(PLIST *p_list); void Push_Stack(PLIST p_list, int(*pArr)[]); //返回整个结点的内容
PLIST GetStackTop(PLIST p_list); void Pop_Stack(PLIST p_list); int isEmpty(PLIST p_list); *********************分割线************************ 、Stack.cpp文件
#include "Stack.h" void Push_Stack(PLIST p_list, int(*pArr)[])
{
PLIST node = (PLIST)malloc(sizeof(LIST));
//先给二级指针申请内存
node->p = (int **)malloc(sizeof(int)* ); // p就相当于是一个 指针数组 int *p[9]
for (int i = ; i < ; i++)
{
//通过这个就能够分配一个二维数组
node->p[i] = (int*)malloc(sizeof(int)* );
}
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
node->p[i][j] = pArr[i][j];
}
//代码 提升写代码能 语法有关
//思路 实现功能 首先你要有思路
//逻辑 你的方法的逻辑性是否可以
// 栈 链表
}
//连接指针
node->pNext = p_list->pNext;
p_list->pNext = node;
// int a[5]
// int *a[5] a二级指针
} PLIST GetStackTop(PLIST p_list)
{
if (p_list->pNext != NULL)
{
return p_list->pNext;
}
return NULL;
} void Pop_Stack(PLIST p_list)
{
PLIST p_Temp = NULL;
if (p_list->pNext != NULL)
{
//p_temp保存第一节点的地址
p_Temp = p_list->pNext; //让头节点的pnext连接到第二个结点
p_list->pNext = p_Temp->pNext;
}
//释放掉第一个结点
free(p_Temp); //会释放p_temp里面所保存的内存 而不是释放指针变量
} int isEmpty(PLIST p_list)
{
return p_list->pNext == NULL;
} void CreateListHead(PLIST *p_list) //传入头节点指针 给它分配内存
{
*p_list = (PLIST)malloc(sizeof(LIST));
(*p_list)->pNext = NULL;
}

最后实现效果如下所示;

2019-04-01  21:33:15

C++学习(三十七)(C语言部分)之 链式栈(推箱子实现)的更多相关文章

  1. 012-C语言小游戏之推箱子

    012-C语言小游戏之推箱子 一.创建游戏地图   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #define ROWS 11 #define COLS 12   char ...

  2. Java开发学习(三十七)----SpringBoot多环境配置及配置文件分类

    一.多环境配置 在工作中,对于开发环境.测试环境.生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql ,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配 ...

  3. 学习笔记:oracle学习三:SQL语言基础之sql语言简介、用户模式

    目录 1.sql语言简介 1.1 sql语言特点 1.2 sql语言分类 1.3 sql语言的编写规则 2.用户模式 2.1 模式与模式对象 2.2 实例模式scott 本系列是作为学习笔记,用于记录 ...

  4. 学习笔记:oracle学习三:SQL语言基础之检索数据:简单查询、筛选查询

    目录 1. 检索数据 1.1 简单查询 1.1.1 检索所有列 1.1.2 检索指定的列 1.1.3 查询日期列 1.1.4 带有表达式的select语句 1.1.5 为列指定别名 1.1.6 显示不 ...

  5. shell学习三十七天----引用

    引用 案例,假设我想输出一个星号(*),使用echo怎样做? echo * 这是肯定不行的,须要将*转移,即:echo \* 这样就引出了引用的概念.所为引用,是用来防止shell将某些你想要的东西解 ...

  6. Salesforce LWC学习(三十七) Promise解决progress-indicator的小问题

    本篇参考:https://developer.salesforce.com/docs/component-library/bundle/lightning-progress-indicator/exa ...

  7. python学习三十七天函数的作用域查找顺序LEGB

    python函数的作用域查找顺序LEGB,分别为 locals  eclosing  globals  builtins .了解作用域的范围,可以更好的操作你想要的业务,分别介绍一下. 1,local ...

  8. 前端学习(三十七)angular(笔记)

    MVC     后台    M         Module             数据层    V         View             视图层    C         Contro ...

  9. C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目

    C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...

  10. C语言之推箱子游戏代码

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:Yan_Less 正文 新手注意:如果你学习遇到问题找不到人解答,可以点 ...

随机推荐

  1. Learning-Python【34】:进程之生产者消费者模型

    一.什么是生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样 ...

  2. ef core一个数据库多个dbcontext

    如一个项目存在多个DbCcontext且使用同一个数据库,关系: 无关联:donetcli指定具体的dbcontext类名生成migration classes 有关联:子dbcontext继承父db ...

  3. windows上使用foremost

    做CTF题需要这工具来提取文件里的隐藏文件, 网上大部分是linux版本,之前好不容易找了一个exe文件结果还不能用.找了很长时间终于找到了: https://github.com/raddyfiy/ ...

  4. Font Awesome字体图标的 用法, 很简单

    http://fontawesome.dashgame.com/ 上面是 官网,  可下载,也可以CDN. 1...  加载 2...  用法

  5. Asp.net core 学习笔记 SignalR

    refer : https://kimsereyblog.blogspot.com/2018/07/signalr-with-asp-net-core.html https://github.com/ ...

  6. try与except处理异常语句

    ji 简介 与其他语言相同,在python中,try/except语句主要是用于处理程序正常执行过程中出现的一些异常情况,如语法错(python作为脚本语言没有编译的环节,在执行过程中对语法进行检测, ...

  7. fiddler修改response header

    if(oSession.host.Contains("baidu.com")){//根据host判断 oSession.RequestHeaders.Remove("Ac ...

  8. 【JS】【5】request.getHeader("referer")的作用

    正文: request.getHeader("referer"):获取来访者地址 注意:只有通过链接访问当前页的时候,才能获取上一页的地址,以下情况是获取不到值的: 只有通过链接访 ...

  9. @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

    @ControllerAdvice 和 @ExceptionHandler 的区别 ExceptionHandler, 方法注解, 作用于 Controller 级别. ExceptionHandle ...

  10. 轻松学习java可重入锁(ReentrantLock)的实现原理

    转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...