C++程序

// migong.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
///

#include <graphics.h>
#include <conio.h>
#include <time.h>

 

//
// 定义全局变量
//
BYTE** g_imgMap = NULL;   // 迷宫地图
SIZE g_szMap;     // 迷宫地图的尺寸
IMAGE g_imgSight(360, 280);  // 游戏的视野
RECT g_rtSight;     // 游戏的视野的范围
IMAGE g_imgItem(180, 20);   // 地图元素
IMAGE g_imgGPS;     // 迷你地图,用于显示游戏者在地图中的位置
POINT g_ptGPS;     // 迷你地图的显示位置
SIZE g_szGPS;     // 迷你地图的尺寸
POINT g_ptPlayer;     // 游戏者的位置

// 枚举地图元素,兼做元素位置的 x 坐标
enum MAPITEM { MAP_WALL = 0, MAP_PLAYER = 20, MAP_GROUND = 40, MAP_MARKRED = 60, MAP_MARKGREEN = 80, MAP_MARKYELLOW = 100, MAP_ENTRANCE = 120, MAP_EXIT = 140, MAP_OUTSIDE = 160 };
// 枚举用户的控制命令
enum CMD { CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_MARKRED = 32, CMD_MARKGREEN = 64, CMD_MARKYELLOW = 128, CMD_CLEARMARK = 256 };

 

//
// 函数声明
//
void Welcome();       // 绘制游戏界面
void InitImage();      // 初始化游戏图片
void InitGame();       // 初始化游戏数据
void GetMazeSize();      // 提示用户输入迷宫大小
void MakeMaze(int width, int height); // 生成迷宫:初始化(注:宽高必须是奇数)
void TravelMaze(int x, int y);   // 生成迷宫:遍历 (x, y) 四周
MAPITEM GetMazeItem(int x, int y);   // 获取指定坐标的迷宫元素
void Paint();       // 绘制视野范围内的迷宫
int  GetCmd(int* c);      // 获取用户输入的命令
void DispatchCmd(int cmd);    // 处理用户输入的命令
void OnUp();        // 向上移动
void OnLeft();       // 向左移动
void OnRight();       // 向右移动
void OnDown();       // 向下移动
void OnMark(MAPITEM value);    // 在地图中做标记
bool CheckWin();       // 检查是否到出口
bool Quit();        // 询问用户是否退出游戏

 

//
// 函数定义
//


// 主程序
void main()
{
 // 初始化
 initgraph(640, 480);   // 创建绘图窗口
 srand((unsigned)time(NULL)); // 设置随机种子

 // 显示主界面
 Welcome();

 // 初始化
 InitImage();
 InitGame();

 // 游戏过程
 int c;
 while( !((GetCmd(&c) == CMD_QUIT) && Quit()) )
 {
  DispatchCmd(c);
  Paint();
  if (CheckWin())
   break;

  // 延时
  Sleep(100);
 }

 // 清理迷宫地图占用的内存
 for(int x = 0; x < g_szMap.cx + 2; x++)
  delete[] g_imgMap[x];
 delete [] g_imgMap;

 // 关闭图形模式
 closegraph();
}


// 绘制游戏界面
void Welcome()
{
 // 绘制渐变色外框
 for(int i=0; i<128; i++)
 {
  setcolor(RGB(0, 0, (127 - i) << 1));
  rectangle(149 - i, 109 - (i >> 1), 490 + i, 370 + (i >> 1));
 }

 // 设置字体样式
 setcolor(WHITE);
 setbkmode(TRANSPARENT);

 // 绘制标题
 setfont(36, 0, _T("宋体"));
 outtextxy(248, 40, _T("迷  宫"));

 // 绘制操作说明
 setfont(12, 0, _T("宋体"));
 outtextxy(50, 382, _T("控制说明:"));
 outtextxy(74, 400, _T("方向键或 A/S/D/W:移动"));;
 outtextxy(74, 454, _T("ESC:退出程序"));
}


