皮卡丘推西瓜游戏 2019年1月12日

皮卡丘推西瓜游戏 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,操作更方便哦

以上是完整源程序代码链接。
——————————————分割线—————————————————
以下是游戏效果展示图。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43310774/article/details/86360876