目录

  • 一、前言
  • 二、游戏运行环境
  • 三、代码实现逻辑
    • 1. game.h
    • 2. game.c
    • 3. test.c
  • 四、总结

一、前言

这是最简单的推箱子了,非常适合初学者。只需要学会一点数组和函数的知识就可以实现。代码的逻辑也不是很难理,就是交换位置。博主实现的推箱子增加了一些花样关卡和颜色,相信很多朋友看完都会受益匪浅。这里我们还是沿用弹跳小球的框架(至于为什么总是沿用这个框架,因为弹跳小球是博主写的第一个小项目,直接搬代码比全部手写快多了),并在原来的框架上增加推箱子所需要的玩法描述。之后加上关卡地图和游戏逻辑就可以实现推箱子啦!先看一下代码的运行效果吧。

二、游戏运行环境

这里就是需要更改一下字符集,否则编译器会报错的。先说报错显示,然后再说更改步骤。这里只讲一种方法。

编译器报错显示:

第一步找到解决方案资源管理器选中你所创建的项目:

第二步:

最后结果:

三、代码实现逻辑

代码逻辑这里是先解释一些难点,然后在附上源码

1. game.h

头文件这里是放一些函数的声明和宏定义。

#pragma once//防止头文件重复包含
#include<stdio.h>
#include<windows.h>
#include<conio.h>#define row 10
#define col 10HANDLE hStdin;//控制台句柄void HideCursor();//隐藏光标函数
int color(int c);//设置颜色
void gotoxy(int x, int y);//设置光标的位置
void prompt();//提示框
void initMap();//加载当前关卡地图
void people_move();//
void IsWin();//胜利判断函数
void draw_map(int arr[row][col],int x,int y);//打印地图
void play_game();//开始游戏
void game_help();//游戏帮助
void update();//更新日志
void showmenu();//游戏菜单

2. game.c

这里放的是代码的实现逻辑,这里需要讲的就是人物推箱子的逻辑。其他的包括地图设计和胜负判断看代码应该都不难理解。 人物推箱子逻辑就是让这两个位置交换嘛,下面用图来帮助理解。

实现的代码:

void people_move()//判断人物移动代码
{int x1 = 0;int y1 = 0;for (int i=0;i<row;i++){for (int j=0;j<col;j++){if (2==map[i][j]||6==map[i][j]){x1 = j;y1 = i;}}}switch (_getch()){case 'w':case 'W'://上case 72:if (0==map[y1-1][x1]||4==map[y1-1][x1]){map[y1][x1] -= 2;map[y1 - 1][x1] += 2;}else if (3==map[y1-1][x1]||7== map[y1 - 1][x1]){if (0==map[y1 - 2][x1]||4==map[y1-2][x1]){map[y1][x1] -= 2;map[y1 - 1][x1] -= 1;map[y1 - 2][x1] += 3;}}break;case 's':case 'S'://下case 80:if (0 == map[y1 + 1][x1] || 4 == map[y1 + 1][x1]){map[y1][x1] -= 2;map[y1 + 1][x1] += 2;}else if (3 == map[y1 + 1][x1] || 7 == map[y1 + 1][x1]){if (0 == map[y1 +2][x1] || 4 == map[y1 + 2][x1]){map[y1][x1] -= 2;map[y1 + 1][x1] -= 1;map[y1 +2][x1] += 3;}}break;case 'a'://左case 'A':case 75:if (0==map[y1][x1-1]||4==map[y1][x1-1]){map[y1][x1] -= 2;map[y1][x1 - 1] += 2;}else if (3 == map[y1][x1 - 1] || 7 == map[y1][x1 - 1]){if (0 == map[y1][x1 - 2] || 4 == map[y1][x1 - 2]){map[y1][x1] -= 2;map[y1][x1 - 1] -= 1;map[y1][x1 - 2] += 3;}}break;case 'd':case 'D'://右case 77:if (0 == map[y1][x1 + 1] || 4 == map[y1][x1 + 1]){map[y1][x1] -= 2;map[y1][x1 + 1] += 2;}else if (3 == map[y1][x1 + 1] || 7 == map[y1][x1 + 1]){if (0 == map[y1][x1 + 2] || 4 == map[y1][x1 + 2]){map[y1][x1] -= 2;map[y1][x1 + 1] -= 1;map[y1][x1 + 2] += 3;}}break;case 27://ESCsystem("cls");exit(0);break;}}

这里为了实现关卡地图,用到了三维数组来储存地图。这里好像并没有啥好讲的,就是每次开始游戏的时候需要在主函数调用一次加载关卡函数就完了。level是我定义的全局变量,用来表示当前到了第几关。我这里只实现了三关。想要实现更多关卡的话可以自己实现。

//加载当前关卡地图
void initMap()
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){map[i][j] = Map3[level-1][i][j];}}
}

