用C语言实现推箱子小游戏基础程序plus

目录

设计一个简单的推箱子游戏

功能设计要求:

代码实现 

数据定义头文件data_def.h

窗口设置头文件WindowsSet.h

WindowsSet.cpp

上移函数

矩阵旋转函数

游戏帧

菜单设置

总代码

main函数

 

成果

设计一个简单的推箱子游戏

        该游戏是通过控制人的走向来移动箱子,箱子只能向前推,不能向后拉,且一次只能推动一个箱子。

功能设计要求:

  1. 人机操控平台:启动程序后,系统提供给用户一个操作界面,以便用户有效操作游戏。
  2. 创建并绘制地图:推箱子游戏需要创建不同的地图以增加游戏的趣味性。
  3. 选择地图:系统应提供两个及以上不同难度的地图以供用户选择。
  4. 移动操作:本游戏主要通过人或人和箱子的移动来进行的。系统接收用户输入一个字符(按键)来控制人的走向,并且可以在允许的情况下推动箱子。
  5. 移动步数和得分:移动步数是统计从开始游戏到游戏结束(通关)所走的总步数,在游戏过程中这是实时变化的。得分是统计每将一个箱子移动到目的地所获得的分数,只有当把所有箱子移动到指定目标位置后游戏结束(通关)。
  6. 游戏操作说明:系统给用户提供地图元素组成、操作规则等信息

代码实现 

        基础代码在用C语言实现推箱子小游戏基础程序_Cheat_Meric的博客-CSDN博客中实现。

        在用C语言实现推箱子小游戏基础程序_Cheat_陈十一的博客-CSDN博客中的解释较为详细细致,在这里不再对代码进行过多的解释,下面直接介绍代码。

        在上一代码的基础上,增加了菜单界面以及关卡选择

        在上一代码中提出的代码优化中,提出的旋转矩阵+上移操作以达成左右下移操作,在编写程序过程中发现虽然代码量减少,但是运行时长是之前的数十倍。

数据定义头文件data_def.h

#ifndef __DATA_DEF_H__
#define __DATA_DEF_H__

#define Box_Size 60
#define Box_Num 9
#define Round_Num 3

//记录玩家位置
struct Player
{
	int x;
	int y;
};
Player player;

enum Element { empty, wall, role, target, box, achieve, data_bg, role_target };
//1表示墙,0表示空地,2表示玩家位置,3目标位置,4箱子位置,5表示achieve,6表示data_bg,7表示role_target
int origin_Round[Round_Num][Box_Num][Box_Num + 1] = {
	{
		{1,1,1,1,1,1,1,1,1,6},
		{1,1,0,0,0,1,1,1,1,6},
		{1,1,0,0,0,1,0,0,1,6},
		{1,1,1,0,0,0,0,3,1,6},
		{1,1,1,0,1,1,1,3,1,6},
		{1,0,4,0,1,1,1,3,1,6},
		{1,0,4,4,1,1,1,1,1,6},
		{1,2,0,0,1,1,1,1,1,6},
		{1,1,1,1,1,1,1,1,1,6},
	},
	{
		{1,1,1,1,1,1,1,1,1,6},
		{1,1,1,3,3,5,3,1,1,6},
		{1,1,1,3,4,0,0,1,1,6},
		{1,1,1,1,0,4,0,1,1,6},
		{1,1,1,1,4,0,1,1,1,6},
		{1,1,1,2,4,0,1,1,1,6},
		{1,1,1,1,0,0,0,1,1,6},
		{1,1,1,1,1,1,1,1,1,6},
	},
	{
		{1,1,1,1,1,1,1,1,1,6},
		{1,1,target,0,0,0,box,0,1,6},
		{1,1,target,box,0,0,1,0,1,6},
		{1,1,target,1,0,1,0,0,1,6},
		{1,1,1,1,0,1,0,1,1,6},
		{1,1,1,0,box,0,0,1,1,6},
		{1,1,1,role,0,1,1,1,1,6},
		{1,1,1,1,1,1,1,1,1,6},
	},
};
//last_step[Box_Num][Box_Num + 1]用于悔棋,记录上一步操作
//First_Round[Box_Num][Box_Num + 1]每一关的矩阵
int last_step[Box_Num][Box_Num + 1], First_Round[Box_Num][Box_Num];

