鱼C论坛

 找回密码
 立即注册
查看: 1810|回复: 0

[技术交流] C语言,2048游戏文字版,流程逻辑思路,代码详解(上)

[复制链接]
发表于 2021-5-12 15:33:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Stubborn 于 2021-5-12 16:15 编辑

C语言,2048游戏,流程逻辑思路,代码详解(上)



首先,贴上游戏的运行流程图例,以及运行时候的界面


流程.png

界面1.png

界面3.png

界面2.png


// ---------------头文件---------------
#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[16];    // 游戏数据
    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("请选择[1 2 3 4]:");
    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();
}

③部分的话,没有实现不想写了 ,④部分直接使用`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[index];
        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_t  EndTime = 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游戏(中)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-16 02:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表