皮卡丘推西瓜游戏 2019年1月12日
以下内容仅供娱乐,欢迎随时探讨,请多指教!
(1)游戏共有五关,由易到难,每一关都有初始化、按键处理、重置、退出功能。
(2)初始化包括屏幕初始化和每一关关卡的初始化,屏幕被初始化为宽600、高660。
(3)更新记录模块,实现学生个人信息和成绩信息的修改。
(4)按键处理包括移动小人和移动箱子,通过移动上下左右键控制小人的移动,从而推动箱子,以把箱子推到指定的目的地为完成通关。
(5)每一关都可以重置,按r键,可以重置当前关,空格回退一步。
(6)按Esc键可以在任何时候退出程序。
(7)输入信息有效性验证模块,验证用户数据输入是否有效合法。
以下为代码:
///////////////////////////////////////////////////////////
// 程序名称:皮卡丘推西瓜
// 编译环境:Visual C++ 6.0和Easyx图形库扩展实现
////////////////////////////////////////////////////////////
//游戏中用0表示空地,1表示人物,2表示箱子,3表示目的地,6表示围墙
////////////////////////////////////////////////////////////
#include "myhead.h"
#include "graphics.h"// 引用图形库头文件,可以置入图片
#include "conio.h"
#include "dos.h"
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
#include "time.h"
#include "windows.h"
#define M 21 //设置密码位数为20
/*定义结构体,储存信息*/
typedef struct winer
{
struct winer *before;
int t[10][10];
struct winer *next;
} winer;
int x,y; //人物坐标
int loop; //控制是否重新开始
IMAGE img[8]; //定义IMAGE对象数组来保存图片
int b[10][10]; //设置当前地图数组,用来接收地图便于读写
char user[M]; //设置账户名
char password[M]; //设置密码
int count=0; //记录步数
int begin, end; //定义开始和结束标志位
//游戏中用0表示空地,1表示人物,2表示箱子,3表示目的地,6表示围墙
const int map[5][10][10]= //定义三维地图数组
{
{ {0},
{0, 0, 6, 6, 6},
{0, 0, 6, 3, 6},
{0, 0, 6, 0, 6, 6, 6, 6},
{6, 6, 6, 2, 0, 2, 3, 6},
{6, 3, 0, 2, 1, 6, 6, 6},
{6, 6, 6, 6, 2, 6},
{0, 0, 0, 6, 3, 6},
{0, 0, 0, 6, 6, 6}
},
{ {6, 6, 6, 6, 6},
{6, 1, 0, 0, 6},
{6, 0, 2, 0, 6, 0, 6, 6, 6},
{6, 0, 0, 0, 6, 0, 6, 3, 6},
{6, 6, 6, 2, 6, 6, 6, 3 , 6},
{0, 6, 6, 0, 0, 0, 0, 0, 6},
{0, 6, 0, 0, 0, 6, 0, 0, 6},
{0, 6, 0, 0, 0, 6, 6, 6, 6},
{0, 6, 6, 6, 6, 6}
},
{ {0, 6, 6, 6, 6},
{0, 6, 1, 0, 6, 6, 6},
{0, 6, 0, 0, 0, 0, 6},
{6, 6, 6, 0, 6, 0, 6, 6},
{6, 3, 6, 0, 6, 0, 0, 6},
{6, 0, 2, 0, 0, 6, 0, 6},
{6, 3, 0, 0, 0, 2, 0, 6},
{6, 6, 6, 6, 6, 6, 6, 6}
},
{ {0, 6, 6, 6, 6, 6, 6, 6},
{0, 6, 0, 1, 0, 3, 3, 6},
{0, 6, 0, 0, 0, 6, 6, 6, 6},
{6, 6, 6, 0, 0, 0, 0, 0, 6},
{6, 0, 0, 0, 6, 2, 6, 0, 6},
{6, 0, 2, 0, 6, 0, 0, 0, 6},
{6, 0, 0, 0, 6, 6, 6, 6, 6},
{6, 6, 6, 6, 6}
},
{ {0, 6, 6, 6, 6, 6},
{0, 6, 0, 1, 0, 6, 6, 6},
{6, 6, 0, 6, 2, 0, 0, 6},
{6, 0, 0 ,3, 0, 3, 0, 6},
{6, 0, 0, 2, 2, 0, 6, 6},
{6, 6, 6, 0, 6, 3, 6},
{0, 0, 6, 0, 0, 0, 6},
{0, 0, 6, 6, 6, 6, 6}
}
};
//游戏中用0表示空地,1表示人物,2表示箱子,3表示目的地,6表示围墙
/*自定义函数原型*/
//
void blank(int x1,int y1); //画空地
void man (int x1,int y1); //画皮卡丘
void box (int x1,int y1); //画箱子
void dest (int x1,int y1); //画目的地
void man1 (int x1,int y1); //画在目的地上的皮卡丘
void box1 (int x1,int y1); //画在目的地上的箱子
void wall (int x1,int y1); //画围墙
void man2 (int x1,int y1); //画在胜利的皮卡丘
void print(int b[][10]); //把数组里的全画出来
void chush(); //初始化过程
winer *chushihua(); //初始化链表
void Drawjm(); //画标志
void scanpassword(); //从文件读入密码
void free_list(winer *head); //释放链表
//xiao
void move (int b[][10],int x1, int y1); //移动
void find (int b[][10]); //找人物坐标
int win (int b[][10]); //判断游戏是否结束
void saveinformation(int i); //该函数用于玩家游戏信息
void changepassword(); //该函数用于修改系统密码
//chen
void huanying(); //欢迎界面
int play (int b[][10],int i); //游戏过程
void tips(); //输出提示信息
void pass(); //密码登录界面
int passyanz(); //此函数用于验证密码,密码支持20位的字符
void savepassword(); //该函数用于文件保存系统密码
void Printspace(int a); //输出空格
void Drawmenu(); //画菜单
void playguanka(); //游戏关卡
//li
/*自定义函数原型*/
winer *head=chushihua(); //头
winer *p=NULL,*q=head; //链表相关
/*******************函数定义*******************/
void Drawmenu()
{
Printspace(50);
printf("╔═══════════════╗\n");
Printspace(50);
printf("║ 1.开始游戏 ║\n");
Printspace(50);
printf("╚═══════════════╝\n\n");
Printspace(50);
printf("╔═══════════════╗\n");
Printspace(50);
printf("║ 2.修改密码 ║\n");
Printspace(50);
printf("╚═══════════════╝\n\n");
Printspace(50);
printf("╔═══════════════╗\n");
Printspace(50);
printf("║ 3.提示信息 ║\n");
Printspace(50);
printf("╚═══════════════╝\n\n");
Printspace(50);
printf("╔═══════════════╗\n");
Printspace(50);
printf("║ 4.退出游戏 ║\n");
Printspace(50);
printf("╚═══════════════╝\n\n");
}
//输出空格
void Printspace(int a)
{
for(int i=0;i<a;i++)
printf(" ");
}
//画界面
void Drawjm()
{
Printspace(35);
printf("╔");
for(int i=1;i<=46;i++)
printf("═");
printf("╗\n");
Printspace(35);
printf("║");
Printspace(18);
printf(" 推 箱 子 ");
Printspace(18);
printf("║\n");
Printspace(35);
printf("╚");
for(i=1;i<=46;i++)
printf("═");
printf("╝\n");
printf("\n\n");
}
//从文件读入密码
void scanpassword()
{
FILE *fp;
fp=fopen("c:\\aaAA\\user.txt","r");
if(fp == NULL)
{
printf("打开失败!\n");
getch();
}
else
{
fscanf(fp,"%s",password);
printf("打开成功,读写成功!1\n");
fclose(fp);
}
}
//此函数用于验证密码,密码支持20位的字符
int passyanz()
{
int x,n=1;
system("cls");
Drawjm();
printf("请输入用户名:");
scanf("%s",user);
printf("tips:初始密码为123\n");
for(;; n++)
{
if(n<=3)
{
char ch,inpassword[M];
int i=0;
printf("请输入密码:");
while((ch=getch())!='\r' && i<=M)
{
if(ch=='\b')
{
if(i>0)
{
i--;
printf("\b \b");// 密码支持退格的实现
}
else
putchar(7);
}
else
{
inpassword[i++]=ch;
printf("*");
}
}
inpassword[i]='\0';
if(strcmp(inpassword,password) == 0)
{
printf("\n密码正确\t请继续操作\n");
x=1;
return x;
}
else
{
printf("\n密码错误\t您还有%d次机会\n",3-n);
}
}
else
{
printf("\n密码均错误\t无法继续操作!\n");
x=0;
return x;
}
}
system("pause");
}
//该函数用于修改系统密码
void changepassword()
{
char ch1,ch2,passwordtemp[M],password2[M];
int i=0,j=0,x;
do
{
i=0,j=0;
printf("请输入新密码\n");
while((ch1=getch())!='\r' && i<=M)
{
if(ch1=='\b')
{
if(i>0)
{
i--;
printf("\b \b");// 密码支持退格的实现
}
else
putchar(7);
}
else
{
passwordtemp[i++]=ch1;
printf("*");
}
}
passwordtemp[i]='\0';
printf("\n请确认新密码\n");
while((ch2=getch())!='\r' && j<=M)
{
if(ch2=='\b')
{
if(j>0)
{
j--;
printf("\b \b");// 密码支持退格的实现
}
else
putchar(7);
}
else
{
password2[j++]=ch2;
printf("*");
}
}
password2[j]='\0';
if(strcmp(passwordtemp,password2)==0)
{
x=0;
printf("\n密码修改成功!\n");
system("pause");
}
else
{
x=1;
printf("\n两次输入密码不同,请再设置一遍\n");
}
}
while(x);
for(i=0; i<=M; i++)
{
password[i]=passwordtemp[i];
}
savepassword();
}
//该函数用于文件保存系统密码
void saveinformation(int i)//该函数用于玩家游戏信息
{
FILE *fp;
fp=fopen("c:\\aaAA\\information.txt","a");
if(fp == NULL)
{
printf("打开失败!\n");
getch();
}
else
{
fprintf(fp,"%s\t%d\t%d\t%.2f\n",user,i+1,count,1.0*(end-begin)/1000);
printf("打开成功,读写成功!2\n");
fclose(fp);
}
}
void savepassword()
{
FILE *fp;
fp=fopen("c:\\aaAA\\user.txt","w");
if(fp == NULL)
{
printf("打开失败!\n");
getch();
}
else
{
fprintf(fp,"%s",password);
printf("打开成功,读写成功!2\n");
fclose(fp);
}
}
//初始化背景和载入图片
void chush()
{
initgraph(600,660);
setbkcolor(LIGHTCYAN);
cleardevice();
loadimage(&img[0], "图片\\0.jpg");
loadimage(&img[1], "图片\\1.jpg");
loadimage(&img[2], "图片\\2.jpg");
loadimage(&img[3], "图片\\3.jpg");
loadimage(&img[4], "图片\\4.jpg");
loadimage(&img[5], "图片\\5.jpg");
loadimage(&img[6], "图片\\6.jpg");
loadimage(&img[7], "图片\\7.jpg");
}
//画空地
void blank(int x1, int y1)
{
putimage(y1, x1, &img[0]); // 在坐标 (y1, x1) 位置显示 IMAGE 对象
}
//画皮卡丘
void man(int x1, int y1)
{
putimage(y1, x1, &img[1]);
}
//画箱子
void box(int x1, int y1)
{
putimage(y1, x1, &img[2]);
}
//画目的地
void dest(int x1, int y1)
{
putimage(y1, x1, &img[3]);
}
//画在目的地上的皮卡丘
void man1(int x1, int y1)
{
putimage(y1, x1, &img[4]);
}
//画在目的地上的箱子
void box1(int x1, int y1)
{
putimage(y1, x1, &img[5]);
}
//画围墙
void wall(int x1, int y1)
{
putimage(y1, x1, &img[6]);
}
//画胜利的皮卡丘
void man2(int x1, int y1)
{
putimage(y1, x1, &img[7]);
}
//把数组里的全画出来
void print(int b[][10])
{
for(int x1 = 0; x1 < 10; x1++)
for(int y1 = 0; y1 < 10; y1++)
putimage(60 * y1, 60 * x1, &img[b[x1][y1]]);
}
//输出提示信息
void tips()
{
printf("游戏玩法:"
"游戏一共5关\n"
"1.方向键和wsad上下左右移动\n"
"2.r键重新开始当前关\n"
"3.空格回退(请不要疯狂点)\n"
"4.经典的推箱子是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力。\n"
"在一个狭小的仓库中,要求把西瓜放到指定的位置,稍不小心就会出现西瓜\n"
"无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,\n"
"合理安排移动的次序和位置,才能顺利的完成任务。 每一关经过精心筛选,\n"
"绝对具有挑战性!下面请开始你的游戏。\n\n\n");
}
//释放链表
void free_list(winer *head)
{
winer *temp=head ;
while(temp!=NULL)
{
head=head->next;
free(temp);
temp=head;
}
}
//找人物坐标x,y
void find(int b[][10])
{
for(x = 0; x < 10; x++)
for(y = 0; y < 10; y++)
if(b[x][y] == 1) return;
}
//判断游戏是否结束
int win(int b[][10])
{
for(int x1 = 0; x1 < 10; x1++)
for(int y1 = 0; y1 < 10; y1++)
if(b[x1][y1] == 2) return 0; //如果还有箱子返回假
return 1; //如果没有箱子返回真
}
//移动过程函数
void move(int b[][10], int x1, int y1)
{
if(b[x+x1][y+y1] == 0 || b[x+x1][y+y1] == 3)
{
count++;
p=(winer*)malloc(sizeof(struct winer));
q->next=p;//接起
for(int j = 0; j < 10; j++)
for(int k = 0; k < 10; k++)
p->t[j][k] = b[j][k];//记录信息
p->next=NULL;
p->before=q;//接起
q=p;
b[x][y]--;
b[x + x1][y + y1]++;
for(int i = 0; i < 60; i++) //过渡动画,看起来舒服
{
blank(60 * x + i * x1, 60 * y + i * y1); //画空地
man(60 * x + (i + 1) * x1, 60 * y + (i + 1) * y1);
Sleep(10);
}
if(b[x][y] == 3)
dest(60 * x, 60 * y);
x += x1;
y += y1;
if(b[x][y] == 4)
man1(60 * x, 60 * y);
}
else if((b[x+x1][y+y1] == 2 || b[x+x1][y+y1] == 5) && (b[x+2*x1][y+2*y1] == 0 || b[x+2*x1][y+2*y1] == 3))
{
count++;
p=(winer*)malloc(sizeof(struct winer));
q->next=p;//接起
for(int j = 0; j < 10; j++)
for(int k = 0; k < 10; k++)
p->t[j][k] = b[j][k];//记录信息
p->next=NULL;
p->before=q;//接起
q=p;
b[x][y]--;
b[x + x1][y + y1]--;
b[x + 2 * x1][y + 2 * y1] += 2; //并用,全部为箱子的不同状态
for(int i = 0; i < 60; i++) //过渡动画,看起来舒服
{
blank(60 * (x + x1) + i * x1, 60 * (y + y1) + i * y1); //画空地
box(60 * (x + x1) + (i + 1) * x1, 60 * (y + y1) + (i + 1) * y1);
blank(60 * x + i * x1, 60 * y + i * y1); //画空地
man(60 * x + (i + 1) * x1, 60 * y + (i + 1) * y1);
Sleep(10);
}
if(b[x][y] == 3)
dest(60 * x, 60 * y);
x += x1;
y += y1;
if(b[x][y] == 4)
man1(60 * x, 60 * y);
if(b[x+x1][y+y1] == 5)
box1(60 * (x + x1), 60 * (y + y1));
}
}
//游戏过程
int play(int b[][10],int i)
{
loop = 0;
int m,n;
chush();
print(b); //画界面
find(b); //通过find函数寻找人物的x, y坐标
do
{
switch(getch()) //获取键盘
{
case 'w':
case 'W':
move(b, -1, 0);
break; //上移
case 'a':
case 'A':
move(b, 0, -1);
break; //左移
case 'd':
case 'D':
move(b, 0, 1);
break; //右移
case 's':
case 'S':
move(b, 1, 0);
break; //下移
case 'r':
case 'R'://重新开始当前关
loop = 1;
return 0;
case ' '://回退功能
if(p == NULL || p->before==NULL || p==head)
{
break;
}
else
{
for(m = 0; m < 10; m++)
for(n = 0; n < 10; n++)
b[m][n] = p->t[m][n];
p=p->before;
free(p->next);
p->next=NULL;
find(b);
print(b);//画界面
count--;
break;
}
case 27: //ESC结束
exit(0); //结束游戏
break;
case 0:
case 0xE0: //如果是方向键
switch(getch()) //再次获取键盘
{
case 72:
move(b, -1, 0);
break;
case 75:
move(b, 0, -1);
break;
case 77:
move(b, 0, 1);
break;
case 80:
move(b, 1 , 0);
}
}
char grade[M] = { 0 };
sprintf(grade, "%d", count);
setbkmode(0);//文字背景透明
settextcolor(LIGHTMAGENTA);
settextstyle(50, 0, _T("宋体"));
clearrectangle(0, 600,600, 660);
outtextxy(0, 600, "步数:");
outtextxy(150, 600, grade);
end=clock();//结束计时
char time[M] = { 0 };
sprintf(time, "%.2f秒",1.0*(end-begin)/1000 );
outtextxy(275, 600, "时间:");
outtextxy(400, 600, time);
}
while(!win(b)); //通过win函数判断是否通过
man2(60 * x, 60 * y);//画一个开心的皮卡丘
saveinformation(i);
getch();
free_list(head); //释放链表
huanying(); //过渡动画
return 0;
}
//游戏关卡
void playguanka()
{
int i;
while(1)
{
system("color f9");
system("cls");
Drawjm();
tips();
do
{
printf("请输入你想要玩第几关(1—5)\ttips:0退出\n");
scanf("%d",&i);
if(i<0 || i>5)printf("输入有错误!\n");
}
while(i<0 || i>5);
i--;
if(-1 == i)return;
huanying();
do
{
loop=0; //loop置为0
for(int x1 = 0; x1 < 10; x1++)
for(int y1 = 0; y1 < 10; y1++)
b[x1][y1] = map[i][x1][y1]; //对当前地图数组分别赋值
count=0;
begin=clock();
play(b,i);
}
while(loop); //如果loop被置为1则重新开始
//printf("重新选择\n");
}
}
//欢迎界面
void huanying()
{
initgraph(210, 210); // 创建绘图窗口,大小为 210x210 像素
for(int i=0; i<6; i++)
{
// 设置背景色为蓝色
setbkcolor(RGB(rand()%256,rand()%256,rand()%256));
// 用背景色清空屏幕
cleardevice();
setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 10);
setlinecolor(RGB(rand()%256,rand()%256,rand()%256));//设置线颜色
setfillcolor(RGB(rand()%256,rand()%256,rand()%256));//设置填充颜色
fillrectangle(50,50,150,150);//画矩形
circle(100, 100, 100); // 画圆,圆心(200, 200),半径 100
setfillcolor(RGB(rand()%256,rand()%256,rand()%256));//设置填充颜色
fillcircle(100,100,35);
setfillcolor(RGB(rand()%256,rand()%256,rand()%256));//设置填充颜色
//solidpolygon
// 设置当前字体为高 16 像素的“宋体”。
settextstyle(16, 0, _T("宋体"));
settextcolor(RGB(rand()%256,rand()%256,rand()%256));
// 在屏幕中央输出字符串
RECT r = {0, 0, 210, 210};
drawtext(_T("游戏载入中..."), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
srand(time(NULL));
Sleep(500);
}
closegraph(); // 关闭绘图窗
}
//初始化链表
winer *chushihua()
{
winer *head;
head=(winer*)malloc(sizeof (winer));
if(head == NULL)
{
printf("申请头结点失败!\n");
return NULL;
}
head->next=NULL;
head->before=NULL;
return head;
}
//密码登录界面
void pass()
{
scanpassword();
passyanz();
}
//主函数
int main()
{
system("color f9");
huanying();
pass();
while(1)
{
int c;
back:
system("cls");
Drawjm();
do
{
Drawmenu();
scanf("%d",&c);
}
while(c<1 || c>4);
switch(c)
{
case 1:
printf("回车开始游戏\n");
getch();
system("cls");
huanying();
playguanka();
break;
case 2:
passyanz();
changepassword();
goto back;
break;
case 3:
tips();
getch();
break;
case 4:
exit(0);
break;
default:
printf("错误输入!!!\n");
break;
}
closegraph();
}
return 0;
}
链接:https://pan.baidu.com/s/17YZvTb3512e9YmbB76IVQA 提取码:c9nz 复制这段内容后打开百度网盘手机App,操作更方便哦
以上是完整源程序代码链接。
——————————————分割线—————————————————
以下是游戏效果展示图。