C语言做迷宫小游戏

参考博客:https://www.cnblogs.com/xiao-qi-w/p/13031637.html

我用的是Dev-C++
第一次第一次写这么多行的代码,写的很菜

一开始写的是闪屏的,后来学到了不闪屏了

感觉很麻烦很多细节我就不加了

#include<stdio.h>
#include<conio.h>
#include<Windows.h>
#include<time.h>
#include<math.h>

//墙和路径的标识
#define WALL  0
#define ROUTE 1
#define PLAYER 2

int _x[500],_y[500];

//地图长度L,包括迷宫主体40,外侧的包围的墙体2,最外侧包围路径2
int L=10;

//控制迷宫的复杂度,数值越大复杂度越低,最小值为0
int Rank=0;

//行动步数
int cnt;

//积分
int score;

//出口处横坐标
int out;

//无用操作
int useless;

//开始和结束时间
clock_t start1,end1;

void CreateMaze(int **maze, int x, int y);//随机生成迷宫
void print(int** Maze);//打印地图
void start();//开始
int init(int** Maze);//初始化地图,返回出口横坐标
void HideCursor();//隐藏光标
void gotoxy(short y,short x);//不闪屏进行光标移动

int main()
{
    HideCursor();//隐藏光标
//    system("color 7C");

    printf("\t\t\t\t\t\t\t\t  游戏说明:\n\n");
    printf("\t\t\t\t\t\t\t★本游戏用wsad键来上下左右移动★\n\n");
    printf("\t\t\t\t\t\t\t★游戏中可以按Esc来返回主菜单★\n\n");
    printf("\t\t\t\t\t\t\t★玩家应当在有限时间内走出迷宫★\n\n");
    system("pause");
    while(777)
    {
        char x;
        system("cls");

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
        printf("\t\t\t\t\t\t\t★游戏开始前请先设置迷宫大小和难度★\n");
        printf("\t\t\t\t\t\t\t\t★按 a 为开始游戏★\n");
        printf("\t\t\t\t\t\t\t\t===================\n");
        printf("\t\t\t\t\t\t\t\t★按 b 为调整大小★\n");
        printf("\t\t\t\t\t\t\t\t===================\n");
        printf("\t\t\t\t\t\t\t\t★按 c 为调整难度★\n");
        printf("\t\t\t\t\t\t\t\t===================\n");
        printf("\t\t\t\t\t\t\t\t★按 d 为退出游戏★\n\n");
        printf("\t\t\t\t\t\t\t\t      请按键:\n");
        x=getch();

        if(x=='b'){
            system("cls");
            printf("\t\t\t\t\t\t\t\t★请输入迷宫大小★:");
            scanf("%d",&L);
            continue;
        }
        else if(x=='c'){
            system("cls");
            printf("\t\t\t\t\t\t\t\t★请输入迷宫难度(最小为0,越小越困难)★:");
            scanf("%d",&Rank);
            continue;
        }
        else if(x=='d'){
            break;
        }
        else if(x=='a'){
            start();//开始游戏
        }
        else break;
    }
	system("pause");
	return 0;
}

void HideCursor()
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
	CursorInfo.bVisible = false; //隐藏控制台光标
	SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
}

void gotoxy(short y,short x){
    COORD pos={x,y};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}

void CreateMaze(int **maze, int x, int y)
{
	maze[x][y] = ROUTE;//标记为路径
	int direction[4][2] = { { 1,0 },{ -1,0 },{ 0,1 },{ 0,-1 } };//上下右左

	//打乱四个方向,使其随机
	for (int i = 0; i < 4; i++) {
		int r = rand() % 4;
		int temp = direction[0][0];
		direction[0][0] = direction[r][0];
		direction[r][0] = temp;

		temp = direction[0][1];
		direction[0][1] = direction[r][1];
		direction[r][1] = temp;
	}

	//向四个已打乱的方向(可能重复)开始深搜
	for (int i = 0; i < 4; i++) {
		int dx = x;
		int dy = y;

		//控制挖的距离,由Rank来调整大小,也就是说rank越小,行动的范围range越小,步数越多
		//例rank为0时走一步就转向
		int range = 1 + (Rank == 0 ? 0 : rand() % Rank);

		while (range>0) {
			dx += direction[i][0];
			dy += direction[i][1];

			//排除掉回头路
			if (maze[dx][dy] == ROUTE) {
				break;
			}

			//判断是否挖穿路径
			int count = 0;
			for (int j = dx - 1; j < dx + 2; j++) {
				for (int k = dy - 1; k < dy + 2; k++) {
					//abs(j - dx) + abs(k - dy) == 1 确保只判断九宫格的四个特定位置,即dx合dy位置的上下左右
					if (abs(j - dx) + abs(k - dy) == 1 && maze[j][k] == ROUTE) {
						count++;
					}
				}
			}

            //判断是否只有来的那条路时路径
			if (count > 1) {
				break;
			}

			//确保不会挖穿时,前进
			--range;
			maze[dx][dy] = ROUTE;
		}

		//没有挖穿危险,以此为节点递归
		if (range <= 0) {
			CreateMaze(maze, dx, dy);
		}
	}
}

