欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言小游戏推箱子2.0vs【正式版】

程序员文章站 2022-04-08 08:53:27
...

前言:

  • 之前发了测试版的代码,随后我自己发现了bug,然后删了文章,下午又研究了会最后做出了正式版,我也是学生,也在学习C语言,一起加油~(暂时地图制作只允许由小坐标到大坐标)*

更新日志:

LV2.0正式版
~1、优化函数,兼容动态数组。
~2、修改回原始字符,因技术原因暂不得使用多字节字符。
~3、新增函数(go)(makemap)。
~4、新增地图编辑器,可保存地图。
~5、新增读取地图功能,制作的地图有用啦。
——BUG:
~1、暂无。

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓代码↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

#include <stdio.h>
#include <Windows.h>
#include <string.h>

using namespace std;

//全部向**释,也就是注释的是下面的代码
//“*”是墙,“X”是终点,“@”是箱子,“O”是玩家.“.”是地板

int  man_x = 0, man_y = 0, man_z = 0, man_x1 = 0, man_y1 = 0, x, y, dtszx, dtszy, dtszz = 1, mapnum = 1;
char map[100][100][1] =
{
{ {'*'}, {'*'}, {'*'}, {'*'}, {'*'}, {'*'} },
{ {'*'}, {'.'}, {'@'}, {'X'}, {'X'}, {'*'} },
{ {'*'}, {'.'}, {'*'}, {'*'}, {'.'}, {'*'} },
{ {'*'}, {'.'}, {'.'}, {'@'}, {'.'}, {'*'} },
{ {'*'}, {'O'}, {'*'}, {'.'}, {'.'}, {'*'} },
{ {'*'}, {'*'}, {'*'}, {'*'}, {'*'}, {'*'} },
};
char map1[100][100][1], map2[100][100][1], CharQ[1] = { '*' }, CharL[1] = { '.' }, CharXZ[1] = { '@' }, CharR[1] = { 'O' }, CharZD[1] = { 'X' };
char*** dtsz;
FILE* fpRead, * fpWrite;

//声明函数,若先定义的函数用到了后定义的函数那么要声明后定义的函数,否则报错

void load();
void readmap();
void sevemap();

//写一个showmap函数来显示游戏地图,也就是输出数组

//此函数为修改输出字符颜色:1蓝色,4红色,7白色(默认颜色),8灰色,10浅绿色,12粉红色,13紫色,14肉色

void color(int x)
{
    HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(h, x);
}

void showmap()
{
    int i, j, k;
    system("cls");

    //按照行和列输出,我的x和y可能是相反的,知道概念就行

    for (i = 0;i < dtszy;i++)
    {
        for (j = 0;j < dtszx; j++)
            for (k = 0;k < dtszz;k++)
            {
                printf("%2c", dtsz[i][j][k]);
                if (dtsz[i][j][k] == NULL)
                    break;
            }
        printf("%2d", i);
        printf("\n");
    }
    for (i = 0;i < dtszx;i++)
    {
        if ((i + 2) % 2 == 0)
            color(1);
        else color(12);
        printf("%2d", i);
    }
    printf("\n");
    color(14);
    printf("2.0测试版\t请输入“w”“a”“s”“d”来操作方向,“h”为回退,只能回退一步,“r”为重新开始,输入“end”结束游戏\n");
    color(7);
}

//地图编辑器的输出地图函数

void showmap2()
{
    int i, j, k;
    system("cls");
    for (i = 0;i < dtszy;i++)
    {
        for (j = 0;j < dtszx;j++)
        {
            for (k = 0;k < dtszz;k++)
                printf("%2c", dtsz[i][j][k]);
        }
        printf("%2d", i);
        printf("\n");
    }
    for (i = 0;i < dtszx;i++)
    {
        if ((i + 2) % 2 == 0)
            color(1);
        else color(12);
        printf("%2d", i);
    }
    printf("\n");
    color(7);
}

void copymap1()
{
    for (int i = 0;i < dtszy;i++)
        for (int j = 0;j < dtszx; j++)
            for (int k = 0;k < dtszz; k++)
                map1[i][j][k] = dtsz[i][j][k];
    man_x1 = man_x;
    man_y1 = man_y;
}