/*
* targetNum目标数量
* achievementNum箱子推到目标的成功数量
* steps记录步数
* level当前关卡
*/
int targetNum = 0, achievementNum = 0, steps, level;

/*
* Menu_Opt菜单选择
* Begin开始游戏的flag
* quit_flag退出判定
*/
int Menu_Opt = 0, Begin = 0, quit_flag = 0;
#endif // !__DATA_DEF_H__

一些会用到的数据的定义,由于origin_Round关卡数组比较多,所以单独存放在一个头文件中。

窗口设置头文件WindowsSet.h

#ifndef __WINDOWSSET_H__
#define __WINDOWSSET_H__

#ifndef __DATA_DEF_H__
#define	__DATA_DEF_H__
#include "data_def.h"
#endif // !__DATA_DEF_H__

int check_lose_win(void);//检查游戏是否结束
void Windows_Init(void);//窗口初始化
void Windows_Show(void);//展示游戏窗口
void Flash_Frame(void);//游戏帧轮询
void Next_Round(void);//下一关
void Start_Up(void);//开始界面
void clear_opt(void);//菜单界面选择的覆盖,覆盖之前的'@'
void Menu_Flash_Frame(void);//菜单界面帧
void matrix_up(void);//上移操作
void matrix_rotate(int m);//矩阵顺时针旋转m次

#endif // !__WINDOWSSET_H__

WindowsSet.cpp

        可以直接跳到最后一条总代码页看总代码

上移函数

//上移操作
void matrix_up(void)
{
	int role_x, role_y;
	role_x = player.x - 1;
	if (First_Round[role_x][player.y] == empty)
	{
		if (First_Round[player.x][player.y] == role)//如果此处是role
			First_Round[player.x][player.y] = empty;
		else//如果此处是role_target
			First_Round[player.x][player.y] = target;
		First_Round[role_x][player.y] = role;
		player.x = role_x;
		steps++;
	}
	else if (First_Round[role_x][player.y] == target)
	{
		if (First_Round[player.x][player.y] == role)//如果此处是role
			First_Round[player.x][player.y] = empty;
		else//如果此处是role_target
			First_Round[player.x][player.y] = target;
		First_Round[role_x][player.y] = role_target;
		player.x = role_x;
		steps++;
	}
	else if ((First_Round[role_x][player.y] == box || First_Round[role_x][player.y] == achieve) && (First_Round[role_x - 1][player.y] == empty || First_Round[role_x - 1][player.y] == target))//判断有wall
	{
		if (First_Round[role_x][player.y] == box)
		{
			if (First_Round[player.x][player.y] == role)//如果此处是role
				First_Round[player.x][player.y] = empty;
			else//如果此处是role_target
				First_Round[player.x][player.y] = target;
			First_Round[role_x][player.y] = role;
			player.x = role_x;
			if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve
			{
				First_Round[role_x - 1][player.y] = achieve;
				achievementNum++;
			}
			else
				First_Round[role_x - 1][player.y] = box;
		}
		else if (First_Round[role_x][player.y] == achieve)
		{
			achievementNum--;
			if (First_Round[player.x][player.y] == role)//此位置是玩家位置
				First_Round[player.x][player.y] = empty;//此位置变为空
			else //此位置是role_target
				First_Round[player.x][player.y] = target;
			First_Round[role_x][player.y] = role_target; //将box从target中推走,则此位置变成role_target
			player.x = role_x;
			if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve
			{
				First_Round[role_x - 1][player.y] = achieve;
				achievementNum++;
			}
			else
				First_Round[role_x - 1][player.y] = box;
		}
		steps++;
	}
}