这里的胜负判断比较简单,就是判断当前地图上没有箱子就是胜利!并加载下一关。

//胜利判断函数
void IsWin()
{//如果整个地图中没有箱子则通过此关卡for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (map[i][j] == 3){ //如果在地图中发现一个箱子则判断为此关卡为不通过return;}}}color(15);printf("游戏胜利!\n");system("pause"); //暂停窗口if (level<3){level++; //通过当前关卡后,进入下一关initMap(); //并加载下一关的地图system("cls");}else{color(12);system("cls");exit(0); //退出程序}
}

游戏源码:

#include"game.h"/*******************************************
*
* @数字0表示空地
* @数字1表示墙
* @数字2表示人物
* @数字3表示箱子
* @数字4表示终点
* @数字6表示人物到达终点
* @数字7表示箱子到达终点
*
********************************************/
int Map3[3][row][col] =
{{ //第一关0, 0, 0, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 0, 0, 0, 0, 0, 1,1, 0, 0, 0, 0, 4, 0, 2, 0, 1,1, 0, 0, 0, 3, 3, 3, 0, 0, 1,1, 0, 4, 1, 1, 4, 1, 1, 4, 1,1, 0, 0, 0, 0, 0, 0, 0, 0, 1,1, 0, 0, 0, 0, 3, 0, 0, 0, 1,1, 0, 0, 3, 0, 4, 0, 0, 0, 1,1, 1, 1, 1, 0, 0, 0, 0, 1, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 0,},{ //第二关0, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 4, 0, 0, 0, 4, 4, 1, 0,0, 1, 4, 0, 0, 0, 3, 4, 1, 0,1, 1, 1, 0, 0, 0, 0, 3, 1, 1,1, 0, 0, 0, 0, 0, 0, 0, 0, 1,1, 0, 3, 0, 0, 0, 0, 3, 0, 1,1, 0, 1, 1, 3, 1, 1, 1, 0, 1,1, 0, 0, 0, 0, 0, 0, 0, 0, 1,1, 0, 0, 0, 0, 2, 0, 0, 0, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},{ //第三关1, 1, 1, 1, 1, 1, 1, 1, 1, 0,1, 0, 4, 4, 1, 0, 0, 0, 1, 1,1, 0, 0, 0, 1, 0, 0, 0, 0, 1,1, 0, 0, 0, 3, 0, 3, 0, 0, 1,1, 0, 0, 0, 1, 0, 0, 0, 0, 1,1, 1, 3, 0, 1, 0, 0, 0, 0, 1,1, 1, 4, 0, 4, 0, 1, 4, 0, 1,1, 1, 1, 1, 3, 3, 1, 1, 1, 1,0, 0, 0, 1, 0, 2, 1, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 0, 0, 0,}
};
int map[row][col] = { 0 };
int level = 1; //记录当前关卡,默认为第1关void HideCursor()//隐藏光标函数
{CONSOLE_CURSOR_INFO cursor;cursor.bVisible = FALSE;cursor.dwSize = sizeof(cursor);HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorInfo(handle, &cursor);
}
void gotoxy(int x, int y)    //设置光标的位置
{     COORD c;    c.X=x-1;  c.Y=y-1;     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
int color(int c)//设置颜色
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);return 0;//改变颜色的函数
}
void prompt()
{gotoxy(21, 1);color(15);printf("||------------------||\n");gotoxy(21, 2);printf("||   提       示    ||\n");gotoxy(21, 3);printf("||                  ||\n");gotoxy(21, 4);printf("||①按wasd或↑←↓→||\n");gotoxy(21, 5);printf("|| 可以移动人物方向 ||\n");gotoxy(21, 6);printf("||                  ||\n");gotoxy(21, 7);printf("||②退出请按ESC     ||\n");gotoxy(21, 8);printf("||                  ||\n");gotoxy(21, 9);printf("||③当前关卡为第  关||\n");gotoxy(21, 10);printf("||                  ||\n");gotoxy(21, 11); printf("||④祝您游戏愉快!  ||\n");gotoxy(21, 12);printf("||                  ||\n");gotoxy(21, 13);printf("||------------------||\n");color(12);gotoxy(38, 9);printf("%d", level);gotoxy(21, 13);printf("\n");
}//加载当前关卡地图
void initMap()
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){map[i][j] = Map3[level-1][i][j];}}
}
void people_move()
{int x1 = 0;int y1 = 0;for (int i=0;i<row;i++){for (int j=0;j<col;j++){if (2==map[i][j]||6==map[i][j]){x1 = j;y1 = i;}}}switch (_getch()){case 'w':case 'W':case 72:if (0==map[y1-1][x1]||4==map[y1-1][x1]){map[y1][x1] -= 2;map[y1 - 1][x1] += 2;}else if (3==map[y1-1][x1]||7== map[y1 - 1][x1]){if (0==map[y1 - 2][x1]||4==map[y1-2][x1]){map[y1][x1] -= 2;map[y1 - 1][x1] -= 1;map[y1 - 2][x1] += 3;}}break;case 's':case 'S':case 80:if (0 == map[y1 + 1][x1] || 4 == map[y1 + 1][x1]){map[y1][x1] -= 2;map[y1 + 1][x1] += 2;}else if (3 == map[y1 + 1][x1] || 7 == map[y1 + 1][x1]){if (0 == map[y1 +2][x1] || 4 == map[y1 + 2][x1]){map[y1][x1] -= 2;map[y1 + 1][x1] -= 1;map[y1 +2][x1] += 3;}}break;case 'a':case 'A':case 75:if (0==map[y1][x1-1]||4==map[y1][x1-1]){map[y1][x1] -= 2;map[y1][x1 - 1] += 2;}else if (3 == map[y1][x1 - 1] || 7 == map[y1][x1 - 1]){if (0 == map[y1][x1 - 2] || 4 == map[y1][x1 - 2]){map[y1][x1] -= 2;map[y1][x1 - 1] -= 1;map[y1][x1 - 2] += 3;}}break;case 'd':case 'D':case 77:if (0 == map[y1][x1 + 1] || 4 == map[y1][x1 + 1]){map[y1][x1] -= 2;map[y1][x1 + 1] += 2;}else if (3 == map[y1][x1 + 1] || 7 == map[y1][x1 + 1]){if (0 == map[y1][x1 + 2] || 4 == map[y1][x1 + 2]){map[y1][x1] -= 2;map[y1][x1 + 1] -= 1;map[y1][x1 + 2] += 3;}}break;case 27:system("cls");exit(0);break;}
}
void draw_map(int arr[row][col], int x, int y)//打印地图
{for (int i=0;i<x;i++){for (int j=0;j<y;j++){if (1 == arr[i][j]){color(9);printf("■");}else if (2 == arr[i][j]){color(10);printf("♀");}else if (3 == arr[i][j]){color(14);printf("■");}else if (4 == arr[i][j]){color(13);printf("★");}else if (6 == arr[i][j]){color(10);printf("♀");}else if (7 == arr[i][j]){color(12);printf("●");}else{printf("  ");}}printf("\n");}
}
//胜利判断函数
void IsWin()
{//如果整个地图中没有箱子则通过此关卡for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (map[i][j] == 3){ //如果在地图中发现一个箱子则判断为此关卡为不通过return;}}}color(15);printf("游戏胜利!\n");system("pause"); //暂停窗口if (level<3){level++; //通过当前关卡后,进入下一关initMap(); //并加载下一关的地图system("cls");}else{color(12);system("cls");exit(0); //退出程序}
}void play_game()
{HideCursor();while (1){gotoxy(1, 1);draw_map(map,row,col);prompt();people_move(map, row, col);gotoxy(1, 1);draw_map(map, row, col);prompt();IsWin(); }
}
static void game_help_menu()//游戏帮助菜单
{printf("\n");printf("游戏操作:\n");printf("\n");printf("①:按w a s d 或 ↑ ←↓ →\n");printf("\n");printf("  可以上下左右控制箱子\n");printf("\n");printf("\n");printf("\n");printf("(按1返回,按任意键退出)\n");printf("请选择:>");
}
void game_help()//游戏帮助
{game_help_menu();switch (_getch()){case '1':break;default:exit(0);break;}
}
static void update_menu()//更新日志菜单
{printf("(暂无)\n");printf("\n");printf("\n");printf("\n");printf("(按1返回,按任意键退出)\n");printf("请选择:>");
}
void update()//更新日志
{update_menu();switch (_getch()){case '1':break;default:exit(0);break;}
}
void showmenu()//游戏菜单
{printf("|----------------------|\n");printf("|      1.开始游戏      |\n");printf("|----------------------|\n");printf("|      2.游戏帮助      |\n");printf("|----------------------|\n");printf("|      3.更新日志      |\n");printf("|----------------------|\n");printf("|      0.退出游戏      |\n");printf("|----------------------|\n");printf("\n");printf("(温馨提醒:请按照菜单相应的选项选择)");printf("\n");printf("请输入你的选择:>");
}

