用C语言写一个可以选择关卡添加关卡的小游戏,推箱子

关于用C语言写一个可以选择关卡的小游戏

这个小游戏就是大家熟知的推箱子,废话不多说先上效果图在这里插入图片描述

上面的 五角星 就是玩家的位置,红色的箱子 就是已经放到指定位置的样子,黄色的箱子是还没有在指定位置的箱子,黑色的方框就是黄色箱子该放置的位置,然后我们使用来操作我们的五角星也就是我们的玩家位置

代码部分

所有代码

Tui_Xiang_Zi.h
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <conio.h>
#define MAXSIZE 20
#define MAXSIZE2 15

typedef struct Tui_Xiang_Zi
{
    //我的 x y   目标点 x  y   长  宽
    // 剩余目标点数  总目标点数
    int p_Now, p_Zong, mx, my, X1[MAXSIZE2], Y1[MAXSIZE2], Kuan, Chang;
    int map_Data[MAXSIZE][MAXSIZE];
} Guan_Ka;

//初始化 分配内存
void Initialization(Guan_Ka *&s)
{
    s = (Guan_Ka *)malloc(sizeof(Guan_Ka));
    //以下内容为初始化数据
    s->my = s->mx = s->Kuan = s->Chang = s->p_Now = s->p_Zong = 0;
    for (int i = 0; i < 10; i++)
    {
        s->X1[i] = s->Y1[i] = 0;
    }
    for (int i = 0; i < MAXSIZE; i++)
    {
        for (int n = 0; n < MAXSIZE; n++)
        {
            s->map_Data[i][n] = 0;
        }
    }
}

//释放
void Destroy(Guan_Ka *&s)
{
    free(s);
}

//读取关卡
int read_Guan_ka(char Guan[2], Guan_Ka *&s)
{
    FILE *fp;
    int c, k;
    char fpp[] = {"./Tui_Xiang_zi01.txt"};
    fpp[14] = Guan[0];
    fpp[15] = Guan[1];
    if ((fp = fopen(fpp, "r")) == NULL)
    {
        return 0;
    }
    c = (int)fgetc(fp) - 48;
    s->Chang = c * 10 + (int)fgetc(fp) - 48;
    k = (int)fgetc(fp) - 48;
    s->Kuan = k * 10 + (int)fgetc(fp) - 48;
    for (int i = 0; i < s->Kuan; i++)
    {
        for (int n = 0; n < s->Chang; n++)
        {
            s->map_Data[i][n] = (int)fgetc(fp) - 48;
            //数据检查 使用时请注释上行  解释下行
            //printf("%d",s->map_Data[i][n] =(int)fgetc(fp) - 48);
        }
    }
    fclose(fp);
    return 1;
}

//上移 操作
void up(Guan_Ka *&s)
{

    if (s->map_Data[s->my - 2][s->mx - 1] == 1)
    {
        return;
    }
    else if (s->map_Data[s->my - 2][s->mx - 1] == 4 || s->map_Data[s->my - 2][s->mx - 1] == 3)
    {
        if (s->map_Data[s->my - 3][s->mx - 1] == 2 || s->map_Data[s->my - 3][s->mx - 1] == 0)
        {
            s->map_Data[s->my - 3][s->mx - 1] = s->map_Data[s->my - 2][s->mx - 1];
            s->map_Data[s->my - 2][s->mx - 1] = 0;
            s->map_Data[s->my - 2][s->mx - 1] = s->map_Data[s->my - 1][s->mx - 1];
            s->map_Data[s->my - 1][s->mx - 1] = 0;
            s->my--;
        }
    }
    else
    {
        s->map_Data[s->my - 2][s->mx - 1] = s->map_Data[s->my - 1][s->mx - 1];
        s->map_Data[s->my - 1][s->mx - 1] = 0;
        s->my--;
    }
}

