c语言推箱子小游戏

  • 导包
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>    // 弹出对话框

地图设计

/*
    0: 空地
    1: 目的地   ☆
    2: 墙壁     ■ 
    4: 箱子     ▓
    8: 玩家     ♀
    16: 箱子到达目的地  ★
*/
int map[13][14] = {
    {0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0},
    {0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0},
    {0, 2, 2, 2, 2, 0, 0, 4, 4, 2, 2, 2, 2, 2},
    {0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2},
    {0, 2, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 2},
    {0, 2, 0, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2},
    {2, 2, 2, 2, 4, 2, 2, 0, 0, 0, 0, 0, 0, 2},
    {2, 0, 0, 0, 4, 0, 2, 0, 0, 0, 8, 0, 0, 2},
    {2, 0, 4, 0, 4, 0, 2, 0, 2, 2, 2, 2, 2, 2},
    {2, 2, 0, 0, 4, 0, 2, 0 ,2, 1, 1, 1, 2, 0},
    {0, 2, 0, 2, 0, 0, 0, 0, 0, 1, 1, 1, 2, 0},
    {0, 2, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 2, 0},
    {0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0}
};

存储所有类型为1节点的位置信息, 只要这些节点都被置为16,那么游戏结束
// 目标点

int tarPos[][2] = {
    {9, 9},
    {9, 10},
    {9, 11},
    {10, 9},
    {10, 10},
    {10, 11},
    {11, 8},
    {11, 9},
    {11, 10},
    {11, 11}
};

所需要的变量

char key = 0;   // 存储用户的按键
int row = 0, column = 0;    // 人物在第几行,第几列
int oldType = 0;    // 人物站着的地方原来是什么地面
int oldBoxType = 0; // 箱子站着的地方原来是什么地面 

开始画地图
// 画地图方法

void DrawMap() {
    for (int i = 0; i < sizeof(map) / sizeof(map[0]); i++)
    {
        for (int j = 0; j < sizeof(map[0]) / sizeof(map[0][0]); j++)
        {
            switch (map[i][j])
            {
            case 0:
                printf("  ");
                break;
            case 1:
                printf("☆");
                break;
            case 2:
                printf("■");
                break;
            case 4:
                printf("▓");
                break;
            case 8:
                printf("♀");
                row = i;
                column = j;
                break;
            case 16:
                printf("★");
                break;
            }
        }
        printf("\n");
    }
}

人物和箱子移动的方法,根据传过来的位置信息进行移动

void Move(int r, int c)
{
    if (map[row + r][column + c] != 2)  // 如果前面不是墙壁的话,就可以移动
    {
        if (map[row + r][column + c] == 4 || map[row + r][column + c] == 16)    // 如果遇到箱子的处理办法
        {
            if (map[row + 2 * r][column + 2 * c] != 2 && map[row + 2 * r][column + 2 * c] != 4 && map[row + 2 * r][column + 2 * c] != 16)   // 箱子后面不是墙壁和箱子
            {
                // 移动箱子
                if (map[row + r][column + c] == 16)
                {
                    oldBoxType = 1;
                }
                else if (map[row + r][column + c] == 4)
                {
                    oldBoxType = 0;
                }
                map[row + r][column + c] = oldBoxType;
                if (map[row + 2 * r][column + 2 * c] == 1)
                {
                    map[row + 2 * r][column + 2 * c] = 16;
                }
                else
                {
                    map[row + 2 * r][column + 2 * c] = 4;
                }
            }
            else {
                return; // 如果箱子后面是墙壁,那么停止移动
            }
        }
        map[row][column] = oldType; // 将人物走过的地方设为原来的地面类型
        oldType = map[row + r][column + c]; // 存储人物接下来要走的地方的地面类型
        map[row + r][column + c] = 8;   // 人移动的位置发生变化
    }
}

检查是否完成

void resultCheck()
{
    bool result = true;
    for (int i = 0; i < sizeof(tarPos) / sizeof(tarPos[0]); i++)
    {
        if (map[tarPos[i][0]][tarPos[i][1]] != 16)
        {
            result = false;
        }
    }
    if (result)
    {
        MessageBox(NULL, TEXT("你赢了!!"), TEXT("游戏结束"), MB_OK);
        exit(0);
    }
}

主函数