矩阵旋转函数

        player结构体也要随着矩阵的旋转而旋转

        可以看到旋转矩阵操作要遍历多次数组

        顺时针旋转m阶矩阵就是将a[i][j]放在(j,m-i-1)处,所以使用temp来进行临时存储。

        这里也可以将matrix_rotate函数化为左移右移和下移函数

                #左移函数:行列交换后进行上移操作再换回

                #下移函数:按行倒序

                #右移函数:行列交换后的下移操作

        代码量比上一程序少且比这一程序的时间少,属于折中。

//矩阵顺时针旋转m次
//那么左移旋转1次,右移旋转3次,下移旋转2次
void matrix_rotate(int m)
{
	int temp[Box_Num][Box_Num];
	int temp_player_x, temp_player_y;
	for (int i = 0; i < m; i++)//旋转次数
	{
		for (int j = 0; j < Box_Num; j++)//行
		{
			for (int k = 0; k < Box_Num; k++)//列
			{
				temp[k][Box_Num - j - 1] = First_Round[j][k];
			}
		}
		for (int j = 0; j < Box_Num; j++)
		{
			for (int k = 0; k < Box_Num; k++)
			{
				First_Round[j][k] = temp[j][k];
			}
		}
		temp_player_x = player.y;
		temp_player_y = Box_Num - player.x - 1;
		player.x = temp_player_x;
		player.y = temp_player_y;
	}
}

游戏帧

        相应的,Flash_Frame函数的代码量显著减少

//游戏帧,轮询键盘
void Flash_Frame(void)
{
	char input;
	//_kbhit检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
	if (_kbhit())
	{
		input = _getch();
		switch (input)
		{
		case('w')://上移
			matrix_up();
			break;
		case('s')://下移
			matrix_rotate(2);
			matrix_up();
			matrix_rotate(2);
			break;
		case('a')://左移
			matrix_rotate(1);
			matrix_up();
			matrix_rotate(3);
			break;
		case('d')://右移
			matrix_rotate(3);
			matrix_up();
			matrix_rotate(1);
			break;
		case('r')://重玩
			Windows_Init();
			break;
		default:
			break;
		}
	}
}

菜单设置

         菜单设置还是用到基础的操作

