ADD file via upload

main
pcnqv9ze5 5 months ago
parent e55c4c3e10
commit 50ec66ef78

@ -0,0 +1,935 @@
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <mmsystem.h>
#include <string>
#include <ctime>
#include <iostream>
#include <vector>
#pragma comment(lib,"winmm.lib") //静态库资源
#define ROW 12
#define COL 12
using namespace std;
const int WALL = 1;
const int BOX = 4;
const int TARGET = 3;
const int PLAYER = 5;
const int EMPTY = 0;
const int _SIZE = 12;
int DUISHU = 3;
const std::vector<std::pair<int, int>> dir = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
class MyMap {
public:
int Map[_SIZE][_SIZE]{ WALL };
private:
int X1{}, X2{}, Y1{}, Y2{};//分别为1、2步之前的坐标
int X{}, Y{}, Direction{};//当前坐标、方向
int PX{}, PY{};//玩家坐标
int StartX{}, StartY{};//记录起点,用于生成箱子
bool test() {//一定程度避免随机数整烂活;
int test{};
for (int i = 0; i < _SIZE; i++) {
for (int j = 0; j < _SIZE; j++) {
if (Map[i][j] == 3)test += 1;
if (Map[i][j] == 4)test += 10;
if (Map[i][j] == 5)test += 100;
}
}
return (test == 100 + 11 * DUISHU);
}
bool _near(int StartX, int StartY, int X, int Y) {
return (StartX == X + 1 && StartY == Y ||
StartX == X - 1 && StartY == Y ||
StartY == Y + 1 && StartX == X ||
StartY == Y - 1 && StartX == X);
}
void update() {
X2 = X1;
Y2 = Y1;
X1 = X;
Y1 = Y;
}
void change(int x, int y) {
if (Map[x][y] == WALL) {
Map[x][y] = EMPTY;
}
}
void through() {//打通箱子周边,使得每个箱子都可推动
int dx = StartX - PX, dy = StartY - PY;
if (dx == 0) {
change(StartX + 2 * (StartX > _SIZE / 2) - 1, StartY);
change(StartX + 2 * (StartX > _SIZE / 2) - 1, StartY + 1);
change(StartX + 2 * (StartX > _SIZE / 2) - 1, StartY - 1);
}
if (dy == 0) {
change(StartX, StartY + 2 * (StartX > _SIZE / 2) - 1);
change(StartX - 1, StartY + 2 * (StartX > _SIZE / 2) - 1);
change(StartX + 1, StartY + 2 * (StartX > _SIZE / 2) - 1);
}
}
public:
MyMap() {
for (int i = 0; i < _SIZE; i++) {
for (int j = 0; j < _SIZE; j++) {
Map[i][j] = WALL;
}
}
}//初始化
bool generatemap(int Complexity) {
int time{};
do {//主体
for (int i = 0; i < _SIZE; i++) {
for (int j = 0; j < _SIZE; j++) {
Map[i][j] = WALL;
}
}//初始化
for (int a = 0; a < DUISHU; a++)//箱子与目标的对数
{
do {
X = rand() % (_SIZE - 4) + 2;
Y = rand() % (_SIZE - 4) + 2;
time++;
if (time > 100) {
std::cout << "error" << std::endl;
return 0;
}//防死循环
} while (Map[X][Y] != WALL);//在墙上生成起点
time = 0;
StartX = X; StartY = Y;//记录起点,用于生成箱子
do {
int _time{};//实际运动次数
for (int i = 0; i < Complexity; i++) {
int temp = rand() % 6;
switch (temp) {
case 0:
Direction++;
break;
case 1:
Direction--;
}//控制直走和转弯的概率,不要频繁转弯且不会掉头
Direction = (4 + Direction) % 4;//防止负数
if (//各种不宜移动的情况
X + dir[Direction].first <= 2 ||
X + dir[Direction].first >= _SIZE - 3 ||
Y + dir[Direction].second <= 2 ||
Y + dir[Direction].second >= _SIZE - 3 ||
Map[X + dir[Direction].first][Y + dir[Direction].second] == BOX
) {
continue;
}
update();
X += dir[Direction].first;
Y += dir[Direction].second;
change(X, Y);
change(X - 2 * dir[Direction].first, Y - 2 * dir[Direction].second);
if (_time > 0) {
change(
dir[Direction].first == 0 ? X2 : X - 2 * dir[Direction].first,
dir[Direction].second == 0 ? Y2 : Y - 2 * dir[Direction].second
);
}
if (_time == 0) {
PX = X - 2 * dir[Direction].first;
PY = Y - 2 * dir[Direction].second;
}//生成玩家
_time++;
}
Map[StartX][StartY] = BOX;
Map[X][Y] = TARGET;
} while (_near(StartX, StartY, X, Y));
through();
}
Map[PX][PY] = PLAYER;
} while (test() == 0);
for (int i = 0; i < _SIZE; i++)//修复墙壁
{
for (int j = 0; j < _SIZE; j++) {
if (i == 0 || j == 0 || i == _SIZE - 1 || j == _SIZE - 1) {
Map[i][j] = WALL;
}
}
}
return 1;
}
void printmap() {
std::cout << std::endl;
for (int i = 0; i < _SIZE; i++) {
for (int j = 0; j < _SIZE; j++) {
std::cout << Map[i][j] << ' ';
}
std::cout << std::endl;
}
}
};
//用三维数组特定的数字描绘出这个地图
int cas = 0;//地图编号
int _count = 0;//已走步数
wchar_t result[10] = { L"0" };//用来显示步数
int temp_map[ROW][COL] = { 0 };//用来暂存地图,以备重置
char c[10] = { 0 };
int map[4][ROW][COL] = { 0 };
IMAGE img[6]; //6张图片6个名字
IMAGE* bacground=new IMAGE;
void loadResource()
{
loadimage(img + 0, L"0.bmp", 50, 50);
loadimage(img + 1, L"1.bmp", 50, 50);
loadimage(img + 2, L"3.bmp", 50, 50);
loadimage(img + 3, L"4.bmp", 50, 50);
loadimage(img + 4, L"5.bmp", 50, 50);
loadimage(img + 5, L"7.bmp", 50, 50);
loadimage(bacground, L"背景.png", 50, 50);
}
//绘制地图
void drawGraph()
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
//算贴图的坐标
int x = 50 * j;
int y = 50 * i;
switch (map[cas][i][j])
{
case 0:
//一个汉字符号占用两个位置
//printf(" ");
putimage(x, y, img + 0);
break;
case 1:
putimage(x, y, img + 1);
//printf("■");
break;
case 3:
putimage(x, y, img + 2);
//printf("☆");
break;
case 4:
putimage(x, y, img + 3);
//printf("★");
break;
case 5:
case 8:
putimage(x, y, img + 4);
//printf("人");
break;
case 7:
putimage(x, y, img + 5);
//printf("●");
break;
}
}
//printf("\n");
}
}
void drawGraph1()//绘制背景图
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
int x = 50 * j;
int y = 50 * i;
putimage(x, y, bacground);
}
}
}
//玩游戏
void keyDown()
{
int userKey = _getch(); //不可见输入
//定位:找到人的位置
int i = 0;
int j = 0;
for (i = 1; i < ROW; i++)
{
for (j = 1; j < COL; j++)
{
if (map[cas][i][j] == 5 || map[cas][i][j] == 8)
{
goto NEXT;
}
}
}
NEXT:
//我们这个游戏用什么按键去玩
switch (userKey)
{
case 'W':
case 'w':
case 72:
if (map[cas][i - 1][j] == 0 || map[cas][i - 1][j] == 3)
{
map[cas][i][j] -= 5;
map[cas][i - 1][j] += 5;
_count++;
}
if (map[cas][i - 1][j] == 4 || map[cas][i - 1][j] == 7)
{
if (map[cas][i - 2][j] == 0 || map[cas][i - 2][j] == 3)
{
map[cas][i][j] -= 5;
map[cas][i - 1][j] += 1;
map[cas][i - 2][j] += 4;
_count++;
}
}
break;
case 's':
case 'S':
case 80:
if (map[cas][i + 1][j] == 0 || map[cas][i + 1][j] == 3)
{
map[cas][i][j] -= 5;
map[cas][i + 1][j] += 5;
_count++;
}
if (map[cas][i + 1][j] == 4 || map[cas][i + 1][j] == 7)
{
if (map[cas][i + 2][j] == 0 || map[cas][i + 2][j] == 3)
{
map[cas][i][j] -= 5;
map[cas][i + 1][j] += 1;
map[cas][i + 2][j] += 4;
_count++;
}
}
break;
case 'a':
case 'A':
case 75:
if (map[cas][i][j - 1] == 0 || map[cas][i][j - 1] == 3)
{
//a+=1 a=a+1 复合赋值运算符
map[cas][i][j] -= 5;
map[cas][i][j - 1] += 5;
_count++;
}
if (map[cas][i][j - 1] == 4 || map[cas][i][j - 1] == 7)
{
if (map[cas][i][j - 2] == 0 || map[cas][i][j - 2] == 3)
{
map[cas][i][j] -= 5;
map[cas][i][j - 1] += 1;
map[cas][i][j - 2] += 4;
_count++;
}
}
break;
case 'd':
case 'D':
case 77:
if (map[cas][i][j + 1] == 0 || map[cas][i][j + 1] == 3)
{
map[cas][i][j] -= 5;
map[cas][i][j + 1] += 5;
_count++;
}
if (map[cas][i][j + 1] == 4 || map[cas][i][j + 1] == 7)
{
if (map[cas][i][j + 2] == 0 || map[cas][i][j + 2] == 3)
{
map[cas][i][j] -= 5;
map[cas][i][j + 1] += 1;
map[cas][i][j + 2] += 4;
_count++;
}
}
break;
case 'z'://按下z重置
case 'Z':
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
map[cas][i][j] = temp_map[i][j];
}
}
_count = 0;
for (int k = 0; k < 10; k++)
{
result[k] = 0;
}
result[0] = L'0';
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(145, 55, L"已走步数:");
outtextxy(230, 55, result);
break;
case 'x':
case 'X':
cas = 3;
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
map[cas][i][j] = 0;
}
}
break;
}
}
//胜负的判断:
int gameOver()
{
//地图上没有箱子就可以结束
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[cas][i][j] == 4)
{
return 0;
}
}
}
return 1;
}
class Button
{
private:
int x; // 按钮左上角x坐标
int y; // 按钮左上角y坐标
int width; // 按钮宽度
int height; // 按钮高度
float scale; // 缩放比例,用于实现鼠标悬停效果
bool isMouseOver; // 表示鼠标是否在按钮上方
bool has_been_clicked;//表示此按钮是否被点击过(主要用于难度选择)
wstring text; // 按钮文本
public:
Button(int x, int y, int width, int height, const wstring& text)
: x(x), y(y), width(width), height(height), text(text), scale(1.0f), isMouseOver(false),has_been_clicked(false)
{
}
// 检查鼠标是否在按钮上方
void checkMouseOver(int mouseX, int mouseY)
{
isMouseOver = (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height);
if (isMouseOver) {
scale = 1.0f; // 鼠标悬停时缩放按钮
}
else {
scale = 1.0f; // 恢复按钮原始大小
}
}
// 检查鼠标点击是否在按钮内,并执行函数
bool checkClick(int mouseX, int mouseY)
{
if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height)
{
has_been_clicked_convert();
isMouseOver = false;
scale = 1.0f;
return true;
}
return false;
}
void has_been_clicked_convert()
{
if (has_been_clicked == false)
has_been_clicked = true;
else
has_been_clicked = false;
}
bool get_has_been_clicked()
{
return has_been_clicked;
}
// 绘制按钮
void draw()
{
int scaledWidth = width * scale; // 缩放后的按钮宽度
int scaledHeight = height * scale; // 缩放后的按钮高度
int scaledX = x + (width - scaledWidth) / 2; // 缩放后的按钮x坐标
int scaledY = y + (height - scaledHeight) / 2; // 缩放后的按钮y坐标
if (isMouseOver || has_been_clicked)
{
setlinecolor(RGB(0, 120, 215)); // 鼠标悬停时按钮边框颜色
setfillcolor(RGB(229, 241, 251)); // 鼠标悬停时按钮填充颜色
}
else
{
setlinecolor(RGB(173, 173, 173)); // 按钮边框颜色
setfillcolor(RGB(225, 225, 225)); // 按钮填充颜色
}
fillrectangle(scaledX, scaledY, scaledX + scaledWidth, scaledY + scaledHeight); // 绘制按钮
settextcolor(BLACK); // 设置文本颜色为黑色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(20 * scale, 0, _T("微软雅黑")); // 设置文本大小和字体
//居中显示按钮文本
int textX = scaledX + (scaledWidth - textwidth(text.c_str())) / 2; // 计算文本在按钮中央的x坐标
int textY = scaledY + (scaledHeight - textheight(_T("微软雅黑"))) / 2; // 计算文本在按钮中央的y坐标
outtextxy(textX, textY, text.c_str()); // 在按钮上绘制文本
}
};
void play_easy()
{
const wchar_t* mapping = L"0123456789";
_count = 0;
std::srand(static_cast<unsigned int>(std::time(0)));
MyMap _map{};
DUISHU = 2;
for (int i = 0; i < 4; i++)
{
while (!_map.generatemap(50))
{
if (_map.generatemap(50))
{
break;
}
}
for (int j = 0; j < ROW; j++)
{
for (int k = 0; k < COL; k++)
{
map[i][j][k] = _map.Map[j][k];
}
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
temp_map[i][j] = map[cas][i][j];
}
}
/*Button* restart = new Button{ 100, 300, 100, 25, L"重置" };*/
/*ExMessage msg;*/
while (1)
{
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(500, 570, L"已走步数:");
outtextxy(100, 570, L"重置Z");
outtextxy(200, 570, L"主菜单X");
int q = 0;
int temp = _count;
while (temp != 0)
{
c[q] = mapping[temp % 10];
temp /= 10;
q++;
}
if (q != 0)
{
for (int j = 0; j < q; j++)
{
result[j] = c[q - j - 1];
}
}
outtextxy(570, 570, result);
if (gameOver())//如果游戏结束
{
cas++; //变换关卡
_count = 0;
for (int i = 0; i < 10; i++)
result[i] = 0;
result[0] = { L'0' };
for (int i = 0; i < 10; i++)
c[i] = 0;
if (cas != 4)
{
Sleep(500);
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(500, 570, L"已走步数:");
outtextxy(570, 570, result);
outtextxy(100, 570, L"重置Z");
outtextxy(200, 570, L"主菜单X");
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
temp_map[i][j] = map[cas][i][j];
}
}
}
else if (cas == 4)
{
cas = 0;
break;
}
}
FlushBatchDraw(); // 将缓冲区内容显示在屏幕上
Sleep(10);
keyDown();//循环按下按键
//system("cls");
}
/*delete restart;*/
}
void play_normal()
{
const wchar_t* mapping = L"0123456789";
_count = 0;
std::srand(static_cast<unsigned int>(std::time(0)));
MyMap _map{};
DUISHU = 4;
for (int i = 0; i < 4; i++)
{
while (!_map.generatemap(30))
{
if (_map.generatemap(30))
{
break;
}
}
for (int j = 0; j < ROW; j++)
{
for (int k = 0; k < COL; k++)
{
map[i][j][k] = _map.Map[j][k];
}
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
temp_map[i][j] = map[cas][i][j];
}
}
while (1)
{
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(500, 570, L"已走步数:");
outtextxy(100, 570, L"重置Z");
outtextxy(200, 570, L"主菜单X");
int q = 0;
int temp = _count;
while (temp != 0)
{
c[q] = mapping[temp % 10];
temp /= 10;
q++;
}
if (q != 0)
{
for (int j = 0; j < q; j++)
{
result[j] = c[q - j - 1];
}
}
outtextxy(570, 570, result);
if (gameOver())//如果游戏结束
{
cas++; //变换关卡
_count = 0;
for (int i = 0; i < 10; i++)
result[i] = 0;
result[0] = { L'0' };
for (int i = 0; i < 10; i++)
c[i] = 0;
if (cas != 4)
{
Sleep(500);
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(500, 570, L"已走步数:");
outtextxy(570, 570, result);
outtextxy(100, 570, L"重置Z");
outtextxy(200, 570, L"主菜单X");
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
temp_map[i][j] = map[cas][i][j];
}
}
}
else if (cas == 4)
{
cas = 0;
break;
}
}
FlushBatchDraw(); // 将缓冲区内容显示在屏幕上
Sleep(10);
keyDown();//循环按下按键
//system("cls");
}
}
void play_hard()
{
const wchar_t* mapping = L"0123456789";
_count = 0;
std::srand(static_cast<unsigned int>(std::time(0)));
MyMap _map{};
DUISHU = 6;
for (int i = 0; i < 4; i++)
{
while (!_map.generatemap(8))
{
if (_map.generatemap(8))
{
break;
}
}
for (int j = 0; j < ROW; j++)
{
for (int k = 0; k < COL; k++)
{
map[i][j][k] = _map.Map[j][k];
}
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
temp_map[i][j] = map[cas][i][j];
}
}
while (1)
{
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(500, 570, L"已走步数:");
outtextxy(100, 570, L"重置Z");
outtextxy(200, 570, L"主菜单X");
int q = 0;
int temp = _count;
while (temp != 0)
{
c[q] = mapping[temp % 10];
temp /= 10;
q++;
}
if (q != 0)
{
for (int j = 0; j < q; j++)
{
result[j] = c[q - j - 1];
}
}
outtextxy(570, 570, result);
if (gameOver())//如果游戏结束
{
cas++; //变换关卡
_count = 0;
for (int i = 0; i < 10; i++)
result[i] = 0;
result[0] = { L'0' };
for (int i = 0; i < 10; i++)
c[i] = 0;
if (cas != 4)
{
Sleep(500);
drawGraph();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(500, 570, L"已走步数:");
outtextxy(570, 570, result);
outtextxy(100, 570, L"重置Z");
outtextxy(200, 570, L"主菜单X");
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
temp_map[i][j] = map[cas][i][j];
}
}
}
else if (cas == 4)
{
cas = 0;
break;
}
}
FlushBatchDraw(); // 将缓冲区内容显示在屏幕上
Sleep(10);
keyDown();//循环按下按键
//system("cls");
}
}
int main()
{
loadResource();//定义加载资源函数
//mciSendString(L"open 1.mp3", 0, 0, 0);//加载音乐
//mciSendString(L"play 1.mp3 repeat", 0, 0, 0);//循环播放音乐资源
initgraph(50 * ROW, 50 * COL);
Button* start = new Button{ 150, 400, 100, 25, L"开始" };
Button* easy = new Button{ 100, 300, 100, 25, L"简单" };
Button* normal = new Button{ 250, 300, 100, 25, L"中等" };
Button* hard = new Button{ 400, 300, 100, 25, L"困难" };
Button* exit = new Button{ 350, 400, 100, 25, L"退出" };
while (1)
{
if (start->get_has_been_clicked())
start->has_been_clicked_convert();
if (easy->get_has_been_clicked())
easy->has_been_clicked_convert();
if (normal->get_has_been_clicked())
normal->has_been_clicked_convert();
if (hard->get_has_been_clicked())
hard->has_been_clicked_convert();
if (exit->get_has_been_clicked())
exit->has_been_clicked_convert();
drawGraph1();
setbkmode(TRANSPARENT);
settextcolor(BLACK);
settextstyle(50, 0, _T("微软雅黑"));
outtextxy(250, 150, L"推箱子");
ExMessage msg;
while (true)
{
if (peekmessage(&msg)) // 检查是否有消息
{
int mouseX = msg.x; // 获取鼠标x坐标
int mouseY = msg.y; // 获取鼠标y坐标
if (msg.message == WM_LBUTTONDOWN)
{
if (start->checkClick(mouseX, mouseY))
{
if (easy->get_has_been_clicked())
{
play_easy();
break;
}
else if (normal->get_has_been_clicked())
{
play_normal();
break;
}
else if(hard->get_has_been_clicked())
{
play_hard();
break;
}
else
{
}
}
else if (easy->checkClick(mouseX, mouseY))
{
if (normal->get_has_been_clicked())
normal->has_been_clicked_convert();
if (hard->get_has_been_clicked())
hard->has_been_clicked_convert();
}
else if (normal->checkClick(mouseX, mouseY))
{
if (easy->get_has_been_clicked())
easy->has_been_clicked_convert();
if (hard->get_has_been_clicked())
hard->has_been_clicked_convert();
}
else if (hard->checkClick(mouseX, mouseY))
{
if (normal->get_has_been_clicked())
normal->has_been_clicked_convert();
if (easy->get_has_been_clicked())
easy->has_been_clicked_convert();
}
else if (exit->checkClick(mouseX, mouseY))
{
return 0;
}
}
else if (msg.message == WM_MOUSEMOVE)
{
start->checkMouseOver(mouseX, mouseY);
easy->checkMouseOver(mouseX, mouseY);
normal->checkMouseOver(mouseX, mouseY);
hard->checkMouseOver(mouseX, mouseY);
exit->checkMouseOver(mouseX, mouseY);
}
}
start->draw(); // 绘制当前页面内容
easy->draw();
normal->draw();
hard->draw();
exit->draw();
FlushBatchDraw(); // 将缓冲区内容显示在屏幕上
Sleep(10);
}
}
delete start;
delete easy;
delete normal;
delete hard;
delete exit;
delete bacground;
closegraph();//关闭窗口
return 0;
}
Loading…
Cancel
Save