3. test.c

这里主要实现一些函数的调用。

#include"game.h"int main()
{SetConsoleTitle("推箱子游戏");//控制台窗口菜单栏上的字system("mode con cols=42 lines=16");//控制台的大小,这里可以按需要自己设置initMap();do{system("cls");showmenu();switch (_getch()){case'1':system("cls");play_game();//开始游戏break;case'2':system("cls");game_help();//游戏帮助break;case'3':system("cls");update();//更新日志break;case'0':exit(0);//退出游戏break;}} while ('0');return 0;
}

四、总结

推箱子实现还是很简单。也能知道前面学好框架有多重要。

C语言小游戏快速入门--推箱子相关推荐

  1. C语言小游戏快速入门--弹跳小球

    目录 一.前言 二.弹跳小球的实现 2.1.界面设置 2.2.弹跳逻辑 1. game.h 2. game.c 3. test.c 三.总结 一.前言 相信很多小伙伴在学习完C语言语法之后就想要做几个 ...

  2. C语言小游戏快速入门--三子棋

    目录 一.前言 二.游戏界面 三.游戏逻辑 1.game.h 2.game.c 3.test.c 四.总结 一.前言 这是一个非常简单的三子棋小游戏,学过C语言数组语法的就可以写出来.在这里博主实现的 ...

  3. PLC也能制作小游戏----Codesys编写推箱子小游戏

    1.序言 前文已介绍,Codesys编程软件拥有的各种编译方式,以及强大的可视化功能,完全可以实现类似的小游戏程序编写,让疲惫的工控人员在调机的空闲之余可以休闲下,本文编写另一个小游戏,也是十几年前的 ...

  4. c#推箱子小游戏代码_推箱子小游戏V1.0制作

    小游戏实践 推箱子简易版 大家好,我是努力学习争取成为优秀的Game Producer的路人猿,今天来一起做一个推箱子的简易版本V1.0!下面跟我一起做吧~ 我们用到的软件如下: 编辑类 Visual ...

  5. c#推箱子小游戏代码_C# 推箱子游戏源码(带音效/关卡)

    C# 推箱子游戏源码(带音效/关卡) c# 2021-1-29 下载地址 https://www.codedown123.com/62444.html Vs2010 FrameWork 4.0 具有音 ...

  6. Android开发入门——推箱子游戏开发实战(十二)

    绘制游戏局面 本文是推箱子游戏程序开发的第七步.系列文章前五篇描述准备工作,故本文编号是(十二).本文讲解如何绘制游戏局面. 本文目标 本文讲解如何绘制游戏局面.游戏局面的示例如图1,图2所示.这两幅 ...

  7. C语言100行代码实现推箱子

    1 C语言100行代码实现推箱子 1.1 概述  C语言是很好入门编程的一个语言,它拥有着很好的移植性,基本上所有的平台都支持C语言编程.有些C语言基础的你,是不是也很想做一个项目来检验一下自己的学习 ...

  8. c语言小游戏vc,C语言探索之旅:第一个C语言小游戏

    C语言探索之旅:第一个C语言小游戏-1.jpg (37.05 KB, 下载次数: 0) 2018-10-8 19:23 上传 内容简介 1.课程纲领 2.第一部分第八课:第一个C语言小游戏 3.第一部 ...

  9. Dart语言——45分钟快速入门(下)

    类和对象 类的定义 // Dart中定义一个类 class Person {String name;int age;Person(String name, int age) {this.name = ...

