BattenSnakexjp4.1
/*
*Copyright (c) 2015, 烟台大学计算机与控制工程学院
* All rights reserved.
* 文件名称:main.cpp,lipueue.h,lipueue.cpp,maopaopaixu.cpp
* 作者:徐吉平
* 完成日期:2015年12月25日
* 版本号:BattenSnakexjp4.1
* 项目描述:数据结构课程设计——BattenSnakexjp4.1
* 输入描述:用户名和密码
* 程序输出:贪吃蛇的运行程序
*/
mian.cpp
#include "listack.h"
#define HEAD 300
#define FOOD 400
using namespace std;
int SCORE=0;
int t=100;
string name,password;
int num=0;
int score[100];//多次得分数组
string Bosspassword="xjp";
void running();
void drawpt(int a,int x,int y);
void draw(int (*sna)[17]);
int randno();
bool judgeGO(int (*sna)[17]);
void downmove(int (*sna)[17]);
void upmove(int (*sna)[17]);
void leftmove(int (*sna)[17]);
void rightmove(int (*sna)[17]);
int judgeF(int (*sna)[17],int keym);
void gameover();
void inscore(int sc[100],int n);
void boss();
bool user=true;
//int score(int (*sna)[17]);
void signin();//注册
void login();//登录
LiStack *s;
LiStack *s2;
LiQueue *Q;
/*-----------------------------------------Push(LiStack *&s,ElemType e)-------------------欢迎辞-----------------------------------------------------------------*/
void welcome()
{
system("color 79");
printf("\n\n\n\n\n\n\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n\n");
printf("\t\t\t欢迎来到xjp贪吃蛇\n");
printf("\t操作方式:键盘右下角的方向键控制方向,退出请按:Esc\n");
printf("\t\t\t相反的方向是暂停\n\n\n");
printf("\t\t\t请选择:1、注册游戏\n");
printf("\t\t\t 2、登录用户\n");
printf("\t\t\t 3、管理员登录\n");
printf("\n\n\n\n\n\t 适度游戏宜脑,过度游戏伤身,合理安排生活,享受健康人生\n");
int ch=getch();//这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车
if(ch==49)
{
signin();
}
else if(ch==50)
{
user=false;
login();
}
else if(ch==51)
{
system("color E3");
string bosspassword;
system("cls");
printf("\n\n\n\n\n\t\t\t 请输入boss密码:");
cin>>bosspassword;
if(bosspassword==Bosspassword)
{
boss();
}
else
{
printf("\t\t\t sorry 密码错误,已返回初始界面\n");
Sleep(1000);
system("cls");
welcome();
}
}
else
{
system("cls");
printf("Please input correct chioce!");
welcome(); //数据结构:递归调用
}
}
/*--------------------------------------------------------------------------------------------------------------------------------------*/
void boss()
{
system("cls");
printf("\n\n\n\n\n\t\t\t Hello boss\n");
printf("\t\t\t请选择操作选项:1、查看历史用户\n");
printf("\t\t\t 2、增加用户信息\n");
printf("\t\t\t 3、修改管理员密码\n");
printf("\t\t\t 4、返回主菜单\n");
int ch2=getch();
if(ch2==49)
{
system("cls");
string NAMe;
string PAssWord;
string SCoRe;
ifstream infile("用户信息.txt" ,ios::in);//|ios::nocreate
if(!infile)
{
cerr<<"open error!"<<endl;
exit(1);
}
int usernum=0;
while(infile>>NAMe)
{
infile>>PAssWord;
infile>>SCoRe;
cout<<NAMe<<" "<<PAssWord<<" "<<SCoRe<<endl;
usernum++;
//enQueue(q,NAMe);
}
printf("\n\n\n\t\t\t 共有%d个注册用户\n",usernum);
system("pause");
system("cls");
welcome();
/*while(!QueueEmpty(q))
{
ElemType N;
deQueue(q,N);
cout<<N<<endl;
}*/
}
else if(ch2==50)
{
system("cls");
ofstream write;
write.open("用户信息.txt",ios::app);
printf("\n\n\n\t\t\tplease intput new name:\n");
cin>>name;
printf("\t\t\tplease intput new password:\n");
cin>>password;
write <<name<<" "<<password<<" "<<0<<endl;
printf("\t\t\t添加用户成功成功\n");
write.close();
Sleep(1000);
system("cls");
boss();
}
else if(ch2==51)
{
system("cls");
string word;
printf("\n\n\n\t\t\tplease intput new Boss password:\n");
cin>>word;
Bosspassword=word;
printf("\t\t\t密码修改成功,请重新登录管理员\n");
Sleep(1000);
welcome();
}
else if(ch2==52)
{
system("cls");
welcome();
}
else
{
system("cls");
printf("Please input correct chioce!");
boss(); //数据结构:递归调用
}
}
/*-----------------------------------------------signin() and login()-------------------------------------------------------------------*/
void signin()
{
ofstream write;
write.open("用户信息.txt",ios::app);
printf("please intput new name:\n");
cin>>name;
printf("please intput new password:\n");
cin>>password;
write <<name<<" "<<password<<" ";
write.close();
printf("注册成功请登录游戏...\n");
login();
}
void login()
{
system("cls");
printf("\n\n\n\n\n\t\t\t请选择游戏级别:1、普通\n");
printf("\t\t\t 2、文艺\n");
printf("\t\t\t 3、逗比\n");
printf("\t\t\t 4、疯子\n");
int ch3=getch();
if(ch3==49)
{
t=100;
}
else if(ch3==50)
{
t=75;
}
else if(ch3==51)
{
t=50;
}
else if(ch3==52)
{
t=10;
}
else
{
system("cls");
printf("\n\n\n\n\n\t\t\t你真是个逗比,快选1、2、3\n");
Sleep(1000);
login();
}
string NaMe;
string PassWord;
string ScoRe;
string newname,newpassword;
printf("please intput your name:\n");
cin>>newname;
printf("please intput your password:\n");
cin>>newpassword;
ifstream infile("用户信息.txt" ,ios::in);//|ios::nocreate
if(!infile)
{
cerr<<"open error!"<<endl;
exit(1);
}
bool find=true;
while(infile>>NaMe)
{
//infile>>NaMe;
infile>>PassWord;
infile>>ScoRe;
//cout<<NaMe<<" "<<PassWord<<" "<<ScoRe<<endl;
//system("pause");
//Push(s,NaMe,PassWord,ScoRe);
//i++;
if(newname==NaMe&&newpassword==PassWord)
{
system("cls");
system("color D0");
printf("\n\n\n\n\n\n\n\t\t\t\t登陆成功~^0^~");
Sleep(1000);
find=false;
running();
//break;
}
}
if(find==true)
{
system("cls");
printf("\n\n\n\n\n\t\t\t用户名或密码错误,请重新登录...\n");
login();
}
}
/*-----------------------------------------------------------------------------------------------------------------------------------*/
/*全程标记法,从尾巴开始123456....HEAD,食物是FOOD。*/
void running()
{
system("color 79");
/*------------各种东西初始化--------------*/
int x=1,y=1,key,key1;
int snake[17][17]= {0}; //数据结构:数组
int o=0;
int p=0;
int q=0;
int r=0;
snake[1][1]=1;
snake[1][2]=2;
snake[1][3]=3;
snake[2][3]=HEAD;
while(snake[x][y]!=0)
{
x=randno();//取随机数
y=randno();
}
snake[x][y]=FOOD;
draw(snake);
/*---------------------------------------*/
/*------------控制部分-------------------*/
while(judgeGO(snake))
{
key=getch();
switch(key)
{
case 72://对应键盘方向键 上
while(!kbhit()&&key1!=80&&judgeGO(snake))//kbhit()检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
{
//draw(snake);
if(judgeF(snake,key))
{
draw(snake);
Sleep(t);
continue;
}
//int b=0;
if(o%1==0) //本想把刷屏的速度和贪吃蛇的移动速度成倍数分开,但效果并不理想
{
upmove(snake);
}
draw(snake);
key1=key;//这里的key1是就来标记上一步的方向,这样相反的方向就暂停了。
o++;
Sleep(t);//执行挂起一段时间,Sleep()单位为毫秒,sleep()单位为秒(如果需要更精确可以用usleep单位为微秒)
}
break;
case 80://对应键盘方向键 下
while(!kbhit()&&key1!=72&&judgeGO(snake))
{
//draw(snake);
if(judgeF(snake,key))
{
draw(snake);
Sleep(t);
continue;
}
if(p%1==0)
{
downmove(snake);
}
draw(snake);
key1=key;
p++;
Sleep(t);
}
break;
case 75://对应键盘方向键 左
while(!kbhit()&&key1!=77&&judgeGO(snake))
{
//draw(snake);
if(judgeF(snake,key))
{
draw(snake);
Sleep(t);
continue;
}
if(q%1==0)
{
leftmove(snake);
}
draw(snake);
key1=key;
q++;
Sleep(t);
}
break;
case 77://对应键盘方向键 右
while(!kbhit()&&key1!=75&&judgeGO(snake))
{
//draw(snake);
if(judgeF(snake,key))
{
draw(snake);
Sleep(t);
continue;
}
if(r%1==0)
{
rightmove(snake);
}
draw(snake);
key1=key;
r++;
Sleep(t);
}
break;
case 27:
exit(0);
default:
switch(key1)
{
case 72:
while(!kbhit()&&judgeGO(snake))
{
upmove(snake);
draw(snake);
}
break;
case 80:
while(!kbhit()&&judgeGO(snake))
{
downmove(snake);
draw(snake);
}
break;
case 75:
while(!kbhit()&&judgeGO(snake))
{
leftmove(snake);
draw(snake);
}
break;
case 77:
while(!kbhit()&&judgeGO(snake) )
{
rightmove(snake);
draw(snake);
}
break;
}
}
}
/*--------------------------------------------------------------------------------------------------------------------------------*/
/*------------是否继续游戏--------------------------------------------------------------------------------------------------------*/
gameover();
if(getch()==27)
{
int N;
printf("您的成绩依次为:");
while(!QueueEmpty(Q))
{
deQueue(Q,N);
cout<<N<<" ";
}
cout<<endl;
inscore(score,num);//最高成绩写入文件
BubbleSort1(score,num);
exit(0);
}
else
{
running();
getch();
}
/*---------------------------------------------------*/
}
/*---------------取随机数,出现食物用------------*/
int randno()
{
srand(time(NULL));
return rand()%15+1;
}
/*-----------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------------------------------*/
/*--------------画图程序----------------------------------------------------------------------------------------------------------*/
void draw(int (*sna)[17])
{
int i,j;
system("cls");
int x,y,max=0;
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(max<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
max=sna[x][y];//求紧随头部之后的值,是蛇身体的最大值
SCORE=(max-3)*10;
}
}
// printf("\n\t\tWelcome to xjp gluttonous snake~您的得分为:%d\n",SCORE);
printf("\n\t\t您的得分为:%d\n",SCORE);
SYSTEMTIME sys;
GetLocalTime(&sys);
printf("\t\t");
cout<<sys.wYear<<"/"<<sys.wMonth<<"/"<<sys.wDay<<" "<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<" "<<sys.wMilliseconds<<"星期:"<<sys.wDayOfWeek<<endl;
for(i=0; i<17; i++)
{
for(j=0; j<17; j++)
{
drawpt(sna[i][j],j,i);
}
}
}
void drawpt(int a,int x,int y)
{
if(x==0)
{
printf("\t\t");
return ;
}
if(y==0)
{
printf("\t\t\t");
return ;
}
if(x==16)
{
printf("\n");
return ;
}
if(y==16)
{
printf("\t\t");
}
if(x>0&&x<16&&y>0&&y<16)//输出显示的矩阵为15*15,四周最外层的隐藏,作为判断是否出界使用
{
if(a==0)
{
printf("□");
}
else if(a==HEAD)
{
printf("◆");
}
else
{
printf("●");
}
return ;
}
}
/*--------------------------------------------------------------------------------------------------------------------------*/
/*----------------------------判断游戏是否结束------------------------------------------------------------------------------*/
bool judgeGO(int (*sna)[17])
{
int x,y,i=0,max=0,count=0;
for(x=0,y=0; y<17; y++)
if(sna[x][y]==HEAD)
return false;
for(x=0,y=0; x<17; x++)
if(sna[x][y]==HEAD)
return false;
for(x=16, y=0; y<17; y++)
if(sna[x][y]==HEAD)
return false;
for(x=0, y=16; x<17; x++)
if(sna[x][y]==HEAD)
return false;
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(max<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
max=sna[x][y];//求紧随头部之后的值,是蛇身体的最大值
}
}
for(i=0; i<max; i++)
{
for(x=1; x<16; x++)
{
for(y=1; y<16; y++)
{
if(sna[x][y]==i+1)
count++;//计算身体的节点数
}
}
}
if(count!=max)//如果计算的节点数与HEAD后的节点数值不同,就是有交叉了,咬到自己了
return false;
return true;
}
int judgeF(int (*sna)[17],int keym)
{
int randno();
int x,y,mark=0,i=randno(),j=randno();
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]==HEAD)
{
if(sna[x-1][y]==FOOD&&keym==72)
{
sna[x-1][y]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
if(sna[x+1][y]==FOOD&&keym==80)
{
sna[x+1][y]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
if(sna[x][y+1]==FOOD&&keym==77)
{
sna[x][y+1]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
if(sna[x][y-1]==FOOD&&keym==75)
{
sna[x][y-1]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
}
}
}
return 0;
}
/*----------------------------------------------------------------------------------------------------------------------------------*/
/*------------------↑ ↓ ← →变向※☆-------------------------------------------------------------------------------------------------*/
void downmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;//前面已经说了,12345....标记法,减去1的话,除了头部以外其他的就移动了。
}
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];//这个是求头部之后的值。
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]==HEAD)
{
sna[x+1][y]=HEAD;//头部的移动,
sna[x][y]=mark+1;//头部的赋值。 *应该是头部后面一个节点的赋值
return;
}
}
}
}
void upmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;
}
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]==HEAD)
{
sna[x-1][y]=HEAD;
sna[x][y]=mark+1;
return;
}
}
}
}
void leftmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;
}
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]==HEAD)
{
sna[x][y-1]=HEAD;
sna[x][y]=mark+1;
return;
}
}
}
}
void rightmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;
}
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0; x<16; x++)
{
for(y=0; y<16; y++)
{
if(sna[x][y]==HEAD)
{
sna[x][y+1]=HEAD;
sna[x][y]=mark+1;
return;
}
}
}
}
/*------------------------------------------------------*/
/*--------------------------------------------------*/
/*-------------游戏结束显示-------------------------*/
void gameover()
{
system("cls");
system("color F4");
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t");
printf("游戏结束\n\n");
printf("\t\t\t 您的最终得分为:%d\n\n",SCORE);
score[num]=SCORE;
enQueue(Q,SCORE);
printf("\t\t按Esc键退出并保存最高成绩,按任意键重新开始\n");
num++;
}
/*------------------------------------------------*/
/*------------------------文件输出最高得分---------------------------------------------------------------------------------------------------*/
void inscore(int sc[100],int n)//每次仅向文件输出最高得分
{
int max=0;
for(int i=0; i<n+1; i++)
{
if(sc[i]>max)
{
max=sc[i];
}
}
if(user==true)
{
ofstream write;
write.open("用户信息.txt",ios::app);
write<<max<<endl;
write.close();
}
}
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*--------------------主函数-------------------------------------------------------------------------------------------------------------*/
int main()
{
system("color 79");
InitQueue(Q);
InitStack(s);
InitStack(s2);
welcome();
return 0;
}
/*---------------------------------------------------------------------------------------------------------------------------------------*/
lipueue.cpp
#include "listack.h"
void InitQueue(LiQueue *&q) //初始化链队
{
q=(LiQueue *)malloc(sizeof(LiQueue));
q->front=q->rear=NULL;
}
void DestroyQueue(LiQueue *&q) //销毁链队
{
QNode *p=q->front,*r; //p指向队头数据节点
if (p!=NULL) //释放数据节点占用空间
{
r=p->next;
while (r!=NULL)
{
free(p);
p=r;
r=p->next;
}
}
free(p);
free(q); //释放链队节点占用空间
}
bool QueueEmpty(LiQueue *q) //判断链队是否为空
{
return(q->rear==NULL);
}
int QueueLength(LiQueue *q) //返回队列中数据元素个数
{
int n=0;
QNode *p=q->front;
while (p!=NULL)
{
n++;
p=p->next;
}
return(n);
}
void enQueue(LiQueue *&q,int e) //入队
{
QNode *p;
p=(QNode *)malloc(sizeof(QNode));
p->SCore=e;
p->next=NULL;
if (q->rear==NULL) //若链队为空,则新节点是队首节点又是队尾节点
q->front=q->rear=p;
else
{
q->rear->next=p; //将*p节点链到队尾,并将rear指向它
q->rear=p;
}
}
bool deQueue(LiQueue *&q,int &e) //出队
{
QNode *t;
if (q->rear==NULL) //队列为空
return false;
t=q->front; //t指向第一个数据节点
if (q->front==q->rear) //队列中只有一个节点时
q->front=q->rear=NULL;
else //队列中有多个节点时
q->front=q->front->next;
e=t->SCore;
free(t);
return true;
}
maopaopaixu.cpp
#include "listack.h"
void BubbleSort1(RecType R[],int n)
{
int i,j,k,exchange;
RecType tmp;
for (i=0; i<n-1; i++)
{
exchange=0;
for (j=n-1; j>i; j--) //比较,找出最小关键字的记录
if (R[j]<R[j-1])
{
tmp=R[j]; //R[j]与R[j-1]进行交换,将最小关键字记录前移
R[j]=R[j-1];
R[j-1]=tmp;
exchange=1;
}
//printf("i=%d: ",i);
if (exchange==0) //中途结束算法
break;
}
printf("您的%d次成绩排序为:",n);
for (k=0; k<n; k++)
printf("%d ",R[k]);
printf("\n");
printf("祝贺您有进步,下次请继续加油\n");
printf("您的信息已记录,xjp gluttonous snake 欢迎您下次登录^-^\n");
Sleep(1000);
}