/***********************************************************
* 版权所有 (C)2016,bigice
*
* 文件名称: main.cpp
* 文件标识:main
* 内容摘要:函数文件
* 其它说明:主函数
* 当前版本: V8.0
* 作 者:何大冰
* 完成日期: 20161226
*
* 修改记录1:
* 修改日期 :20161216
* 版本号: V1.0
* 修改人: 何大冰
* 修改内容:整理思路,创建基本架构
*
* 修改记录2:
* 修改日期:20161217
* 版本号: V2.0
* 修改人: 何大冰
* 修改内容:游戏能够基本正常运行。
*
* 修改记录3:
* 修改日期: 20161219
* 版本号: V3.0
* 修改人: 何大冰
* 修改内容:修复大量的BUG
*
* 修改记录4:
* 修改日期: 20161219
* 版本号: V4.0
* 修改人: 何大冰
* 修改内容:程序复杂度进一步增加
*
* 修改记录5:
* 修改日期: 20161220
* 版本号: V5.0
* 修改人: 何大冰
* 修改内容:对新功能进行探索,失败,转到原来的版本
*
* 修改记录6:
* 修改日期: 20161222
* 版本号: V6.0
* 修改人: 何大冰
* 修改内容:加入了新功能
*
* 修改记录6:
* 修改日期: 20161224
* 版本号: V7.0
* 修改人: 何大冰
* 修改内容:完成游戏的大部分功能
*
* 修改记录6:
* 修改日期: 20161226
* 版本号: V8.0
* 修改人: 何大冰
* 修改内容:将程序添加注释,将初始化数据变成文件存储,修改小部分不完善的地方
**********************************************************/
main.cpp:
#include "ice.h"
void SlowDisplay(char *str) //字体缓慢显示的函数
{
char *p = str;
while(!kbhit()) //检测是否有键盘输入,如果有键盘输入输出就停止
{
if(*p!=0)
printf("%c",*p++);
else
break;
Sleep(50);
}
}
int main()
{
SlowDisplay("--------------------------------拯救公主----------------------------------------");
SlowDisplay(" 魔鬼将公主捉进了城堡。英勇的王子得知此事后,");
SlowDisplay("询问住在森林小屋的老婆婆,老婆婆告诉他城堡的地点,");
SlowDisplay("并给了他一把威力无比的宝剑和国王的信物,于是王子踏上了拯救公主的路。。。。。。\n");
system("cls");
printf("-------------------------------bigice制作-------------------------------\n");
ALGraph *G; //邻接表
MGraph g; //邻接矩阵
Ans c; //存储问题的数组
int *A; //矩阵
A=init(c);
ArrayToList(A, Max, G);
ArrayToMat(A, Max, g);
VNode p; //头节点
p=G->adjlist[1];
printf("%s\n",p.data); //游戏开始第一句话
IFS(G,p,p.cnt,c,g); //大冰改进的遍历方法IFS
return 0;
}
ice.cpp:
/*********************************************************
* 版权所有 (C)2016,bigice
*
* 文件名称:ice.cpp
* 文件标识:ice.cpp
* 内容摘要:对各种参数进行初始化
* 其它说明:可以读取txt文件
* 当前版本: V8.0
* 作 者: 何大冰
* 完成日期: 20161226
*
************************************************************/
#include "ice.h"
/*********************************************************
* 功能描述:初始化矩阵,初始化问题,初始化问题的答案
* 输入参数:无
* 输出参数:无
* 返回值 :一个矩阵
* 其它说明:读取txt文件对矩阵、问题以及问题答案进行初始化
************************************************************/
int* init(Ans c)
{
int i,j;
char buf[300];
int m=0;
int *A=(int *)malloc(sizeof(int)*Max*Max);
FILE* rc=fopen("init.txt","r");
if(rc==NULL)
{
printf("failed to open file\n");
system("pause");
return NULL;
}
for(i=0;i<Max;i++)
{
for(j=0;j<Max;j++)
{
fscanf(rc,"%d",A+i*Max+j);//对矩阵的初始化
}
}
FILE* ra =fopen("c[i].question.txt","r");
if(ra==NULL)
{
printf("failed to open file\n");
system("pause");
return NULL;
}
for(m=0;m<6;m++)
{
strcpy(c[m].question,fgets(buf,300,ra)); //对问题的初始化
}
FILE* rb =fopen("c[i].answer.txt","r");
if(ra==NULL)
{
printf("failed to open file\n");
system("pause");
return NULL;
}
for(m=0;m<6;m++)
{
fscanf(rb,"%d",&c[m].answer); //对问题答案的初始化
}
return A;
}
/*********************************************************
* 功能描述:对邻接表中每个顶点的数据域进行初始化
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:读取txt文件对邻接表中每个顶点的数据域进行初始化
************************************************************/
void init2(ALGraph *&G)
{
int i=0;
char buf[300];
FILE* ra =fopen("adjlist[i].data.txt","r");
if(ra==NULL)
{
printf("failed to open file\n");
system("pause");
return ;
}
for(i=0;i<16;i++)
{
strcpy(G->adjlist[i].data,fgets(buf,300,ra)); //对各个顶点信息的初始化
}
}
/*********************************************************
* 功能描述:对邻接矩阵中每个顶点的名字进行初始化
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:读取txt文件对邻接矩阵中每个顶点的名字进行初始化
************************************************************/
void init2(MGraph &g)
{
int i=0;
char buf[300];
FILE* ra =fopen("g.vexs[i].name.txt","r");
if(ra==NULL)
{
printf("failed to open file\n");
system("pause");
return ;
}
for(i=0;i<16;i++)
{
strcpy(g.vexs[i].name,fgets(buf,300,ra)); //对顶点名字的初始化
}
}
graph.cpp:
#include "ice.h"
/*********************************************************
* 功能描述:矩阵化成邻接表
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:图算法库
************************************************************/
void ArrayToList(int *Arr, int n, ALGraph *&G)
{
int i,j;
ArcNode *p;
G=(ALGraph *)malloc(sizeof(ALGraph));
G->n=n;
for (i=0; i<n; i++) //给邻接表中所有头节点的指针域置初值
{
G->adjlist[i].firstarc=NULL;
G->adjlist[i].num=i;
}
init2(G);
for (i=0; i<n; i++) //检查邻接矩阵中每个元素
for (j=n-1; j>=0; j--)
if (Arr[i*n+j]==1) //存在一条边,将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j]
{
p=(ArcNode *)malloc(sizeof(ArcNode)); //创建一个节点*p
p->adjvex=j;
p->info=Arr[i*n+j]; //给权值
p->nextarc=G->adjlist[i].firstarc; //采用头插法插入*p
G->adjlist[i].firstarc=p;
}
total(G);
}
/*********************************************************
* 功能描述:矩阵化为邻接矩阵
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:图算法库
************************************************************/
void ArrayToMat(int *Arr, int n, MGraph &g)
{
int i,j,count=0; //count用于统计边数,即矩阵中非0元素个数
g.n=n;
for (i=0; i<g.n; i++)
for (j=0; j<g.n; j++)
{
g.edges[i][j]=Arr[i*n+j]; //将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j],计算存储位置的功夫在此应用
if(g.edges[i][j]!=0)
count++;
}
g.e=count;
init2(g);
}
/*********************************************************
* 功能描述:输出邻接表G
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:图算法库
************************************************************/
void DispAdj(ALGraph *G)
{
int i;
ArcNode *p;
for (i=0; i<G->n; i++)
{
printf("%d:\n",G->adjlist[i].cnt);;
p=G->adjlist[i].firstarc;
printf("%3d: ",i);
while (p!=NULL)
{
printf("-->%d",p->adjvex);
p=p->nextarc;
}
printf("\n");
}
}
/*********************************************************
* 功能描述:本游戏的核心算法,bigice独创,游戏的主要步骤
* 输入参数:玩家选择的选项
* 输出参数:玩家选中的选项的内容
* 返回值 :无
* 其它说明:本游戏的核心算法,由主函数调用
************************************************************/
void IFS(ALGraph *G,VNode p1,int cnt,Ans c,MGraph g)
{
srand(time(NULL));
int w,i;
int t;
ArcNode *p=p1.firstarc;
if(p!=NULL)
{
scanf("%d",&t);
while(t<1||t>cnt)
{
if(t==0)
{
help(G,c,g);
system("cls");
printf("%s\n",p1.data);
}
else printf("你输入的数字有误,请重新输入\n");
scanf("%d",&t);
}
system("cls");
for(i=0;i<t;i++)
{
w=p->adjvex;
p=p->nextarc;
}
cout<<G->adjlist[w].data<<endl;
if(G->adjlist[w].cnt==1)
{
questions((rand()%(5-0+1)+0),c,G,g);
}
IFS(G,G->adjlist[w],G->adjlist[w].cnt,c,g);
}
}
/*********************************************************
* 功能描述:每个头结点所连接的结点个数
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:统计每个头结点所连接的结点个数,供其他函数使用
************************************************************/
void total(ALGraph *&G)
{
int i;
ArcNode *p;
p=G->adjlist[0].firstarc;
for(i=0;i<Max;i++)
{
G->adjlist[i].cnt=0;
p=G->adjlist[i].firstarc;
while(p!=NULL)
{
(G->adjlist[i].cnt)++;
p=p->nextarc;
}
}
}
/*********************************************************
* 功能描述:帮助函数
* 输入参数:选择帮助选项
* 输出参数:相应的操作
* 返回值 :无
* 其它说明:帮助页面,调用其他函数
************************************************************/
void help(ALGraph *G,Ans c,MGraph g)
{
int a,m;
printf("欢迎进入帮助页面!\n");
printf(" ◢████████████◣ \n");
printf(" ██████████████ \n");
printf(" ██ ◥██◤ ██ \n");
printf(" ◢███ ◥◤ ██◣ \n");
printf(" ▊▎██◣ ◢█▊▊ \n");
printf(" ▊▎██◤ ● ● ◥█▊▊ \n");
printf(" ▊ ██ █▊▊ \n");
printf(" ◥▇██ ▊ ▊ █▇◤ \n");
printf(" ██ ◥▆▄▄▄▄▆◤ █▊ ◢▇▇◣ \n");
printf(" ◢██◥◥▆▅▄▂▂▂▂▄▅▆███◣ ▊◢ █ \n");
printf(" █╳ ╳█ ◥◤◢◤ \n");
printf(" ◥█◣ ˙ ˙ ◢█◤ ◢◤ \n");
printf(" ▊ ▊ █ \n");
printf(" ▊ ▊ ◢◤ \n");
printf(" ▊ ⊕ █▇▇▇◤ \n");
printf(" ◢█▇▆▆▆▅▅▅▅▆▆▆▇█◣ \n");
printf(" ▊ ▂ ▊ ▊ ▂ \n");
printf("1 以邻接表的形式展示当前地图\n");
printf("2 输出问题答案\n");
printf("3 输出到达各个地方的最短路径\n");
printf("按其他按钮退出帮助程序 \n");
scanf("%d",&a);
switch (a)
{
case 1:DispAdj(G);
printf("请输1继续游戏:");
scanf("%d",&m);
while(m!=1)
{
scanf("%d",&m);
}
break;
case 2:
printf("请输入你想知道的问题的序号:");
scanf("%d",&m);
if(m<0||m>5) printf("你输入的序号错误\n");
else printf("序号为%d的问题答案为:%d\n",m,questions2(m,c));
printf("请输1继续游戏:");
scanf("%d",&m);
while(m!=1)
{
scanf("%d",&m);
}
break;
case 3:
Dijkstra(g,1);
printf("请输1继续游戏:");
scanf("%d",&m);
while(m!=1)
{
scanf("%d",&m);
}
break;
default:break;
}
}
/*********************************************************
* 功能描述:前向递归查找路径上的顶点
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:Dijkstra算法库
************************************************************/
void Ppath(int path[],int i,int v,MGraph g)
{
int k;
k=path[i];
if (k==v) return; //找到了起点则返回
Ppath(path,k,v,g); //找顶点k的前一个顶点
printf("%s->",g.vexs[k].name); //输出顶点k
}
/*********************************************************
* 功能描述:输出最短路径
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:Dijkstra算法库
************************************************************/
void Dispath(int dist[],int path[],int s[],int n,int v,MGraph g)
{
int i;
for (i=0; i<n; i++)
if (s[i]==1)
{
printf(" 从%s到%s的最短路径长度为:%d\t路径为:",g.vexs[v].name,g.vexs[i].name,dist[i]);
printf("%s->",g.vexs[v].name); //输出路径上的起点
Ppath(path,i,v,g); //输出路径上的中间点
printf("%s\n",g.vexs[i].name); //输出路径上的终点
}
else printf("从%d到%d不存在路径\n",v,i);
}
/*********************************************************
* 功能描述:Dijkstra算法
* 输入参数:无
* 输出参数:无
* 返回值 :无
* 其它说明:Dijkstra算法库
************************************************************/
void Dijkstra(MGraph g,int v)
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u=0;
for (i=0; i<g.n; i++)
{
dist[i]=g.edges[v][i]; //距离初始化
s[i]=0; //s[]置空
if (g.edges[v][i]<INF) //路径初始化
path[i]=v;
else
path[i]=-1;
}
s[v]=1;
path[v]=0; //源点编号v放入s中
for (i=0; i<g.n; i++) //循环直到所有顶点的最短路径都求出
{
mindis=INF; //mindis置最小长度初值
for (j=0; j<g.n; j++) //选取不在s中且具有最小距离的顶点u
if (s[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1; //顶点u加入s中
for (j=0; j<g.n; j++) //修改不在s中的顶点的距离
if (s[j]==0)
if (g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[j])
{
dist[j]=dist[u]+g.edges[u][j];
path[j]=u;
}
}
Dispath(dist,path,s,g.n,v,g); //输出最短路径
}
/*********************************************************
* 功能描述:回答问题的运行程序
* 输入参数:玩家的选项
* 输出参数:回答是否正确
* 返回值 :无
* 其它说明:无
************************************************************/
void questions(int i,Ans c,ALGraph *G,MGraph g)
{
int m,n;
n=questions2(i,c); //n为问题的答案
scanf("%d",&m);
while(m!=n)
{
if(m<0||m>4)
{
printf("你输入的数字有误,请重新输入\n");
scanf("%d",&m);
}
else if(m==0) //如果为0进入帮助页面
{
help(G,c,g);
questions2(i,c);
scanf("%d",&m);
}
else
{
printf("这个题你都能回答错误,真是猪脑子!请重新输入答案:\n");
scanf("%d",&m);
}
}
printf("恭喜你,回答正确,按1继续游戏\n");
}
/*********************************************************
* 功能描述:查找i序号上的问题以及答案
* 输入参数:无
* 输出参数:无
* 返回值 :第i个问题的答案
* 其它说明:读取txt文件对邻接矩阵中每个顶点的名字进行初始化
************************************************************/
int questions2(int i,Ans c)
{
printf("%s",c[i].question);
return c[i].answer;
}
graph.h:
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
#include <string>
#include <iostream>
using namespace std;
#define MAXV 100 //最大顶点个数
#define INF 32767 //INF表示∞
typedef int InfoType; //权值的数据类型
#define Max 16
#define Max2 6
#define MaxSize 100
//以下定义邻接矩阵类型
typedef struct
{
int no; //顶点编号
InfoType info; //顶点其他信息,在此存放带权图权值
char name[30]; //顶点名字
} VertexType; //顶点类型
typedef struct //图的定义
{
int edges[MAXV][MAXV]; //邻接矩阵
int n,e; //顶点数,弧数
VertexType vexs[MAXV]; //存放顶点信息
} MGraph; //图的邻接矩阵类型
//以下定义邻接表类型
//每个顶点
typedef struct ANode
{
int adjvex; //在矩阵中的列位置
struct ANode *nextarc; //指向下一条弧的指针
InfoType info; //权值
} ArcNode;
//头节点
typedef struct Vnode
{
int num; //顶点的标号
char data[300]; //顶点信息
ArcNode *firstarc; //指向第一条弧
int cnt; //顶点与几个其他顶点相连
} VNode;
//整个邻接表
typedef VNode AdjList[MAXV]; //AdjList是邻接表类型
typedef struct
{
AdjList adjlist; //邻接表
int n,e; //图中顶点数n和边数e
} ALGraph; //图的邻接表类型
//储存问题的结构体
typedef struct
{
char question[500];
int answer;
} Que;
typedef Que Ans[Max2];
//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图
//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)
// n - 矩阵的阶数
// g - 要构造出来的邻接矩阵数据结构
void ArrayToList(int *Arr, int n, ALGraph *&); //用普通数组构造图的邻接表
void DispAdj(ALGraph *G);//输出邻接表G
int* init(Ans c);
void init2(ALGraph *&G);
void init2(MGraph &g);
void total(ALGraph *&G);
void IFS(ALGraph *G,VNode p1,int cnt,Ans c,MGraph g);
int questions2(int i,Ans c);
void questions(int i,Ans c,ALGraph *G,MGraph g);
void help(ALGraph *G,Ans c,MGraph g);
void Ppath(int path[],int i,int v,MGraph g);
void Dispath(int dist[],int path[],int s[],int n,int v,MGraph g);
void Dijkstra(MGraph g,int v);
void ArrayToMat(int *Arr, int n, MGraph &g);
#endif // GRAPH_H_INCLUDED
ice.h:
#ifndef ICE_H_INCLUDED
#define ICE_H_INCLUDED
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include "graph.h"
#endif // ICE_H_INCLUDED
运行截图:
初始化各个数据的文件链接:http://download.csdn.net/detail/big_ice/9722618