//左移函数,下面三个移动函数同理,判断人物移动方向的字符是什么,然后替换字符,调用加载终点函数和输出地图函数

void left()//完成
{
    for (int k = 0;k < dtszz;k++)
    {
        if (dtsz[man_y][man_x - 1][k] == CharL[k] || dtsz[man_y][man_x - 1][k] == CharZD[k])
        {
            copymap1();
            dtsz[man_y][man_x][k] = CharL[k];
            dtsz[man_y][man_x - 1][k] = CharR[k];
            man_x--;
            load();
            showmap();
        }
        else if (dtsz[man_y][man_x - 1][k] == CharXZ[k])
            if (dtsz[man_y][man_x - 2][k] == CharL[k] || dtsz[man_y][man_x - 2][k] == CharZD[k])
            {
                copymap1();
                dtsz[man_y][man_x - 2][k] = CharXZ[k];
                dtsz[man_y][man_x - 1][k] = CharR[k];
                dtsz[man_y][man_x][k] = CharL[k];
                man_x--;
                load();
                showmap();
            }
            else
                MessageBoxA(0, "推不动啦", "警告", MB_OK);
        else
            MessageBoxA(0, "走不动啦", "警告", MB_OK);
    }
}

void right()//完成
{
    for (int k = 0;k < dtszz;k++)
    {
        if (dtsz[man_y][man_x + 1][k] == CharL[k] || dtsz[man_y][man_x + 1][k] == CharZD[k])
        {
            copymap1();
            dtsz[man_y][man_x][k] = CharL[k];
            dtsz[man_y][man_x + 1][k] = CharR[k];
            man_x++;
            load();
            showmap();
        }
        else if (dtsz[man_y][man_x + 1][k] == CharXZ[k])
            if (dtsz[man_y][man_x + 2][k] == CharL[k] || dtsz[man_y][man_x + 2][k] == CharZD[k])
            {
                copymap1();
                dtsz[man_y][man_x + 2][k] = CharXZ[k];
                dtsz[man_y][man_x + 1][k] = CharR[k];
                dtsz[man_y][man_x][k] = CharL[k];
                man_x++;
                load();
                showmap();
            }
            else
                MessageBoxA(0, "推不动啦", "警告", MB_OK);
        else
            MessageBoxA(0, "走不动啦", "警告", MB_OK);
    }
}

void up()//完成
{
    for (int k = 0;k < dtszz;k++)
    {
        if (dtsz[man_y - 1][man_x][k] == CharL[k] || dtsz[man_y - 1][man_x][k] == CharZD[k])
        {
            copymap1();
            dtsz[man_y][man_x][k] = CharL[k];
            dtsz[man_y - 1][man_x][k] = CharR[k];
            man_y--;
            load();
            showmap();
        }
        else if (dtsz[man_y - 1][man_x][k] == CharXZ[k])
            if (dtsz[man_y - 2][man_x][k] == CharL[k] || dtsz[man_y - 2][man_x][k] == CharZD[k])
            {
                copymap1();
                dtsz[man_y - 2][man_x][k] = CharXZ[k];
                dtsz[man_y - 1][man_x][k] = CharR[k];
                dtsz[man_y][man_x][k] = CharL[k];
                man_y--;
                load();
                showmap();
            }
            else
                MessageBoxA(0, "推不动啦", "警告", MB_OK);
        else
            MessageBoxA(0, "走不动啦", "警告", MB_OK);
    }
}

void down()//完成
{
    for (int k = 0;k < dtszz;k++)
    {
        if (dtsz[man_y + 1][man_x][k] == CharL[k] || dtsz[man_y + 1][man_x][k] == CharZD[k])
        {
            copymap1();
            dtsz[man_y][man_x][k] = CharL[k];
            dtsz[man_y + 1][man_x][k] = CharR[k];
            man_y++;
            load();
            showmap();
        }
        else if (dtsz[man_y + 1][man_x][k] == CharXZ[k])
            if (dtsz[man_y + 2][man_x][k] == CharL[k] || dtsz[man_y + 2][man_x][k] == CharZD[k])
            {
                copymap1();
                dtsz[man_y + 2][man_x][k] = CharXZ[k];
                dtsz[man_y + 1][man_x][k] = CharR[k];
                dtsz[man_y][man_x][k] = CharL[k];
                man_y++;
                load();
                showmap();
            }
            else
                MessageBoxA(0, "推不动啦", "警告", MB_OK);
        else
            MessageBoxA(0, "走不动啦", "警告", MB_OK);
    }
}