//初始化迷宫
int init(int** Maze)
{
    //最外围层设为路径的原因,为了防止挖路时挖出边界,同时为了保护迷宫主体外的一圈墙体被挖穿
	//迷宫的最外层为空白墙,即路径1
	for (int i = 0; i < L; i++){
		Maze[i][0] = ROUTE;
		Maze[0][i] = ROUTE;
		Maze[i][L - 1] = ROUTE;
		Maze[L - 1][i] = ROUTE;
	}

	//创造迷宫,(2,2)为起点
	CreateMaze(Maze, 2, 2);

	//画迷宫的入口和出口
	Maze[2][1] = PLAYER;
//	由于算法随机性,出口有一定概率不在(L-3,L-2)处,此时需要寻找出口
	for (int i = L - 3; i >= 0; i--) {
		if (Maze[i][L - 3] == ROUTE) {
			Maze[i][L - 2] = ROUTE;
			return i;//返回出口的纵坐标
		}
	}
}

void print(int** Maze)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
    for (int i = 0; i < L; i++) {
		for (int j = 0; j < L; j++) {
//            if((i == 2 && j == 0) || (i == out && j == L - 1)) continue;
            switch(Maze[i][j])
            {
            case 0:
                printf("■");
                break;
            case 1:
                printf("  ");
                break;
            case 2:
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
                printf("◆");
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
                break;
            }
		}
		printf("\n");
	}
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
}

void move(int** Maze,char direction,int x,int y)
{
    switch(direction)//后面找光标位置的y坐标时得乘2,因为前边一个空格或者符号占两个位置
    {
    case 'w':
        if(Maze[x-1][y]==0){useless++;break;}
        gotoxy(x,2*y);
        printf("  ");
        gotoxy(x-1,2*y);
        printf("◆");
//        Maze[x][y] = 1;
//        x--;
//        Maze[x][y] = 2;
        break;
    case 's':
        if(Maze[x+1][y]==0){useless++;break;}
        gotoxy(x,2*y);
        printf("  ");
        gotoxy(x+1,2*y);
        printf("◆");
//        Maze[x][y] = 1;
//        x++;
//        Maze[x][y] = 2;
        break;
    case 'a':
        if(Maze[x][y-1]==0){useless++;break;}
        gotoxy(x,2*y);
        printf("  ");
        gotoxy(x,2*(y-1));
        printf("◆");
//        Maze[x][y] = 1;
//        y--;
//        Maze[x][y] = 2;
        break;
    case 'd':
        if(Maze[x][y+1]==0){useless++;break;}
        gotoxy(x,2*y);
        printf("  ");
        gotoxy(x,2*(y+1));
        printf("◆");
//        Maze[x][y] = 1;
//        y++;
//        Maze[x][y] = 2;
        break;
    }
}