//菜单界面
//暂未实现作者信息功能
void Start_Up(void)
{
	//背景色
	setfillcolor(RGB(255, 255, 255));
	fillrectangle(0, 0, Box_Num * Box_Size + 200, Box_Num * Box_Size);

	//菜单界面方块按钮样式
	setfillcolor(RGB(0x6f,0xf6,0xeb));
	setlinecolor(RGB(150, 150, 150));
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 120, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 70);
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 10);
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 50);
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 + 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 110);

	settextstyle(20, 0, _T("宋体"));
	outtextxy(Box_Size * Box_Num + 5, Box_Num * Box_Size / 2 + 150, _T("确定:空格"));

	//菜单界面的展示
	wchar_t level_str[3];
	setbkmode(OPAQUE);
	settextcolor(RGB(0, 0, 0));
	settextstyle(40, 0, _T("宋体"));
	_stprintf_s(level_str, _T("%d"), level+1);
	outtextxy(Box_Size * Box_Num/2 + 30, Box_Num * Box_Size / 2 - 115, _T("开始游戏"));
	outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 - 55, _T("关卡选择"));
	outtextxy(Box_Size * Box_Num - 40, Box_Num * Box_Size / 2 - 55, level_str);
	outtextxy(Box_Size * Box_Num / 2, Box_Num * Box_Size / 2 + 5, _T("查看作者信息"));
	outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 + 65, _T("结束游戏"));

	switch (Menu_Opt)//标识选择的位置
	{
	case(0):
		break;
	case(1):
		outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 115, _T("@"));
		break;
	case(2):
		outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 55, _T("@"));
		break;
	case(3):
		outtextxy(Box_Size * Box_Num / 2 - 20, Box_Num * Box_Size / 2 + 5, _T("@"));
		break;
	case(4):
		outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 + 65, _T("@"));
		break;
	default:
		break;
	}
	FlushBatchDraw();
}
void Menu_Flash_Frame(void)
{
	char input;
	if (_kbhit())
	{
		input = _getch();
		switch (input)
		{
		case('w')://选择按钮上移
			clear_opt();
			Menu_Opt--;
			if (Menu_Opt <= 0)
				Menu_Opt = 4;
			break;
		case('s')://选择按钮下移
			clear_opt();
			Menu_Opt++;
			if (Menu_Opt > 4)
				Menu_Opt = 1;
			break;
		case(' ')://确定按钮
			switch (Menu_Opt)
			{
			case(1):Begin = 1; Windows_Init(); break;//如果在'开始游戏'按钮处确定,则开始游戏
			case(2)://关卡选择
				level++;//关卡增加
				if (level >= Round_Num)//关卡越界则回到第一关
					level = 0;
				break;
			case(3):break;//作者信息界面
			case(4):quit_flag = 1; break;//退出程序
			default:
				break;
			}
			break;
		default:
			break;
		}
		Start_Up();
	}
}
//菜单界面选择的覆盖,覆盖之前的'@'
void clear_opt(void)
{
	switch (Menu_Opt)
	{
	case(0):
		break;
	case(1):
		outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 115, _T(" "));
		break;
	case(2):
		outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 55, _T(" "));
		break;
	case(3):
		outtextxy(Box_Size * Box_Num / 2 - 10, Box_Num * Box_Size / 2 + 5, _T(" "));
		break;
	case(4):
		outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 + 65, _T(" "));
		break;
	default:
		break;
	}
}

总代码

#include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include "data_def.h"
#include "WindowsSet.h"

//上移操作
void matrix_up(void)
{
	int role_x, role_y;
	role_x = player.x - 1;
	if (First_Round[role_x][player.y] == empty)
	{
		if (First_Round[player.x][player.y] == role)//如果此处是role
			First_Round[player.x][player.y] = empty;
		else//如果此处是role_target
			First_Round[player.x][player.y] = target;
		First_Round[role_x][player.y] = role;
		player.x = role_x;
		steps++;
	}
	else if (First_Round[role_x][player.y] == target)
	{
		if (First_Round[player.x][player.y] == role)//如果此处是role
			First_Round[player.x][player.y] = empty;
		else//如果此处是role_target
			First_Round[player.x][player.y] = target;
		First_Round[role_x][player.y] = role_target;
		player.x = role_x;
		steps++;
	}
	else if ((First_Round[role_x][player.y] == box || First_Round[role_x][player.y] == achieve) && (First_Round[role_x - 1][player.y] == empty || First_Round[role_x - 1][player.y] == target))//判断有wall
	{
		if (First_Round[role_x][player.y] == box)
		{
			if (First_Round[player.x][player.y] == role)//如果此处是role
				First_Round[player.x][player.y] = empty;
			else//如果此处是role_target
				First_Round[player.x][player.y] = target;
			First_Round[role_x][player.y] = role;
			player.x = role_x;
			if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve
			{
				First_Round[role_x - 1][player.y] = achieve;
				achievementNum++;
			}
			else
				First_Round[role_x - 1][player.y] = box;
		}
		else if (First_Round[role_x][player.y] == achieve)
		{
			achievementNum--;
			if (First_Round[player.x][player.y] == role)//此位置是玩家位置
				First_Round[player.x][player.y] = empty;//此位置变为空
			else //此位置是role_target
				First_Round[player.x][player.y] = target;
			First_Round[role_x][player.y] = role_target; //将box从target中推走,则此位置变成role_target
			player.x = role_x;
			if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve
			{
				First_Round[role_x - 1][player.y] = achieve;
				achievementNum++;
			}
			else
				First_Round[role_x - 1][player.y] = box;
		}
		steps++;
	}
}