最新文章

  1. DeepMind发布最新原始音频波形深度生成模型WaveNet,将为TTS带来无数可能
  2. Centos7解决图形界面卡死问题
  3. Qt程序打包发布方法(使用官方提供的windeployqt工具)
  4. 区分基于Ant目标的Gradle任务
  5. JAVA入门级教学之(classpath的配置)
  6. mysql实验步骤_MySQL双方配置实验步骤
  7. 谷歌浏览器调用本地exe_无需修改前端和后端代码本地跨域开发设置
  8. r语言清除变量_R语言:结构方程模型、潜变量分析
  9. 关于异常的合理处理方式
  10. 从张一鸣和黄峥的离职信中,我们发现了四个共同点
  11. 微信小程序教程笔记2
  12. 【资料分享】STM32配置TB6612驱动程序详解
  13. Fast-Paced Multiplayer (Part I): Introduction
  14. 微信小程序实现星星评分
  15. 黑马程序员—String类常用方法
  16. python使用pyecharts库画地图数据可视化
  17. vector<vector>排序
  18. ios app硬脱壳之前查看加密方式的方法
  19. Cesium 叠加矢量数据(路网、水系等)
  20. 入门--什么是机器码、注册机和注册码

热门文章

  1. Flash Pro CS5无法跳过注册Adobe ID的问题
  2. 【学习笔记】薛定谔的喵咪Cat—球盒问题(全详解)
  3. 计算机算法设计与分析 动态规划 实验报告,动态规划法解最长公共子序列(计算机算法设计与分析实验报告).doc...
  4. 看用友网络如何应对“后地产时代”的去化与创新
  5. 一文读懂算力内涵和发展框架
  6. 需求预测——Coupled Layer-wise Graph Convolution for Transportation Demand Prediction
  7. java基于微信小程序的四六级英语学习测试系统 uinapp 计算机毕业设计
  8. mac os 安装rz/sz
  9. 龙尚3G、4G模块嵌入式Linux系统使用说明【转】
  10. 爱国者回应MID过渡平台性能仍基于Menlow