int main(void)
{
    DrawMap();
    while (true)
    {
        key = _getch();    //_gettch()可以用来监听键盘按键
        switch (key)
        {
        case 'a':
            Move(0, -1);
            break;
        case 'd':
            Move(0, 1);
            break;
        case 'w':
            Move(-1, 0);
            break;
        case 's':
            Move(1, 0);
            break;
        }
        resultCheck();  // 检查是否完成
        system("cls");  // 清空屏幕
        DrawMap();  // 重新画图
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一份带有注释和流程图的 C 语言推箱子小游戏,代码共计约 300 行。 首先是游戏界面和规则的介绍: ```c /* * 推箱子小游戏 * * 游戏规则: * 1. 玩家通过移动可以将箱子推到目标点; * 2. 玩家不能推动箱子穿过墙; * 3. 当所有箱子都被推到目标点时,游戏胜利; * 4. 玩家可以通过菜单选择不同的关卡。 * * 控制说明: * 1. 上下左右键控制玩家移动; * 2. 空格键控制玩家推动箱子; * 3. ESC 键退出游戏。 * * 开发环境:Visual Studio 2019 * 编译命令:gcc main.c -o main -Wall * * 作者:CSDN-开发者头条 * 时间:2021年9月 */ #include <stdio.h> #include <stdlib.h> #include <conio.h> // Windows下的控制台输入输出库 #include <Windows.h> // Windows下的API库 ``` 接下来是一些常量和数据结构的定义,包括地图和玩家的坐标,以及菜单和游戏提示的字符串。 ```c // 地图大小 #define ROW 10 #define COL 16 // 地图元素定义 #define WALL 1 #define BOX 2 #define TARGET 3 // 菜单选项 #define MENU_ITEMS 3 #define MENU_LEVEL 0 #define MENU_HELP 1 #define MENU_QUIT 2 // 游戏状态定义 #define GAME_MENU 0 #define GAME_PLAYING 1 #define GAME_WIN 2 #define GAME_OVER 3 // 游戏提示字符串 #define TIP_MENU "1. 选择关卡 2. 操作说明 3. 退出游戏" #define TIP_LEVEL "请选择关卡:1. 简单 2. 中等 3. 困难" #define TIP_HELP "使用方向键移动,空格键推箱子,ESC键返回" #define TIP_WIN "恭喜你赢得了胜利!" #define TIP_OVER "很遗憾游戏失败了,按ESC键返回菜单" #define TIP_ERROR "输入错误,请重新输入!" // 关卡地图定义 const int levels[3][ROW][COL] = { { // 简单 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1}, {1, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} }, { // 中等 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1}, {1, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} }, { // 困难 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1}, {1, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} } }; ``` 接下来是函数声明和主函数体: ```c // 函数声明 void init_console(); // 初始化控制台 void print_map(int map[ROW][COL]); // 打印地图 void gotoxy(int x, int y); // 光标定位 void clear_input(); // 清空输入缓冲区 void show_menu(); // 显示菜单 void show_level_menu(); // 显示关卡选择菜单 void show_help(); // 显示操作帮助 void show_tip(const char *tip); // 显示提示信息 void play_level(int map[ROW][COL]); // 开始游戏 int check_win(int map[ROW][COL]); // 检查是否胜利 int can_move(int map[ROW][COL], int row, int col, int dir_row, int dir_col); // 检查是否可移动 int move_box(int map[ROW][COL], int row, int col, int dir_row, int dir_col); // 移动箱子 void move_player(int map[ROW][COL], int *row, int *col, int dir_row, int dir_col); // 移动玩家 void play_game(); // 游戏主循环 // 主函数 int main() { init_console(); play_game(); return 0; } ``` 以下是各个函数的实现。 初始化控制台,设置控制台窗口大小和字体大小,以及隐藏控制台光标。 ```c // 初始化控制台 void init_console() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); COORD size = { COL * 2, ROW + 1 }; SMALL_RECT rc = { 0, 0, size.X - 1, size.Y - 1 }; SetConsoleWindowInfo(hOut, TRUE, &rc); SetConsoleScreenBufferSize(hOut, size); CONSOLE_FONT_INFOEX info = { sizeof(CONSOLE_FONT_INFOEX) }; info.dwFontSize.Y = 16; wcscpy_s(info.FaceName, L"Consolas"); SetCurrentConsoleFontEx(hOut, FALSE, &info); CONSOLE_CURSOR_INFO cursor_info = { sizeof(CONSOLE_CURSOR_INFO), FALSE }; SetConsoleCursorInfo(hOut, &cursor_info); } ``` 打印地图,根据不同的元素类型打印不同的字符。 ```c // 打印地图 void print_map(int map[ROW][COL]) { int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { switch (map[i][j]) { case WALL: printf("#"); break; case BOX: printf("$"); break; case TARGET: printf("O"); break; default: printf(" "); break; } printf(" "); } printf("\n"); } printf("\n"); } ``` 光标定位,用于在控制台中移动光标。 ```c // 光标定位 void gotoxy(int x, int y) { COORD pos = { x, y }; HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hOut, pos); } ``` 清空输入缓冲区,用于在控制台中清空输入缓冲区。 ```c // 清空输入缓冲区 void clear_input() { while (_kbhit()) { _getch(); } } ``` 显示菜单,包括关卡选择、帮助和退出游戏。 ```c // 显示菜单 void show_menu() { int selected = 0; // 当前选中项 int ch = 0; // 输入字符 const char *menu_items[MENU_ITEMS] = { TIP_LEVEL, TIP_HELP, "3. 退出游戏" }; while (1) { // 显示菜单项 int i; for (i = 0; i < MENU_ITEMS; i++) { gotoxy(0, i); if (i == selected) { printf(">"); } else { printf(" "); } printf("%s\n", menu_items[i]); } // 处理输入 ch = _getch(); switch (ch) { case 72: // 方向键上 selected--; if (selected < 0) { selected = MENU_ITEMS - 1; } break; case 80: // 方向键下 selected++; if (selected >= MENU_ITEMS) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值