C++实现控制台迷宫小游戏

前言

这个程序是我一年前写的,那是还不是很成熟,导致C、C++混在一起,警告一大堆。。
不过这个程序是我第一部 成功做成的游戏。
虽然关卡只做了3关,但是这个游戏代码框架值得参考。
(关卡可以自己再加,就在那个数组那里)

我大部分的程序都包含了我自己做的头文件,因此弄这儿来的时候必须替换一大堆东西,可能有些BUG。敬请谅解。

原来还是有音乐的,因为没有资源的问题,把它去了,如果真想要可以到这里下载,这里的源文件是真正的源文件,没有替换过的,当然无法通过编译,仅供参考。。。
> 点此下载控制台版 <
我这个寒假前半部分又做了一个ege版,可以加载图片与音乐,效果好多了(不要问为什么都是从别的游戏里取来的资源,因为我没别的地方好取…)。做了12关,可以玩玩看,地址:
> 点此下载EGE版 <
音乐音量我还不能调整,气煞人也。

这个文件是有点大,要是竞赛早被踢了。。不过还是看看吧。
控制台是按键操作,EGE版是鼠标按键兼用。
我不是很在行,请忽略一些UI的外观问题及小bugs.
控制台版预览
控制台版↑

EGE版预览
EGE版↑
(我没有任何商业用途,没有侵权)

控制台版源码

Walker_Origin.cpp (修改后的控制台程序,可以通过编译)↓

