推箱子游戲利用圖形庫實現 2019年1月12日

皮卡丘推西瓜遊戲 2019年1月12日
以下內容僅供娛樂,歡迎隨時探討,請多指教

(1)遊戲共有五關,由易到難,每一關都有初始化、按鍵處理、重置、退出功能。
(2)初始化包括屏幕初始化和每一關關卡的初始化,屏幕被初始化爲寬600、高660。
(3)更新記錄模塊,實現學生個人信息和成績信息的修改。
(4)按鍵處理包括移動小人和移動箱子,通過移動上下左右鍵控制小人的移動,從而推動箱子,以把箱子推到指定的目的地爲完成通關。
(5)每一關都可以重置,按r鍵,可以重置當前關,空格回退一步。
(6)按Esc鍵可以在任何時候退出程序。
(7)輸入信息有效性驗證模塊,驗證用戶數據輸入是否有效合法。

想要源代碼可以參考百度雲文件,下面?

鏈接:https://pan.baidu.com/s/17YZvTb3512e9YmbB76IVQA 提取碼:c9nz 複製這段內容後打開百度網盤手機App,操作更方便哦

以上是完整源程序代碼鏈接。
——————————————分割線—————————————————
以下是遊戲效果展示圖。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
以下爲代碼:

///////////////////////////////////////////////////////////
// 程序名稱:皮卡丘推西瓜
// 編譯環境:Visual C++ 6.0
////////////////////////////////////////////////////////////
//遊戲中用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("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("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("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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章