//矩阵顺时针旋转m次
//那么左移旋转1次,右移旋转3次,下移旋转2次
void matrix_rotate(int m)
{
	int temp[Box_Num][Box_Num];
	int temp_player_x, temp_player_y;
	for (int i = 0; i < m; i++)//旋转次数
	{
		for (int j = 0; j < Box_Num; j++)//行
		{
			for (int k = 0; k < Box_Num; k++)//列
			{
				temp[k][Box_Num - j - 1] = First_Round[j][k];
			}
		}
		for (int j = 0; j < Box_Num; j++)
		{
			for (int k = 0; k < Box_Num; k++)
			{
				First_Round[j][k] = temp[j][k];
			}
		}
		temp_player_x = player.y;
		temp_player_y = Box_Num - player.x - 1;
		player.x = temp_player_x;
		player.y = temp_player_y;
	}
}

//菜单界面选择的覆盖,覆盖之前的'@'
void clear_opt(void)
{
	switch (Menu_Opt)
	{
	case(0):
		break;
	case(1):
		outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 115, _T(" "));
		break;
	case(2):
		outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 55, _T(" "));
		break;
	case(3):
		outtextxy(Box_Size * Box_Num / 2 - 10, Box_Num * Box_Size / 2 + 5, _T(" "));
		break;
	case(4):
		outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 + 65, _T(" "));
		break;
	default:
		break;
	}
}

//菜单界面帧
void Menu_Flash_Frame(void)
{
	char input;
	if (_kbhit())
	{
		input = _getch();
		switch (input)
		{
		case('w')://选择按钮上移
			clear_opt();
			Menu_Opt--;
			if (Menu_Opt <= 0)
				Menu_Opt = 4;
			break;
		case('s')://选择按钮下移
			clear_opt();
			Menu_Opt++;
			if (Menu_Opt > 4)
				Menu_Opt = 1;
			break;
		case(' ')://确定按钮
			switch (Menu_Opt)
			{
			case(1):Begin = 1; Windows_Init(); break;//如果在'开始游戏'按钮处确定,则开始游戏
			case(2)://关卡选择
				level++;//关卡增加
				if (level >= Round_Num)//关卡越界则回到第一关
					level = 0;
				break;
			case(3):break;//作者信息界面
			case(4):quit_flag = 1; break;//退出程序
			default:
				break;
			}
			break;
		default:
			break;
		}
		Start_Up();
	}
}

//菜单界面
//暂未实现作者信息功能
void Start_Up(void)
{
	//背景色
	setfillcolor(RGB(255, 255, 255));
	fillrectangle(0, 0, Box_Num * Box_Size + 200, Box_Num * Box_Size);

	//菜单界面方块按钮样式
	setfillcolor(RGB(0x6f,0xf6,0xeb));
	setlinecolor(RGB(150, 150, 150));
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 120, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 70);
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 10);
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 50);
	fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 + 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 110);

	settextstyle(20, 0, _T("宋体"));
	outtextxy(Box_Size * Box_Num + 5, Box_Num * Box_Size / 2 + 150, _T("确定:空格"));

	//菜单界面的展示
	wchar_t level_str[3];
	setbkmode(OPAQUE);
	settextcolor(RGB(0, 0, 0));
	settextstyle(40, 0, _T("宋体"));
	_stprintf_s(level_str, _T("%d"), level+1);
	outtextxy(Box_Size * Box_Num/2 + 30, Box_Num * Box_Size / 2 - 115, _T("开始游戏"));
	outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 - 55, _T("关卡选择"));
	outtextxy(Box_Size * Box_Num - 40, Box_Num * Box_Size / 2 - 55, level_str);
	outtextxy(Box_Size * Box_Num / 2, Box_Num * Box_Size / 2 + 5, _T("查看作者信息"));
	outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 + 65, _T("结束游戏"));

	switch (Menu_Opt)//标识选择的位置
	{
	case(0):
		break;
	case(1):
		outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 115, _T("@"));
		break;
	case(2):
		outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 55, _T("@"));
		break;
	case(3):
		outtextxy(Box_Size * Box_Num / 2 - 20, Box_Num * Box_Size / 2 + 5, _T("@"));
		break;
	case(4):
		outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 + 65, _T("@"));
		break;
	default:
		break;
	}
	FlushBatchDraw();
}