//回退函数,返回上一个操作符,就是用一个备用数组保存操作前的地图,然后回退时赋值回去

void ht()
{
    for (int i = 0;i < dtszy;i++)
        for (int j = 0;j < dtszx; j++)
            for (int k = 0;k < dtszz; k++)
                dtsz[i][j][k] = map1[i][j][k];

    man_y = man_y1;
    man_x = man_x1;
    showmap();
}

//重新开始函数,原理与回退一致

void ag()
{
    for (int i = 0;i < dtszy;i++)
        for (int j = 0;j < dtszx; j++)
            for (int k = 0;k < dtszz; k++)
            {
                dtsz[i][j][k] = map2[i][j][k];
                if (map2[i][j][0] == NULL)
                    break;
            }

    man_y = y;
    man_x = x;
    showmap();
}

//加载终点函数,时刻与最初的地图做对比,如果原本终点的位置被玩家占有后变成空地那么该地点就还原为终点

void load()
{
    int i, j, k;
    for (i = 0;i < dtszy;i++)
        for (j = 0;j < dtszx;j++)
            for (k = 0;k < dtszz;k++)
                if (map2[i][j][0] == 'X')
                    if (dtsz[i][j][k] != map2[i][j][k] && dtsz[i][j][k] == '.')
                        dtsz[i][j][k] = map2[i][j][k];
}

//制作地图函数