// 初始化游戏图片
void InitImage()
{
 // 预绘制游戏图片到 IMAGE 缓存(可以修改为加载图片以获得更好效果)
 SetWorkingImage(&g_imgItem);
 cleardevice();
 // 绘制 PLAYER
 setorigin(MAP_PLAYER, 1);
 setfillstyle(RED);
 setcolor(YELLOW);
 fillellipse(2, 2, 17, 17);
 setcolor(RED);
 line(7, 7, 7, 8);
 line(12, 7, 12, 8);
 bar(5, 6, 14, 14);
 // 绘制墙壁
 setorigin(MAP_WALL, 0);
 setfillstyle(GREEN, PATTERN_FILL, "\x20\x20\x20\xff\x04\x04\x04\xff");
 setcolor(BROWN);
 bar(1, 1, 18, 18);
 rectangle(1, 1, 19, 19);

 // 绘制入口
 setorigin(MAP_ENTRANCE, 0);
 setcolor(GREEN);
 setfont(12, 0, _T("宋体"));
 outtextxy(4, 4, _T("入"));
 // 绘制出口
 setorigin(MAP_EXIT, 0);
 outtextxy(4, 4, _T("出"));
 // 绘制迷宫外面的空地
 setorigin(MAP_OUTSIDE, 0);
 setfillstyle(YELLOW, PATTERN_FILL, "\x50\x55\x22\x20\x05\x55\x22\x02");
 bar(0, 0, 20, 20);
 // 恢复坐标系
 setorigin(0, 0);

 // 显示作者
 SetWorkingImage();
 setcolor(BLUE);
 TCHAR author[] = _T("李志豪");
 outtextxy(471, 4, author);
 setcolor(LIGHTBLUE);
 outtextxy(470, 3, author);
}


// 初始化游戏数据
void InitGame()
{
 // 提示用户输入迷宫大小
 GetMazeSize();

 // 初始化参数
 if (g_imgMap != NULL)
 { // 清理迷宫地图占用的内存
  for(int x = 0; x < g_szMap.cx + 2; x++)
   delete[] g_imgMap[x];
  delete [] g_imgMap;
 }
 MakeMaze(g_szMap.cx, g_szMap.cy);  // 创建迷宫
 g_ptPlayer.x = 2;     // 设置游戏者的位置
 g_ptPlayer.y = 2;
 g_rtSight.left = 0;     // 设置视野范围
 g_rtSight.top = 0;
 g_rtSight.right = 17;
 g_rtSight.bottom= 13;

 // 画迷你地图外框
 setcolor(RED);
 rectangle(g_ptGPS.x - 1, g_ptGPS.y - 1, g_ptGPS.x + g_szGPS.cx, g_ptGPS.y + g_szGPS.cy);
 // 画迷你地图入口和出口
 setcolor(YELLOW);
 moveto(g_ptGPS.x - 8, g_ptGPS.y + g_szGPS.cy / g_szMap.cy);
 linerel(7, 0); linerel(-3, -3); moverel(3, 3); linerel(-3, 3);
 moveto(g_ptGPS.x + g_szGPS.cx, g_ptGPS.y + g_szGPS.cy - g_szGPS.cy / g_szMap.cy);
 linerel(7, 0); linerel(-3, -3); moverel(3, 3); linerel(-3, 3);

 // 绘制游戏区
 Paint();
}


// 提示用户输入迷宫大小
void GetMazeSize()
{
 g_szMap.cx = g_szMap.cy = 0;

 // 获取用户输入的宽高
 TCHAR s[4];
 while(g_szMap.cx < 20 || g_szMap.cx > 200)
 {
  InputBox(s, 4, _T("请输入迷宫的宽度\n范围:20~200"), _T("输入"), _T("25"));
  g_szMap.cx = _ttoi(s);
 }
 while(g_szMap.cy < 20 || g_szMap.cx > 200)
 {
  InputBox(s, 4, _T("请输入迷宫的高度\n范围:20~200"), _T("输入"), _T("25"));
  g_szMap.cy = _ttoi(s);
 }

 // 确保宽高为奇数
 if (g_szMap.cx % 2 != 1) g_szMap.cx++;
 if (g_szMap.cy % 2 != 1) g_szMap.cy++;
}