void start()
{
    //开始一局游戏

    //申请数组空间
    int **Maze = (int**)malloc(L * sizeof(int *));
    for (int i = 0; i < L; i++) {
        Maze[i] = (int*)calloc(L, sizeof(int));
    }

    //得到出口纵坐标
    out = init(Maze);

    int rt = rand()%20;
    for( ; ; ){

        cnt=  0;
        score = 0;
        useless = 0;

        char t;

        //y,x表示角色横纵坐标, out表示出口的纵坐标
        int x = 2, y = 1;
        _x[cnt] = 2;
        _y[cnt] = 1;

        //随机数发生器初始化函数
        srand((unsigned)time(NULL));

        //游戏开始
        x = 2; y = 1;
        Maze[2][1] = 2;
        Maze[out][L-2] = 1;

        system("cls");//清屏
        Maze[2][0] = 1;
        Maze[out][L - 1] = 1;

        gotoxy(L,10);

        printf("\t◆您需要在%d秒内走出迷宫◆\n",L/2 + rt);
        gotoxy(0,0);

        print(Maze);
        Maze[2][0] = 0;
        Maze[out][L - 1] = 0;

        int r=L+3;
        printf("步数:%d\n",cnt);
        printf("积分:%d\n",score);
        printf("无用的操作:%d\n",useless);
//        printf("倒计时:%d\n",countdown);

        int Maze_[500][500];
        memset(Maze_,0,sizeof Maze_);
        Maze[2][1] = 1;

        start1 = clock();

        for( ; ; ){
            t=getch();
            HideCursor();
            if(t == 27)   //如果输入为ESC键,结束游戏回到主菜单
                break;

            move(Maze, t, x, y);//根据输入t进行移动

            switch(t)
            {
                case 'w':
                {
                    if(Maze[x-1][y] == 0)break;
                    x --;
                    cnt ++;
                    _x[cnt] = x;
                    _y[cnt] = y;
                    break;
                }
                case 's':
                {
                    if(Maze[x+1][y] == 0)break;
                    x ++;
                    cnt ++;
                    _x[cnt] = x;
                    _y[cnt] = y;
                    break;
                }
                case 'a':
                {
                    if(Maze[x][y-1] == 0)break;
                    y --;
                    cnt ++;
                    _x[cnt] = x;
                    _y[cnt] = y;
                    break;
                }
                case 'd':
                {
                    if(Maze[x][y+1] == 0)break;
                    y ++;
                    cnt ++;
                    _x[cnt] = x;
                    _y[cnt] = y;
                    break;
                }
            }
            if(x == 2 && y == 1){}
            else if(!Maze_[x][y]){
                Maze_[x][y] = 1;
                score ++;
            }

            gotoxy(L,6);
            printf("%d",cnt);

            gotoxy(L+1,6);
            printf("%d",score);

            gotoxy(L+2,12);
            printf("%d",useless);

            if(x == out && y == L-2) {//已经到出口,游戏结束。
                end1 = clock();
                if((end1 - start1) / 1000 <= L/2 + rt){
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
                    system("cls");
                    printf("\t\t\t\t\t\t\t\t|===========================|\n");
                    printf("\t\t\t\t\t\t\t\t|恭喜你在有限时间内走到尽头!|\n");
                    printf("\t\t\t\t\t\t\t\t|===========================|\n\n");
                    printf("\n\t\t\t\t\t\t\t\t您所用的时间为:%d s\n",(end1 - start1)/1000);
                    printf("\n\t\t\t\t\t\t\t\t您行走的路线为:");
                    for(int i = 0;i <= cnt; i ++){
                        if(i != 0)printf("->");
                        printf("(%d,%d)",_x[i],_y[i]);
                    }
                    printf("\n");
                    int _Maze[500][500];
                    memset(_Maze,0,sizeof _Maze);
                    for(int i = 0;i <= cnt;i ++){
                        _Maze[_x[i]][_y[i]]=1;
                    }

                    printf("\t\t\t\t\t\t\t\t您行走的步数为:%d\n\n",cnt);
                    printf("\t\t\t\t\t\t\t\t您的积分为:%d\n\n",score);
                    printf("\t\t\t\t\t\t\t\t您无效操作次数为:%d\n\n",useless);
                    printf("\t\t\t\t\t\t\t\t您行走的路线图为:\n\n");
                    for (int i = 0; i < L; i++) {
                        for (int j = 0; j < L; j++) {
                            if(i == 0 || i == L - 1 || j == 0 || j == L -1){
                                printf("  ");
                            }
                            else   {
                                switch(_Maze[i][j])
                                {
                                case 0:
                                    printf("--");
                                    break;
                                case 1:
                                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
                                    printf("◆");
                                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
                                    break;
                                }
                            }
                        }
                        printf("\n");
                    }
                    printf("\n");

                    system("pause");
                    system("cls");

                    break;
                }
                else {
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
                    system("cls");
                    printf("\t\t\t\t\t\t\t\t|=================|\n");
                    printf("\t\t\t\t\t\t\t\t|很不幸您挑战失败!|\n");
                    printf("\t\t\t\t\t\t\t\t|=================|\n");
                    printf("\n\t\t\t\t\t\t\t\t您所用的时间为:%d s\n\n",(end1 - start1)/1000);
                    printf("\t\t\t\t\t\t\t\t您行走的步数为:%d\n\n",cnt);
                    printf("\t\t\t\t\t\t\t\t您的积分为:%d\n\n",score);
                    printf("\t\t\t\t\t\t\t\t您无效操作次数为:%d\n\n",useless);
                    system("pause");
                    system("cls");
                    break;
                }
            }
        }

        printf("\n                ◆如果想重新玩这个迷宫的话请按r◆\n");
        printf("\n");
        printf("                ◆如果想回到菜单的话请按g◆\n");

        int flag=0;
        t=getch();
        switch(t)
        {
        case 'r':
            flag=0;
            break;
        case 'g':
            flag=1;
            break;
        }
        if(flag==0)continue;
        else break;
    }

    //一局游戏结束,释放内存
    for (int i = 0; i < L; i++) free(Maze[i]);
    free(Maze);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值