C语言,2048游戏文字版,流程逻辑思路,代码详解(上)
本帖最后由 Stubborn 于 2021-5-12 16:15 编辑C语言,2048游戏,流程逻辑思路,代码详解(上)
首先,贴上游戏的运行流程图例,以及运行时候的界面
// ---------------头文件---------------
#include "stdbool.h"
#include <stdio.h>
#include "stdlib.h"
#include "time.h"
#include "conio.h"
#include <windows.h>
struct Game{
size_t length;
short arr; // 游戏数据
size_t move; //已执行步数
size_t score; //存储游戏分数
size_t max; //合并的最大值
time_t StartTime; //游戏运行时间
};
/*******函数声明*******/
/*******功 能 函 数*******/
void GetCursorPosition(short, short);//获取屏幕光标位置
int SetTypefaceColor(short); //设置文字颜色
int randint(size_t); //返回一个随机值
/*******绘 制 相 关 函 数*******/
void DrawTitle(); //绘制标题2048
void DrawGameGuide(); //绘制游戏引导
void DrawTheGameBox(struct Game); //绘制游戏界面
void DrawKeyRule(); //绘制游戏规则以及按键说明
int DrawNumbersColor(int); //绘制数字颜色
int DrawWin(struct Game); // 绘制胜利界面
int DrawLoser(struct Game *); // 绘制失败界面
int _Loser(struct Game);
/*******游 戏 逻 辑 函 数*******/
void StartGame(); //开始游戏
bool JudgmentInput(int, struct Game *); //判断键盘操作是否在可执行范围内
bool GeneratingRandomNumbers(struct Game *); //随机在在Game.arr里产生一个数字
bool _MoveUp(struct Game *);
bool MoveUp(struct Game *); // 上下左右移动操作
bool _MoveLeft(struct Game *);
bool MoveLeft(struct Game *);
bool _MoveRight(struct Game *);
bool MoveRight(struct Game *);
bool _MoveDown(struct Game *);
bool MoveDown(struct Game *);
int main(){
DrawGameGuide();
return 0;
}
void GetCursorPosition(short x, short y){
/*获取屏幕光标位置,从某个特定位置打印字符*/
COORD coo = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coo);
}
int SetTypefaceColor(short c) {
/*设置字体颜色*/
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
return 0;
}
以上是关于一些头文件,和系统函数。正文开始。
首先就是实现流程图中①的部分了。由于只是绘制,所以没有什么逻辑可言,依照自己风格绘制即可。
①-void DrawTitle();绘制一个2048的标题
void DrawTitle(){
/*输出2048字符画*/
system("cls");
SetTypefaceColor(11); //浅淡绿色
GetCursorPosition(19, 2);
printf("■■■ ■■■■ ■■ ■■■■");
GetCursorPosition(19, 3);
printf(" ■ ■ ■ ■■ ■ ■");
GetCursorPosition(19, 4);
printf("■■■ ■ ■ ■■ ■■■■");
GetCursorPosition(19, 5);
printf("■ ■ ■ ■■■■ ■ ■");
GetCursorPosition(19, 6);
printf("■■■ ■■■■ ■ ■■■■");
}
①-DrawGameGuide;绘制整个的游戏欢迎界面。注意switch 分哪里,此时具体函数未实现,可以不调用函数,等实现之后在修改。
void DrawGameGuide(){
system("cls");
DrawTitle();
int n;
GetCursorPosition(32, 8);
SetTypefaceColor(13);
printf("挑 战 2048");
SetTypefaceColor(14);
for (short k = 9; k < 21; k++) {
for (short l = 15; l < 61; l++) {
GetCursorPosition(l, k);
if (k == 9 || k == 20)printf("=");
else if (l == 15 || l == 60)printf("||");
}
}
SetTypefaceColor(12); //红色字体
GetCursorPosition(25, 12); //设置显示位置
printf("1.开始游戏");
GetCursorPosition(40, 12);
printf("2.游戏规则");
GetCursorPosition(25, 16);
printf("3.挑战模式");
GetCursorPosition(40, 16);
printf("4.退出");
GetCursorPosition(21, 22);
SetTypefaceColor(5); //深紫色字体
printf("请选择:");
scanf("%d", &n);
switch (n) { //分支选择
case 1: //输入数字“1”
StartGame();
break;
case 2: //输入数字“2”
DrawKeyRule();
break;
case 3: //输入数字“3”
system("cls");
GetCursorPosition(20,12);
printf("挑战模式未实现,没有version.2.0\n");
GetCursorPosition(20,16);
printf(" ̄へ ̄\tQAQ\n");
GetCursorPosition(20,22);
printf("按任意键返回欢迎界面");
getch();
system("cls");
DrawGameGuide();
case 4: //输入数字“4”
exit(0); //退出游戏
}
}
现在①部分的欢迎界面都编写完成,开始编写②部分绘制函数
void DrawKeyRule(){
int i,j = 1;
system("cls");
SetTypefaceColor(13);
GetCursorPosition(34,3);
printf("游戏规则");
SetTypefaceColor(2);
for (i = 6; i <= 18; i++) //输出上下边框===
{
for (j = 15; j <= 70; j++)//输出左右边框||
{
GetCursorPosition(j, i);
if (i == 6 || i == 18) printf("=");
else if (j == 15 || j == 69) printf("||");
}
}
SetTypefaceColor(3);
GetCursorPosition(18,7);
printf("tip1: 玩家可以通过↑ ↓ ← →方向键来移动方块");
SetTypefaceColor(10);
GetCursorPosition(18,9);
printf("tip2: 按ESC退出游戏");
SetTypefaceColor(14);
GetCursorPosition(18,11);
printf("tip3: 玩家选择的方向上,若有相同的数字则合并");
SetTypefaceColor(11);
GetCursorPosition(18,13);
printf("tip4: 每移动一步,空位随机出现一个2或4");
SetTypefaceColor(4);
GetCursorPosition(18,15);
printf("tip5: 棋盘被数字填满,无法进行有效移动,游戏失败");
SetTypefaceColor(5);
GetCursorPosition(18,17);
printf("tip6: 棋盘上出现2048,游戏胜利。按任意键返回主界面");
getch(); //按任意键返回欢迎界面
system("cls");
DrawGameGuide();
}
③部分的话,没有实现不想写了{:10_250:} ,④部分直接使用`exit(0); `退出即可
⑤部分的绘制游戏界面代码如下
void DrawTheGameBox(struct Game data){
/**The game interface includes score time and game content*/
system("cls");
SetTypefaceColor(14);
/// 打印4 x 4棋盘
for (int i = 2; i < 22; i+=5) {
int n = 4, j=i;
GetCursorPosition(15,i);
printf("-----------------------------------------");
while (n!=0){
j += 1;
GetCursorPosition(15,j);
printf("| | | | | ");
n -=1;
}
}
GetCursorPosition(15,22);
printf("-----------------------------------------");
/// 打印data.arr数据
for (size_t index = 0; index < data.length; ++index) {
size_t value = data.arr;
if ( value == 0){
continue;
}
short x = (short)index/4;
short y = (short)index%4;
GetCursorPosition(20 + y*10, 5 + x*5);
DrawNumbersColor(value);
printf("%d", value);
}
/// 打印游戏数据,分数,执行步数,耗时
GetCursorPosition(16,1);
SetTypefaceColor(11);
printf("游戏分数: %d",data.score);
SetTypefaceColor(13);
GetCursorPosition(42,1);
printf("执行步数: %d\n",data.move);
GetCursorPosition(44,23);
SetTypefaceColor(10);
time_tEndTime = time(NULL);
printf("已用时:%f s", difftime(EndTime,data.StartTime));
GetCursorPosition(20,26);
SetTypefaceColor(13);
printf("①、↑、↓、←、→方向键进行游戏操作!");
GetCursorPosition(20, 28);
printf("②、ESC键退出游戏");
}
⑤void StartGame();函数部分,这里稍微说一下,为什么从void DrawGameGuide(); 函数中跳转到StartGame的原因。而不是直接跳到绘制游戏DrawTheGameBox函数。首先,我们的绘制函数会在每一次操作后,跟新游戏状态。也是就说DrawTheGameBox应该只是一个单纯的绘制游戏界面函数,不应该有 其他的功能。其次我们重新开始一次新的游戏,游戏数据也应该重置。
void StartGame(){
/**Start the game, run the logic of the game
* */
bool True = true;
struct Game data= {16, {0}, 0, 0, 0, time(NULL)};
struct Game *p = &data;
GeneratingRandomNumbers(p);
DrawTheGameBox(data);
}
以上就是关于绘制函数的实现,还有胜利和失败的游戏界面,在后面会继续介绍到。下一贴介绍游戏的主逻辑
2048游戏(中)
页:
[1]