// 生成迷宫:初始化(注:宽高必须是奇数)
void MakeMaze(int width, int height)
{
 if (width % 2 != 1 || height % 2 != 1)
  return;

 int x, y;

 // 定义迷宫尺寸,并分配迷宫内存
 g_imgMap = new BYTE*[width + 2];
 for(x = 0; x < width + 2; x++)
 {
  g_imgMap[x] = new BYTE[height + 2];
  memset(g_imgMap[x], MAP_WALL, height + 2);
 }

 // 定义边界
 for (x = 0; x <= width + 1; x++)
  g_imgMap[x][0] = g_imgMap[x][height + 1] = MAP_GROUND;
 
 for (y = 1; y <= height; y++)
  g_imgMap[0][y] = g_imgMap[width + 1][y] = MAP_GROUND;
  
 // 定义入口和出口
 g_imgMap[1][2] = MAP_ENTRANCE;
 g_imgMap[width][height - 1] = MAP_EXIT;

 // 从任意点开始遍历生成迷宫
 TravelMaze(((rand() % (width - 1)) & 0xfffe) + 2, ((rand() % (height - 1)) & 0xfffe) + 2);

 // 将边界标记为迷宫外
 for (x = 0; x <= width + 1; x++)
  g_imgMap[x][0] = g_imgMap[x][height + 1] = MAP_OUTSIDE;
 
 for (y = 1; y <= height; y++)
  g_imgMap[0][y] = g_imgMap[width + 1][y] = MAP_OUTSIDE;
}


// 生成迷宫:遍历 (x, y) 四周
void TravelMaze(int x, int y)
{
 // 定义遍历方向
 int d[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
 
 // 将遍历方向乱序
 int n, t, i;
 for(i = 0; i < 4; i++)
 {
  n = rand() % 4;
  t = d[i][0], d[i][0] = d[n][0], d[n][0] = t;
  t = d[i][1], d[i][1] = d[n][1], d[n][1] = t;
 }
 
 // 尝试周围四个方向
 g_imgMap[x][y] = MAP_GROUND;
 for(i = 0; i < 4; i++)
  if (g_imgMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == 0)
  {
   g_imgMap[x + d[i][0]][y + d[i][1]] = MAP_GROUND;
   TravelMaze(x + d[i][0] * 2, y + d[i][1] * 2);  // 递归
  }
}


// 获取指定坐标的迷宫元素
MAPITEM GetMazeItem(int x, int y)
{
 return (MAPITEM)g_imgMap[x][y];
}


// 绘制视野范围内的迷宫
void Paint()
{
 int x1, y1;

 // 绘制视野内的迷宫
 SetWorkingImage(&g_imgSight);
 for(int x = g_rtSight.left; x <= g_rtSight.right; x++)
  for(int y = g_rtSight.top; y <= g_rtSight.bottom; y++)
  {
   x1 = (x - g_rtSight.left) * 20;
   y1 = (y - g_rtSight.top) * 20;
   putimage(x1, y1, 20, 20, &g_imgItem, GetMazeItem(x, y), 0);
  }

 // 绘制游戏者
 x1 = (g_ptPlayer.x - g_rtSight.left) * 20;
 y1 = (g_ptPlayer.y - g_rtSight.top) * 20;
 putimage(x1, y1, 20, 20, &g_imgItem, MAP_PLAYER, 0);

 

 // 更新到绘图窗口
 SetWorkingImage();
 putimage(150, 110, 340, 260, &g_imgSight, 10, 10);
 putimage(g_ptGPS.x, g_ptGPS.y, &g_imgGPS);
}


// 获取用户输入的命令
int GetCmd(int *c)
{
 *c = 0;

 if (GetAsyncKeyState(VK_LEFT) & 0x8000)  *c |= CMD_LEFT;
 if (GetAsyncKeyState(VK_RIGHT) & 0x8000)  *c |= CMD_RIGHT;
 if (GetAsyncKeyState(VK_UP)  & 0x8000)  *c |= CMD_UP;
 if (GetAsyncKeyState(VK_DOWN) & 0x8000)  *c |= CMD_DOWN;
 if (GetAsyncKeyState('A')  & 0x8000)  *c |= CMD_LEFT;
 if (GetAsyncKeyState('D')  & 0x8000)  *c |= CMD_RIGHT;
 if (GetAsyncKeyState('W')  & 0x8000)  *c |= CMD_UP;
 if (GetAsyncKeyState('S')  & 0x8000)  *c |= CMD_DOWN;
 if (GetAsyncKeyState(' ')  & 0x8000)  *c |= CMD_MARKRED;
 if (GetAsyncKeyState('G')  & 0x8000)  *c |= CMD_MARKGREEN;
 if (GetAsyncKeyState('Y')  & 0x8000)  *c |= CMD_MARKYELLOW;
 if (GetAsyncKeyState('C')  & 0x8000)  *c |= CMD_CLEARMARK;
 if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)  *c |= CMD_QUIT;

 return *c;
}