//检查是否成功或失败
int check_lose_win(void)
{
	int i, j;
	for (i = 1; i < Box_Num - 1; i++)
	{
		for (j = 1; j < Box_Num - 1; j++)
		{
			if (First_Round[i][j] == box && (First_Round[i + 1][j] == wall && First_Round[i][j + 1] == wall || First_Round[i - 1][j] == wall && First_Round[i][j - 1] == wall))
				return 0;//lose
			else if (First_Round[i][j] == box && (First_Round[i + 1][j] == wall && First_Round[i][j - 1] == wall || First_Round[i - 1][j] == wall && First_Round[i][j + 1] == wall))
				return 0;
		}
	}
	if (achievementNum == targetNum)
		return 1;//win
	return -1;
}

/*
* 游戏界面初始化
* 用于重玩
*/
void Windows_Init(void)
{
	initgraph(Box_Num * Box_Size + 150, Box_Num * Box_Size);
	setbkcolor(RGB(255, 255, 255));
	BeginBatchDraw();
	Start_Up();
	int i, j;
	targetNum = 0;
	//遍历第level关关卡给first_round
	for (i = 0; i < Box_Num; i++)
	{
		for (j = 0; j < Box_Num; j++)
		{
			First_Round[i][j] = origin_Round[level][i][j];
			if (origin_Round[level][i][j] == role)
			{
				player.x = i;
				player.y = j;
			}
			else if (origin_Round[level][i][j] == target)
				targetNum++;
		}
	}
	achievementNum = 0;
	steps = 0;
}

//在游戏win之后可以进入下一关卡
void Next_Round(void)
{
	while (1)
	{
		if (_kbhit())
		{
			char n;
			n = _getch();
			if (n == 'n')
			{
				level++;
				Windows_Init();
				break;
			}
		}
	}
}