void makemap()
{
    int i, j, k, mkmapx1, mkmapy1, mkmapx2, mkmapy2, xz = NULL, mannum = 0, xznum = 0, zdnum = 0;
    char fx = '1';
    dtszx = 200;
    dtszy = 200;
    while (dtszx > 60 || dtszy > 45 || dtszx < 6 || dtszy < 6)
    {
        system("cls");
        printf("输入地图大小:列数和行数min:6*6 max:60*45\n");
        scanf_s("%d %d", &dtszx, &dtszy);
    }

    //调用windows头文件执行代码,创建窗口

    MessageBoxA(0, "现在将窗口调至最大", "友情提示", MB_OK);

    //动态数组创建,开辟空间

    dtsz = new char** [dtszy];
    for (int i = 0; i < dtszy; ++i)
    {
        dtsz[i] = new char* [dtszx];
        for (int j = 0; j < dtszx; ++j)
        {
            dtsz[i][j] = new char[1];
        }
    }
    for (i = 0;i < dtszy;i++)
        for (j = 0;j < dtszx;j++)
            for (k = 0;k < dtszz;k++)
            {
                dtsz[i][j][k] = CharL[k];
                if (i == 0 || j == 0 || i == dtszy - 1 || j == dtszx - 1)
                {
                    dtsz[i][j][k] = CharQ[k];
                }
            }

    //以下是在地图编辑器中的操作

    while (xz != 8)
    {
        system("cls");
        showmap2();
        printf("输入坐标加数字改变位置或区域属性,如:修改坐标(10,10)到(11,11)的值为墙则输入“");
        color(4);
        printf("10.10 11.11 1");
        color(7);
        printf("”人物只能由第一个坐标决定位置\n1、墙“*”。2、路“.”。3、玩家“O”。4、箱子“@”。5、箱子终点“X”。6、保存(");
        color(4);
        printf("仅可保存一张图");
        color(7);
        printf(")。7、游玩。8、退出。(即使退出也需填写坐标)\n");
        scanf_s("%d.%d %d.%d %d", &mkmapx1, &mkmapy1, &mkmapx2, &mkmapy2, &xz);
        switch (xz)
        {
        case 1:
        {
            for (i = mkmapy1;i <= mkmapy2;i++)
                for (j = mkmapx1;j <= mkmapx2;j++)
                    for (k = 0;k < dtszz;k++)
                        dtsz[i][j][k] = CharQ[k];break;
        }
        case 2:
        {
            for (i = mkmapy1;i <= mkmapy2;i++)
                for (j = mkmapx1;j <= mkmapx2;j++)
                    for (k = 0;k < dtszz;k++)
                        dtsz[i][j][k] = CharL[k];break;
        }
        case 3:
        {
            if (mannum < 1)
            {
                for (i = mkmapy1;i <= mkmapy1;i++)
                    for (j = mkmapx1;j <= mkmapx1;j++)
                        for (k = 0;k < dtszz;k++)
                            dtsz[i][j][k] = CharR[k];
            }
            else MessageBoxA(0, "已经存在一个人物", "警告", MB_OK);break;
        }
        case 4:
        {
            for (i = mkmapy1;i <= mkmapy2;i++)
                for (j = mkmapx1;j <= mkmapx2;j++)
                    for (k = 0;k < dtszz;k++)
                        dtsz[i][j][k] = CharXZ[k];break;
        }
        case 5:
        {
            for (i = mkmapy1;i <= mkmapy2;i++)
                for (j = mkmapx1;j <= mkmapx2;j++)
                    for (k = 0;k < dtszz;k++)
                        dtsz[i][j][k] = CharZD[k];break;
        }
        case 6://保存,对文件的操作
        {
            if (xznum != zdnum)
            {
                MessageBoxA(0, "箱子数量不等于终点数量", "警告", MB_OK);
                xz = 0;
            }
            else if (mannum == 0)
            {
                MessageBoxA(0, "缺少玩家", "警告", MB_OK);
                xz = 0;
            }
            else if (xznum < 1 || zdnum < 1)
            {
                MessageBoxA(0, "缺少箱子或者终点", "警告", MB_OK);
                xz = 0;
            }
            else
            {
                sevemap();
                xz = 0;break;
            }
        }
        case 7://结束前判断
        {
            if (xznum != zdnum)
            {
                MessageBoxA(0, "箱子数量不等于终点数量", "警告", MB_OK);
                xz = 0;
            }
            else xz = 8;break;
        }
        case 8:
        {
            if (xznum != zdnum)
            {
                MessageBoxA(0, "箱子数量不等于终点数量", "警告", MB_OK);
                xz = 0;
            }
            else if (mannum == 0)
            {
                MessageBoxA(0, "缺少玩家", "警告", MB_OK);
                xz = 0;
            }
            else if (xznum < 1 || zdnum < 1)
            {
                MessageBoxA(0, "缺少箱子或者终点", "警告", MB_OK);
                xz = 0;
            }
            else xz = 8;
            break;
        }
        }
        mannum = zdnum = xznum = 0;
        for (i = 0;i < dtszy;i++)
            for (j = 0;j < dtszx;j++)
                for (k = 0;k < dtszz;k++)
                {
                    if (dtsz[i][j][k] == CharR[k])
                        mannum++;
                    if (dtsz[i][j][k] == CharXZ[k])
                        xznum++;
                    if (dtsz[i][j][k] == CharZD[k])
                        zdnum++;
                }
    }
    MessageBoxA(0, "点击确定游戏", "开始游戏", MB_OK);
}

//正常开始游戏的函数

void go()
{
    int i, j, k;
    dtszx = 6;
    dtszy = 6;
    dtsz = new char** [dtszy];
    for (int i = 0; i < dtszy; ++i)
    {
        dtsz[i] = new char* [dtszx];
        for (int j = 0; j < dtszx; ++j)
            dtsz[i][j] = new char[1];
    }

    for (i = 0;i < dtszy;i++)
        for (j = 0;j < dtszx;j++)
            for (k = 0;k < dtszz;k++)
            {
                if (map[i][j][k] == NULL)
                    break;
                dtsz[i][j][k] = map[i][j][k];
            }
}

void choice()
{
    int choice;
    color(4);
    printf("请选择:\n\t");
    color(14);
    printf("1、开始游戏。\n\t2、地图编辑器。\n\t3、读取地图\n\t");
    color(7);
    scanf_s("%d", &choice);
    switch (choice)
    {
    case 1:go();break;
    case 2:makemap();break;
    case 3:readmap();break;
    }
}