//下移  操作
void down(Guan_Ka *&s)
{
    if (s->map_Data[s->my][s->mx - 1] == 1)
    {
        return;
    }
    else if (s->map_Data[s->my][s->mx - 1] == 4 || s->map_Data[s->my][s->mx - 1] == 3)
    {
        if (s->map_Data[s->my + 1][s->mx - 1] == 2 || s->map_Data[s->my + 1][s->mx - 1] == 0)
        {
            s->map_Data[s->my + 1][s->mx - 1] = s->map_Data[s->my][s->mx - 1];
            s->map_Data[s->my][s->mx - 1] = 0;
            s->map_Data[s->my][s->mx - 1] = s->map_Data[s->my - 1][s->mx - 1];
            s->map_Data[s->my - 1][s->mx - 1] = 0;
            s->my++;
        }
    }
    else
    {
        s->map_Data[s->my][s->mx - 1] = s->map_Data[s->my - 1][s->mx - 1];
        s->map_Data[s->my - 1][s->mx - 1] = 0;
        s->my++;
    }
}

// 左移  操作
void left(Guan_Ka *&s)
{
    if (s->map_Data[s->my - 1][s->mx - 2] == 1)
    {
        return;
    }
    else if (s->map_Data[s->my - 1][s->mx - 2] == 4 || s->map_Data[s->my - 1][s->mx - 2] == 3)
    {
        if (s->map_Data[s->my - 1][s->mx - 3] == 2 || s->map_Data[s->my - 1][s->mx - 3] == 0)
        {
            s->map_Data[s->my - 1][s->mx - 3] = s->map_Data[s->my - 1][s->mx - 2];
            s->map_Data[s->my - 1][s->mx - 2] = 0;
            s->map_Data[s->my - 1][s->mx - 2] = s->map_Data[s->my - 1][s->mx - 1];
            s->map_Data[s->my - 1][s->mx - 1] = 0;
            s->mx--;
        }
    }
    else
    {
        s->map_Data[s->my - 1][s->mx - 2] = s->map_Data[s->my - 1][s->mx - 1];
        s->map_Data[s->my - 1][s->mx - 1] = 0;
        s->mx--;
    }
}

//  右移 操作
void right(Guan_Ka *&s)
{
    if (s->map_Data[s->my - 1][s->mx] == 1)
    {
        return;
    }
    else if (s->map_Data[s->my - 1][s->mx] == 4 || s->map_Data[s->my - 1][s->mx] == 3)
    {
        if (s->map_Data[s->my - 1][s->mx + 1] == 2 || s->map_Data[s->my - 1][s->mx + 1] == 0)
        {
            s->map_Data[s->my - 1][s->mx + 1] = s->map_Data[s->my - 1][s->mx];
            s->map_Data[s->my - 1][s->mx] = 0;
            s->map_Data[s->my - 1][s->mx] = s->map_Data[s->my - 1][s->mx - 1];
            s->map_Data[s->my - 1][s->mx - 1] = 0;
            s->mx++;
        }
    }
    else
    {
        s->map_Data[s->my - 1][s->mx] = s->map_Data[s->my - 1][s->mx - 1];
        s->map_Data[s->my - 1][s->mx - 1] = 0;
        s->mx++;
    }
}

//扫描 并确定目标点坐标 和 我的坐标
void Scanning(Guan_Ka *&s)
{
    int i = 0, n = 0;
    s->p_Now=0;
    for (i = 0; i < s->Kuan; i++)
    {

        for (n = 0; n < s->Chang; n++)
        {
            if (s->map_Data[i][n] == 4 || s->map_Data[i][n] == 2)
            {
                s->X1[s->p_Now] = n;
                s->Y1[s->p_Now] = i;
                s->p_Now++;
            }
            if (s->map_Data[i][n] == 5)
            {
                s->mx = n + 1;
                s->my = i + 1;
            }
        }
    }
    s->p_Zong = s->p_Now;
}

// 判断目标点还有几个 和  纠正目标点
int pass_Ok(Guan_Ka *&s)
{
    s->p_Now = s->p_Zong;
    for (int i = 0; i < s->p_Zong; i++)
    {
        //当目标点变成空地的时候 恢复目标点 该有的样子
        if (s->map_Data[s->Y1[i]][s->X1[i]] == 0)
        {
            s->map_Data[s->Y1[i]][s->X1[i]] = 2;
        }
        //如果目标点坐标上面有箱子 那么目标点就减一
        if (s->map_Data[s->Y1[i]][s->X1[i]] == 4 || s->map_Data[s->Y1[i]][s->X1[i]] == 3)
        {
            s->p_Now--;
        }
    }
    return s->p_Now;
}