// 处理用户输入的命令
void DispatchCmd(int cmd)
{
 if (cmd & CMD_UP)   OnUp();
 if (cmd & CMD_DOWN)   OnDown();
 if (cmd & CMD_LEFT)   OnLeft();
 if (cmd & CMD_RIGHT)  OnRight();
 if (cmd & CMD_MARKRED)  OnMark(MAP_MARKRED);
 if (cmd & CMD_MARKGREEN) OnMark(MAP_MARKGREEN);
 if (cmd & CMD_MARKYELLOW) OnMark(MAP_MARKYELLOW);
 if (cmd & CMD_CLEARMARK) OnMark(MAP_GROUND);
}


// 向上移动
void OnUp()
{
 if (g_ptPlayer.y > 1 && GetMazeItem(g_ptPlayer.x, g_ptPlayer.y - 1) != MAP_WALL)
 {
  g_ptPlayer.y--;

  if (g_ptPlayer.y - g_rtSight.top < 4 && g_rtSight.top > 0)
  {
   g_rtSight.top--;
   g_rtSight.bottom--;
  }
 }
}


// 向左移动
void OnLeft()
{
 if (g_ptPlayer.x > 1 && GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_WALL && GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_ENTRANCE)
 {
  g_ptPlayer.x--;

  if (g_ptPlayer.x - g_rtSight.left < 5 && g_rtSight.left > 0)
  {
   g_rtSight.left--;
   g_rtSight.right--;
  }
 }
}


// 向右移动
void OnRight()
{
 if (g_ptPlayer.x < g_szMap.cx && GetMazeItem(g_ptPlayer.x + 1, g_ptPlayer.y) != MAP_WALL)
 {
  g_ptPlayer.x++;

  if (g_rtSight.right - g_ptPlayer.x < 5 && g_rtSight.right <= g_szMap.cx)
  {
   g_rtSight.left++;
   g_rtSight.right++;
  }
 }
}


// 向下移动
void OnDown()
{
 if (g_ptPlayer.y < g_szMap.cy && GetMazeItem(g_ptPlayer.x, g_ptPlayer.y + 1) != MAP_WALL)
 {
  g_ptPlayer.y++;

  if (g_rtSight.bottom - g_ptPlayer.y < 4 && g_rtSight.bottom <= g_szMap.cy)
  {
   g_rtSight.top++;
   g_rtSight.bottom++;
  }
 }
}


// 在地图中做标记
void OnMark(MAPITEM value)
{
 g_imgMap[g_ptPlayer.x][g_ptPlayer.y] = value;
}


// 检查是否到出口
bool CheckWin()
{
 if (g_ptPlayer.x == g_szMap.cx && g_ptPlayer.y == g_szMap.cy - 1)
 {
  HWND hwnd = GetHWnd();
  if (MessageBox(hwnd, _T("恭喜你走出来了!\n您想再来一局吗?"), _T("恭喜"), MB_YESNO | MB_ICONQUESTION) == IDYES)
  {
   InitGame();
   return false;
  }
  else
   return true;
 }

 return false;
}


// 询问用户是否退出游戏
bool Quit()
{
 HWND hwnd = GetHWnd();
 return (MessageBox(hwnd, _T("您确定要退出游戏吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值