void readmap()
{
    int i, j, k;
    char b[1];

    fopen_s(&fpRead, "map.txt", "r");

    for (i = 0;b[0] != '$';i++)
        fscanf_s(fpRead, "%c", &b[0], 10);
    fscanf_s(fpRead, "%d\t%d\n", &dtszy, &dtszx);

    dtsz = new char** [dtszy];
    for (int i = 0; i < dtszy; ++i)
    {
        dtsz[i] = new char* [dtszx];
        for (int j = 0; j < dtszx; ++j)
            dtsz[i][j] = new char[dtszz];
    }

    for (i = 0;i < dtszy;i++)
    {
        for (j = 0;j < dtszx;j++)
            for (k = 0;k < dtszz;k++)
                fscanf_s(fpRead, "%c", &dtsz[i][j][k], 10);
        fscanf_s(fpRead, "%c", &b[0], 10);//这里,读取换行符
    }
    fclose(fpRead);
}

void sevemap()
{
    int i, j, k;
    fopen_s(&fpWrite, "map.txt", "w");
    fprintf(fpWrite, "$\t%d\t%d\n", dtszy, dtszx);
    for (i = 0;i < dtszy;i++)
    {
        for (j = 0;j < dtszx;j++)
            for (k = 0;k < dtszz;k++)
                fprintf(fpWrite, "%c", dtsz[i][j][k]);
        fprintf(fpWrite, "\n");
    }
    fprintf(fpWrite, "\n");
    fclose(fpWrite);
    MessageBoxA(0, "已经保存", "警告", MB_OK);
}

int main()
{
    int i = 0, j = 0, k = 0, end = 0, zdx = 0, zdy = 0, zdnum = 0, zdnum2;
    char fx, bj1[1] = { '0' };
    system("mode con cols=150 lines=49");

    choice();
    MessageBoxA(0, "点击确定游戏", "开始游戏", MB_OK);
    showmap();

    for (i = 0;i < dtszy;i++)
        for (j = 0;j < dtszx; j++)
            for (k = 0;k < dtszz; k++)
                map2[i][j][k] = dtsz[i][j][k];

    for (i = 0;i < dtszy;i++)
        for (j = 0;j < dtszx; j++)
            for (k = 0;k < dtszz; k++)
                if (dtsz[i][j][k] == CharR[k])
                {
                    man_y = i;
                    y = i;
                    man_x = j;
                    x = j;
                    map2[i][j][k] = dtsz[i][j][k];
                }

    for (i = 0;i < dtszy;i++)
        for (j = 0;j < dtszx;j++)
            for (k = 0;k < dtszz;k++)
            {
                if (dtsz[i][j][k] == CharZD[k])
                {
                    zdnum++;
                    zdnum2 = zdnum;
                }
            }

    while (zdnum != 0)
    {
        scanf_s("%c", &fx, 2);

        if (fx == 'w' && end == 0)
            up();
        if (fx == 's' && end == 0)
            down();
        if (fx == 'a' && end == 0)
            left();
        if (fx == 'd' && end == 0)
            right();
        if (fx == 'h' && end == 0)
            ht();
        if (fx == 'r' && end == 0)
            ag();
        if (fx == 'e')
        {
            end = 1;
            showmap();
        }
        if (fx == 'n' && end == 1)
        {
            end = 2;
            showmap();
        }
        if (fx == 'd' && end == 2)
            break;
        load();
        zdnum = zdnum2;
        for (i = 0;i < 100;i++)
            for (j = 0;j < 100;j++)
                for (k = 0;k < dtszz;k++)
                    if (map2[i][j][k] == 'X')
                        if (dtsz[i][j][k] == '@')
                            zdnum--;
    }
    if (zdnum == 0)
        MessageBoxA(0, "胜利!!", "", MB_OK);
    else MessageBoxA(0, "游戏结束", "", MB_OK);

    delete[]dtsz;
}

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑代码↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
C语言小游戏推箱子2.0vs【正式版】
还会继续更新!有bug记得反馈哦~
度盘:
链接:https://pan.baidu.com/s/1xTPZ0udYOZLm9VNQMIDffg
提取码:2ufq
如果不允许贴连接我就认了,也是方便大家~