/*
 %%% COPY RIGH/LEF T <C> 2020 %%%
     Name: Walker.cpp
     Author: cjz2005
   Description: A game
 %%% ALL RIGHTS RESERVED %%%
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <Windows.h>
#define _up 'w'
#define _down 's'
#define _left 'a'
#define _right 'd'
#define SINT short int
#define USINT unsigned short int
#define HIDH printf("\033[?25l")//隐藏光标;
#define banben "1.0" 
using namespace std;
int RandInt(int min,int max)
{
 srand(time(NULL));
 return (rand()%(max-min+1))+max;
}
VOID Cls(VOID) { //Clear the screen
 system("cls");
 return;
}
void HideCursor()
{
    CONSOLE_CURSOR_INFO cursor_info = {10, 0}; 
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
VOID SetColor(UINT uFore,UINT uBack) {
 HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
 SetConsoleTextAttribute(handle,uFore+uBack*0x10);
 //CloseHandle(handle); 
}
VOID SetPosC(COORD a) { // set cursor
 HANDLE out=GetStdHandle(STD_OUTPUT_HANDLE);
 SetConsoleCursorPosition(out, a);
}
VOID SetPos(short x, short y) { // set cursor2
 COORD pos= {x, y};
 SetPosC(pos);
}
VOID DrawCol1(int x, int y1, int y2, char ch) {
 int y=y1;
 while(y!=y2+1) {
  SetPos(x, y);
  putchar(ch);
  y++;
 }
}
VOID DrawCol1D(int x, int y1, int y2, char ch,DWORD dwMilliSeconds) {
 int y=y1;
 while(y!=y2+1) {
  SetPos(x, y);
  putchar(ch);
  y++;
  Sleep(dwMilliSeconds);
 }
}
VOID DrawRow1(int y, int x1, int x2, char ch) {
 SetPos(x1,y);
 for(int i = 0; i <= (x2-x1); i++)
  putchar(ch);
}
VOID DrawRow1D(int y, int x1, int x2, char ch,DWORD dwMilliSeconds) {
 SetPos(x1,y);
 for(int i = 0; i <= (x2-x1); i++) {
  putchar(ch);
  Sleep(dwMilliSeconds);
 }
}
VOID DrawRow(COORD a, COORD b, char ch) {
 if(a.Y == b.Y)
  DrawRow1(a.Y, a.X, b.X, ch);
 else {
  abort();
 }
}
VOID DrawRowD(COORD a, COORD b, char ch,DWORD dwMilliSeconds) {
 if(a.Y == b.Y)
  DrawRow1D(a.Y, a.X, b.X, ch,dwMilliSeconds);
 else {
  abort();
 }
}
COORD p={0,0};
const USINT level_w=8;
const USINT level_h=8;
bool coll[level_w][level_h];
COORD c1={0,0},c2={99,0};
USINT data[30][level_w][level_h]=
{ //这里是地图数据,可以进行添加和修改。
{
 {1,1,1,1,1,1,1,1
 },
 {1,6,2,0,0,0,1,2
 },
 {1,0,0,0,2,0,1,1
 },
 {1,3,1,1,1,0,1,2
 },
 {3,0,0,0,0,0,3,1
 },
 {4,0,1,2,1,2,4,1
 },
 {4,0,0,0,0,0,0,7
 },
 {1,3,2,4,2,1,3,3
 }},
 {
 {1,3,1,2,1,1,1,0
 },
 {1,6,3,0,0,0,1,0
 },
 {1,0,0,0,2,0,1,0
 },
 {1,0,2,1,1,0,1,0
 },
 {1,0,0,5,0,0,3,0
 },
 {3,2,1,2,1,0,4,0
 },
 {4,7,0,0,0,0,0,4
 },
 {1,4,3,2,2,1,1,3
 }},
 {
 {1,1,1,1,1,1,1,1
 },
 {1,6,2,0,0,0,0,2
 },
 {1,0,0,0,2,5,0,1
 },
 {1,3,5,1,1,0,0,2
 },
 {3,0,5,0,0,0,4,1
 },
 {3,0,1,0,1,2,3,1
 },
 {4,5,0,0,0,0,0,7
 },
 {4,3,2,4,2,1,3,3
 }
  } 
 }; 
//HANDLE mfun;
//HANDLE mfunc;//崩溃 
USINT nlevel;
USINT elevel2; 
HWND hwnd=FindWindow("ConsoleWindowClass",NULL);
bool isgo=true;
bool IsBarrier(SINT blockId=-1)
{
 bool r=0;
 switch(blockId)
 {
  case -1:r=0;break;
  case 0:case 5:case 6:case 7:
   r=0;break;
  default:
   r=1;break;
 }
 return r;
}
void PrintLevel(USINT uLevel)
{
 SetPos(4,5);
 for(int i=0;i<30;i++)
 {
  if(i<uLevel)
  {
  SetColor(10,0);
  cout<<" "<<i+1;
  }
  else
  {
  SetColor(8,0);
  cout<<" ▓";
  }
 }
 return;
}
 /*
0 = 黑色 8 = 灰色
1 = 蓝色 9 = 淡蓝色
2 = 绿色 10 = 淡绿色
3 = 浅绿色 11 = 淡浅绿色 
4 = 红色 12 = 淡红色
5 = 紫色 13 = 淡紫色
6 = 黄色 14 = 淡黄色
7 = 白色 15 = 亮白色
*/
void DrawBlock(int bid)
{
 USINT f=7,b=0;
 bool isch=true;
 char *ch;
 switch(bid)
 {
  case 0:isch=false;ch=(LPSTR)"  ";break;
  case 1:f=7;b=0;ch=(LPSTR)"□";break;
  case 2:f=6;b=0;ch=(LPSTR)"■";break;
  case 3:f=8;b=0;ch=(LPSTR)"■";break; 
  case 4:f=4;b=0;ch=(LPSTR)"▓";break; 
  case 5:f=12;b=0;ch=(LPSTR)"◎";break;//mine 
  case 6:f=2;b=10;ch=(LPSTR)"◆";break;//start
  case 7:f=4;b=12;ch=(LPSTR)"◆";break;//end 
  default:isch=false;ch=(LPSTR)"  ";break;
  } 
  SetColor(f,b);
  cout<<ch;
  return;
}
void PlayLevel(USINT elevel)
{
 char chp;
 char menui;
 string reason;
 //COORD end={0,0};
 const COORD start[30]=      //起点 
 {
  {1,1},{1,1},{1,1}
 };
 bool iswin=false;
 bool ismenu=false;
 //memset(data1,2,sizeof(data1));
 //data1=data[elevel];
 /*switch(elevel)
 {
  case 1:case 2:p.X=1;p.Y=1;break;
  default:p.X=1;p.Y=1;break;
 }*/
 p.X=start[elevel-1].X;p.Y=start[elevel-1].Y;
 while(1)
 {
 Cls();
 ismenu=false;
 for(int i=0;i<level_w;i++)
 {
 for(int j=0;j<level_h;j++)
 {
 if(p.X!=j||p.Y!=i)
 {
 DrawBlock(data[elevel-1][i][j]);   //画图 
 }
 else
 {
 SetColor(15,0);
 cout<<"♀";
 }
 }
 cout<<"\n";
 }
 if(data[elevel-1][p.Y][p.X]==7)     //终点 
 {
  iswin=true;
  break;
 }else if(data[elevel-1][p.Y][p.X]==5) //地雷 
 {
  iswin=false;
  reason="被地雷炸死了";
  SetPos(p.X+3,p.Y);
  SetColor(14,4);
  cout<<"炸";
  Sleep(100);
  SetColor(12,0);
  break;
 }
 SetColor(13,0); 
 DrawCol1(70,0,33,'|');
 SetPos(72,1);
 SetColor(15,0);
 cout<<"第"<<elevel<<"关";
 SetPos(72,0);
 SetColor(7,0);
 cout<<"In block's ID:"<<data[elevel-1][p.Y][p.X];
 chp = getch();
 switch(chp)//操作 
 {
  case 97:if(!IsBarrier(data[elevel-1][p.Y][p.X-1]))p.X-=1;break;//A
  case 115:if(!IsBarrier(data[elevel-1][p.Y+1][p.X])) p.Y+=1;break;//S
  case 100:if(!IsBarrier(data[elevel-1][p.Y][p.X+1])) p.X+=1;break;//D
  case 119: if(!IsBarrier(data[elevel-1][p.Y-1][p.X]))p.Y-=1;break;//W
  case 27:ismenu=true;break;//Esc菜单 
  default:break; 
 }
 if(ismenu)
 {
  Cls();
  SetPos(44,3);
  SetColor(11,0);
  cout<<"主 菜 单";
  SetPos(45,5);
  SetColor(14,0);
  cout<<"Q:退出";
  SetPos(45,7);
  cout<<"R:重来";
  SetPos(41,9);
  SetColor(10,0);
  cout<<"[Esc:返回游戏]";
  menu://菜单 
  menui=getch();
  if(menui==113||menui==81)
  {
   SetPos(30,13);
   SetColor(11,0);
   cout<<"* 退出会放弃本关的操作,是否继续?[回车:是/其它:否]  ";
   if(getch()==13)
   {
    Cls();
    isgo=false;
    elevel2=1;
    return;
   }else
   {
    SetPos(42,13);
    cout<<"                                                                        ";
    goto menu;
   }
  }else if(menui==114||menui==82)
  {
   SetPos(42,13);
   SetColor(12,0);
   cout<<"% 重来……";
   Sleep(100);
   isgo=true;
   elevel2=elevel;
   return;
  }else if(menui==27)
  {
   ismenu=false;
  }else 
  goto menu;
 }
 }//while
 if(iswin)  //成功 
 {
  FILE *fp;
  Sleep(150);
  Cls();
  SetColor(10,0);
  if(elevel==nlevel)
     DrawRowD(c1,c2,'@',20);
     else
     DrawRow(c1,c2,'@');
  SetPos(42,2);
  SetColor(10,0);
  cout<<" 恭 ";
  Sleep(200);
  cout<<"喜!";
  SetPos(39,3);
  SetColor(7,0);
  cout<<"第"<<elevel<<"关闯关成功!";
  SetPos(0,33);
  SetColor(10,0);//light green
  if(elevel==nlevel)
  {
  DrawRow1D(40,0,99,'@',20);
  SetPos(0,0);
  DrawCol1D(0,0,33,'@',77);
  SetPos(99,0);
  DrawCol1D(99,0,33,'@',77);
  }
  else
  {
  DrawRow1(40,0,99,'@');
  SetPos(0,0);
  DrawCol1(0,0,33,'@');
  SetPos(99,0);
  DrawCol1(99,0,33,'@');
  }
  fp = fopen("save.wld","wb");
  fprintf(fp,"%d",nlevel+1);
  fclose(fp);
  SetPos(42,10);
  SetColor(8,0);
  cout<<"回车:下一关";
  SetPos(42,11);
  cout<<"r:再闯一次";
  SetPos(42,12);
  cout<<"Esc:回到关卡页面";
  Sleep(100);
  SetPos(42,10);
  SetColor(6,0);
  cout<<"回车:下一关";
  SetPos(42,11);
  cout<<"r:再闯一次";
  SetPos(42,12);
  cout<<"Esc:回到关卡页面";  //渐变动画 
  Sleep(200);
  SetPos(42,10);
  SetColor(14,0);
  cout<<"回车:下一关";
  SetPos(42,11);
  cout<<"r:再闯一次";
  SetPos(42,12);
  cout<<"Esc:回到关卡页面"; 
  ichp:
  chp=getch();
  if(chp==13)//enter
  {
   isgo=true;
   elevel2=elevel+1;
   if(elevel==nlevel)
   ++nlevel;
   //PlayLevel(++nlevel);
  }else if(chp==114)//r
  {
   isgo=true;
   elevel2=elevel;
   if(elevel==nlevel)
   ++nlevel;
   //PlayLevel(nlevel++);
  }else if(chp==27)//esc
  {
   isgo=false;
   elevel2=1;
   if(elevel==nlevel)
   ++nlevel;
   return;
  }else 
  goto ichp;
 }//success
 else//失败
 {
  Sleep(200);
  Cls();
  SetColor(12,0);//dark red
  if(elevel==nlevel)
  {
  DrawRowD(c1,c2,'%',10);
  SetPos(0,33);
  DrawRow1D(40,0,99,'%',10);
  SetPos(0,0);
  DrawCol1D(0,0,33,'%',30);
  SetPos(99,0);
  DrawCol1D(99,0,33,'%',30);
  }else
  {
  DrawRow(c1,c2,'%');
  SetPos(0,33);
  DrawRow1(40,0,99,'%');
  SetPos(0,0);
  DrawCol1(0,0,33,'%');
  SetPos(99,0);
  DrawCol1(99,0,33,'%'); 
  }
  SetPos(41,2);
  SetColor(13,0);
  cout<<"失  ";
  Sleep(100);
  cout<<"败!";
  SetPos(41,3);
  SetColor(8,0);
  cout<<"原因: "<<reason;
  SetPos(42,6);
  SetColor(8,0);
  cout<<"R:重来";
  SetPos(42,8);
  cout<<"Esc:回到关卡页面";
  Sleep(100);
  SetPos(42,6);
  SetColor(6,0);
  cout<<"R:重来";
  SetPos(42,8);
  cout<<"Esc:回到关卡页面"; //渐变动画 
  Sleep(200);
  SetPos(42,6);
  SetColor(14,0);
  cout<<"R:重来";
  SetPos(42,8);
  cout<<"Esc:回到关卡页面";
  ichpf:
  fflush(stdout);
  chp=getch();
  CloseHandle(mfun);
  if(chp==114)//R
  {
   isgo=true;
   elevel2=elevel;
  }else if(chp==27)//esc
  {
   isgo=false;
   elevel2=1;
   return;
  }else 
  goto ichpf;
 } //fail 
 return;
}
int main()
{
 int isnl;
 int elevel;
 USINT rlevel=2;
 char *cmd;
 char r1,r2,r3;
 char title[16];
 char titi;
 FILE *fp;
 string sfilename;
 srand((int)time(0));    //随机种子
 /*char path[MAX_PATH];
 string paths;
    getcwd(path,sizeof(path));
    paths=path;
    sfilename = paths.substr(0,paths.length()-6); */
    tit:     //标题画面 
    HideCursor();   //隐藏光标
    //HIDH;
    sprintf(title,"title Walker v%s",banben);
    system(title); 
    system("mode con cols=100 lines=40");//窗口宽度高度
    SetColor(10,0);
    DrawRow(c1,c2,'*');
    SetPos(45,1);
    SetColor(11,0);
    cout<<"W A L K E R";
    SetPos(44,17);
    SetColor(14,0);
    cout<<"回车: 开始游戏";
    SetPos(44,22);
 cout<<"Q或Esc:退出游戏"; 
 SetPos(0,31);
 SetColor(8,0);
 cout<<"编者:cjz2005";
 SetPos(0,33);
 SetColor(7,0);
 cout<<"Walker v"<<banben;
    do
    {
     titi=getch();
     if(titi=='q'||titi=='Q'||titi==27)
     {
      FlashWindow(hwnd,true);
      Sleep(100); 
      FlashWindow(hwnd,false);
      Sleep(100);
      ShowWindow(hwnd,SW_HIDE);
      Sleep(300);
      exit(0);
  }
 }while(titi!='q'&&titi!='Q'&&titi!=13&&titi!=27);
    Cls();
    SetColor(10,0);
    DrawRow(c1,c2,'#');
    SetPos(45,1);
    SetColor(11,0);
    cout<<"W A L K E R";
    SetPos(44,13);
    cout<<"*正在载入存档...";
    Sleep(300);
    if((fp = fopen("save.wld","r")) == NULL)
    { SetPos(37,14);
     cout<<"*没有找到存档,正在新建文档..."; 
     Sleep(600);
     fp = fopen("save.wld","w");
          fprintf(fp,"2"); 
  nlevel=1;
     fclose(fp);
 }else
 {
  fscanf(fp,"%d",&rlevel);
  nlevel=rlevel/*-1*/;
  fclose(fp);
 }Cls();
 //nlevel--;
 if(nlevel==0)
 {
  system("color 0B");
  SetPos(35,20);
  cout<<"出错,游戏崩溃中……";
  MessageBeep(MB_ICONHAND); 
  Sleep(100);
  fp=fopen("save.wld","w");
  fprintf(fp,"2");
  fclose(fp);
  Sleep(10000); 
  abort();
 }
 fclose(fp);
 lec: //       选择关卡 
 Cls();
 SetColor(10,0);
    DrawRow(c1,c2,'=');
    SetPos(45,1);
    SetColor(11,0);
    cout<<"选 择 关 卡";
 PrintLevel(nlevel);
 SetPos(4,10);
 SetColor(14,0);
 cout<<"·Enter:进入下一关";
 SetPos(4,11);
 cout<<"·Esc:返回";
 SetPos(4,12);
 cout<<"·其它:选择关卡";
 isnl=getch();
 if(isnl==13)elevel=nlevel;//enter
 else if(isnl==27)//esc
 {
 goto tit;
 }
 else{//choosing
 SetPos(4,13);
 SetColor(11,0);
 cout<<"* 输入关卡(输入0退出): ";
 scanf("%d",&elevel);
 if(elevel==0)
 {
    goto lec;
 }
 if(elevel<=0||elevel>nlevel)
 {
  do{
  cout<<"\r                                                         ";
   SetPos(3,11);
 SetColor(12,0);
 if(elevel>nlevel)
 cout<<"·您输入的关卡未解锁,请";
 else 
 cout<<"·您输入的关卡不在范围内,请";
 cout<<"重新输入关卡: ";
 SetColor(10,0); 
 scanf("%d",&elevel);
     }while(elevel<=0||elevel>nlevel)
     ;
 }
 }
 SetPos(3,11);
 SetColor(12,0);
 cout<<"\r                                                       ";
 //getch();
 Cls();
 PlayLevel(elevel);
 do{
 if(isgo)
 PlayLevel(elevel2);
 }while(isgo);
 Cls();
 goto lec;
 return 0;
}
后记

感谢你的浏览。
啊。。到这里打字都很难了,太卡了。。主要是代码太长了。。没关系。
编译试试看吧。
(还有一点,我用的是Dev C++,不能使用#pragma comment,因此要试图加载音乐的时候,得链接winmm。我这里就加个参数就可以了:
链接

发布了17 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/cjz2005/article/details/104812023
今日推荐