//显示  推箱子关卡
void display_Level(Guan_Ka *&s)
{
    int i = 0, n = 0, z = 0;
    for (i = 0; i < s->Kuan; i++)
    {
        for (n = 0; n < s->Chang; n++)
        {
            switch (s->map_Data[i][n])
            {
                //不同的 数据表示了不同的形状
            case 0:
                printf("  ");
                break;
            case 1:
                printf("█ ");
                break;
            case 2:
                printf("□");
                break;
            case 3:
            case 4:
                for (z = 0; z < s->p_Zong; z++)
                {
                    if (i == s->Y1[z] && n == s->X1[z])
                    {
                        printf("\033[31m■\033[37m");
                        break;
                    }
                }
                if (z >= s->p_Zong)
                {
                    printf("\033[33m■\033[37m");
                }
                break;
            case 5:
                for (z = 0; z < s->p_Zong; z++)
                {
                    if (i == s->Y1[z] && n == s->X1[z])
                    {
                        printf("\033[31m★\033[37m");
                        break;
                    }
                }
                if (z >= s->p_Zong)
                {
                    printf("★");
                }
                break;
            }
        }
        printf("\n");
    }
}

Tui_Xiang_Zi.cpp
#include "Tui_Xiang_Zi.h"
//关卡选择界面


void operation_Interface(int n)
{
    switch (n)
    {
    case 1:
        printf("-------------------\n");
        printf(" 欢迎来到推箱子游戏\n");
        printf("     请选择关卡\n");
        printf("       01-26关\n");
        printf("-------------------\n");
        break;
    case 2:
        printf("-------------------\n");
        printf(" \033[31m    输入关卡有误\033[37m\n");
        printf("     请重新输入\n");
        printf("       01-26关\n");
        printf("-------------------\n");
        break;
    }
}

int main()
{
    //初始化窗口
    system("mode con cols=51 lines=15");
    int n = 1, i = 1;
    char a[2] = {'0', '1'};
    Guan_Ka *guan;
    operation_Interface(1);
    Initialization(guan);
    scanf("%s", a);
    while(read_Guan_ka(a, guan) == 0){
        system("cls");
        operation_Interface(2);   
        scanf("%s", a);
    }
    while (n)
    {
    again:
        system("cls");
        if (read_Guan_ka(a, guan) == 0)
        {
            printf("\033[33m恭喜你已经通关\033[37\n");
            break;
        }
        Scanning(guan);
        
        // for(int i=0;i<guan->Kuan;i++)
        // for (int n = 0; n < guan->Chang; n++)
        // {
        //     printf("%d",guan->map_Data[i][n]);
        // }
        i = 1;
        while (i)
        {
            if (pass_Ok(guan) == 0)
            {
                printf("第%c%c关\n", a[0], a[1]);
                display_Level(guan);
                printf("即将下一关\n");
                sleep(1);
                break;
            }
            else
            {
                printf("第%c%c关\n", a[0], a[1]);
                display_Level(guan);
                printf("重新开始 请按0\n退出     请按1\n ");
            }
            int b;
            b = _getch();
            switch (b)
            {
            case 72:
                up(guan);
                break;

            case 75:
                left(guan);
                break;
            case 77:
                right(guan);
                break;
            case 80:
                down(guan);
                break;
            case '0':
                goto again;
            case '1':
                goto tuichu;
            }
            system("cls");
        }
        if (a[1] == 57)
        {
            a[0]++;
            a[1] = 48;
        }
        else
        {
            a[1]++;
        }
    }
tuichu:
    free(guan);
    printf("游戏结束 按任意键退出\n");
    getch();
}

关卡数据

下面的需要创建一个txt文件,然后每一个txt文件里面就放一串下面的数字,该文件需要放在同一目录下