//游戏场景
void Windows_Show(void)
{
	int i, j;
	cleardevice();
	//遍历二维关卡数据
	for (i = 0; i < Box_Num; i++)
	{
		for (j = 0; j < Box_Num; j++)
		{
			//空格子或数据背景色
			if (First_Round[i][j] == empty || First_Round[i][j] == data_bg)
			{
				setfillcolor(RGB(255, 255, 255));
				setlinecolor(RGB(255, 255, 255));
				fillrectangle(j * Box_Size, i * Box_Size, (j + 1) * Box_Size, (i + 1) * Box_Size);
			}
			else if (First_Round[i][j] == wall)//墙样式
			{
				setfillcolor(RGB(0x93, 0x84, 0x5c));
				setlinecolor(RGB(255, 255, 255));
				fillrectangle(j * Box_Size, i * Box_Size, (j + 1) * Box_Size, (i + 1) * Box_Size);
			}
			else if (First_Round[i][j] == role || First_Round[i][j] == role_target)//角色和角色与目标重合的样式
			{
				setfillcolor(RGB(0xf5, 0xc3, 0x42));
				setlinecolor(RGB(255, 255, 255));
				fillcircle((j + 0.5) * Box_Size, (i + 0.5) * Box_Size, 0.5 * Box_Size);
			}
			else if (First_Round[i][j] == box)//盒子样式
			{
				setfillcolor(RGB(0, 0, 255));
				setlinecolor(RGB(255, 255, 255));
				fillrectangle(j * Box_Size, i * Box_Size, (j + 1) * Box_Size, (i + 1) * Box_Size);
			}
			else if (First_Round[i][j] == target)//目标样式
			{
				setfillcolor(RGB(0, 255, 150));
				setlinecolor(RGB(255, 255, 255));
				fillrectangle((j + 0.3) * Box_Size, (i + 0.3) * Box_Size, (j + 0.7) * Box_Size, (i + 0.7) * Box_Size);
			}
			else if (First_Round[i][j] == achieve)//成功的目标样式
			{
				setfillcolor(RGB(15, 99, 60));
				setlinecolor(RGB(255, 255, 255));
				fillcircle((j + 0.5) * Box_Size, (i + 0.5) * Box_Size, 0.5 * Box_Size);
			}
		}
	}
	//OPAQUE不透明
	//SetBkMode函数来设置DrawText函数的输出方式
	wchar_t step_str[10], score_str[10];
	setbkmode(OPAQUE);
	settextcolor(RGB(0, 0, 0));
	settextstyle(30, 0, _T("宋体"));

	outtextxy(Box_Size * Box_Num + 5, 40, _T("操作:wsad"));
	outtextxy(Box_Size * Box_Num + 5, 80, _T("重玩:r"));

	outtextxy(Box_Size * Box_Num + 5, 160, _T("steps:"));
	_stprintf_s(step_str, _T("%d"), steps);
	outtextxy(Box_Size * Box_Num + 100, 160, step_str);

	outtextxy(Box_Size * Box_Num + 5, 200, _T("score:"));
	_stprintf_s(score_str, _T("%d"), achievementNum);
	outtextxy(Box_Size * Box_Num + 100, 200, score_str);

	if (check_lose_win() == 0)
	{
		//TRANSPARENT透明
		setbkmode(TRANSPARENT);
		settextcolor(RGB(255, 0, 0));
		settextstyle(80, 0, _T("宋体"));
		outtextxy(80, 200, _T("lose"));
	}
	else if (check_lose_win() == 1)
	{
		setbkmode(TRANSPARENT);
		settextcolor(RGB(0, 0, 0));
		settextstyle(80, 0, _T("宋体"));
		outtextxy(120, 150, _T("win"));
		settextstyle(40, 0, _T("宋体"));
		outtextxy(80, 220, _T("press 'n'to next round"));
	}
	FlushBatchDraw();
}

//游戏帧,轮询键盘
void Flash_Frame(void)
{
	char input;
	//_kbhit检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
	if (_kbhit())
	{
		input = _getch();
		switch (input)
		{
		case('w')://上移
			matrix_up();
			break;
		case('s')://下移
			matrix_rotate(2);
			matrix_up();
			matrix_rotate(2);
			break;
		case('a')://左移
			matrix_rotate(1);
			matrix_up();
			matrix_rotate(3);
			break;
		case('d')://右移
			matrix_rotate(3);
			matrix_up();
			matrix_rotate(1);
			break;
		case('r')://重玩
			Windows_Init();
			break;
		default:
			break;
		}
	}
}

main函数

#include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include "WindowsSet.h"

extern int Begin, quit_flag;//引入外部变量

int main()
{
	Windows_Init();
	while (1)
	{
		if (Begin)//开始游戏,游戏界面轮询
		{
			Windows_Show();
			if (check_lose_win() == 1)
				Next_Round();
			Flash_Frame();
		}
		else//菜单界面轮询
		{
			Menu_Flash_Frame();
		}
		if (quit_flag)//退出游戏
		{
			break;
		}
	};
	return 0;
}

        这里必须要用extern声明外部变量,否则无法引用

        暂时还没有查询到为什么在#include "data_def.h"后还是显示未声明变量。

成果

        将各个总代码整合便可得到最终成果

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值