// 后两位的数字是关卡数
//  Tui_Xiang_Zi01.txt
08080011100000121000001011111113032112035111111131000001210000011100
//  Tui_Xiang_Zi02.txt
0909111110000150010000103310111103010121111011121011000021010001001010001111011111000
//  Tui_Xiang_Zi03.txt
10070111111100010000011111311100011050300301102210301111221000100111111110
//  Tui_Xiang_Zi04.txt
0608011110110010153010113011110301123001122421111111
//  Tui_Xiang_Zi05.txt
08080111110001001110015300101110101112101001123001011200030111111111
//  Tui_Xiang_Zi06.txt
131100011111110001111000001000100021110100010101000011001010303120100101004001010010213030101001100001010111010111200005101000001100010111111111111
//  Tui_Xiang_Zi07.txt
100800011111110011001051001000100100130303010010311001111030101112222200101111111110
//  Tui_Xiang_Zi08.txt
10070001111110011100001011203110111223030051122030301111111100100000011110
//  Tui_Xiang_Zi09.txt
1109011111111100100110001001000300010013011103100101222101011012221011103003003011000001050111111111111
//  Tui_Xiang_Zi10.txt
080700111111001000011113330115032201103222111111001000011110
//  Tui_Xiang_Zi11.txt
1206011110011111110010010001103011113001100322220301110000105011011111111110
//  Tui_Xiang_Zi12.txt
080700111110111005101003201110023201111043010010001100111110
//  Tui_Xiang_Zi13.txt
08080011110000122100011021100100321011030011100133011005000111111111
//  Tui_Xiang_Zi14.txt
080711111111100100011032230115324011103223011001000111111111
//  Tui_Xiang_Zi15.txt
080701111111110000101030330112222221103303011110511100111100
//  Tui_Xiang_Zi16.txt
1009001111110000100001110010300001111030110312220300011222313011111101030100010050010001111111
//  Tui_Xiang_Zi17.txt
0907111111000100001000103331100100122111110022301010500001011111111
//  Tui_Xiang_Zi18.txt
1009001111111100100012010110032221010030142111011310111000300301100010000111111115010000001111
//  Tui_Xiang_Zi19.txt
100801111111000122220100111222311110031303011033001301100001000111110501110001111100
//  Tui_Xiang_Zi20.txt
070811111111223221122122110333011003001103330110015011111111
//  Tui_Xiang_Zi21.txt
11080001111110000010222100111122221001001113011110303003301150303000011000111000111111011111
//  Tui_Xiang_Zi22.txt
0909111111110100000010101330010102221010112223011010110301013003001010010051011111111
//  Tui_Xiang_Zi23.txt
100800111111001110001111100030300110300030511113311111001002210000122221000011111100
//  Tui_Xiang_Zi24.txt
1409111111000111111000011101002110030301012221101003011100211003330003052111100300310021001003130122210011000001002100011111111111
//  Tui_Xiang_Zi25.txt
111000000111111011111200010100122110101003220001010010210111110113100110300003301101310010011500111111111111000000
//  Tui_Xiang_Zi26.txt
1312011111111100001000110011110103000000001011311101100101001104010110103222222010110111020101010000031113101000100003510111113101111000001000100000000111110000
//  Tui_Xiang_Zi27.txt
//  Tui_Xiang_Zi28.txt
//  Tui_Xiang_Zi29.txt
//  Tui_Xiang_Zi30.txt
我不想写了 你们自己搞 下面我会给个网址你们自己去写吧 哎哟喂

大家可以到这个网址去找推箱子的关卡推箱子关卡大全没错就是4399
后面我再写一个专门用作关卡生成的exe 你们就先手动打着 或者改动代码

关卡数据规则

前两位表示x(长) 第3位和第4位表示y(高)后面的数据需要按照这个长和高来定制 5表示玩家 2 表示箱子的目标位置 3表示箱子 4表示箱子是否处于目标位置

思路和建议

其实这不是真正意义上的C语言,而是c++,因为我使用了引用(因为这是我大一的时候写的但是我不想改了引用属实是完全没必要) 但是这里我提供了一些思路
你也可是使用指向指针的指针
关卡可以读取

建议

大家如果打开看的话一定会发现 关卡数是固定的,实际上是我不想写预读取关卡数各位可以根据Tui_Xiang_Zi关卡数.txt这种格式进行一个循环预读取然后重新把到底有多少关渲染上去。

你们仔细的话还会发现一个问题就是第一关我输入01是错的,你们可以写个过滤器

还有一个你们一定觉得这关卡就单纯的看着123450 看起来很打脑壳 自己设置关卡的时候肯定会眼睛晕 建议写一个专门用于添加关卡的程序可以在同目录下生成Tui_Xiang_Zi关卡数.txt文件 (过段时间我会写一个出来 这是今天翻老代码的时候发现了以前写的一个推箱子 )

当然我这雀食有很多不足的地方有些地方的逻辑也没有写好 欢迎大家在评论区留言

警告

原创内容 未经允许请随便转载(梵颜夕表示这很行)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梵颜夕不会发疯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值