别踩白块儿(C语言+easyx库)

介绍:界面为4*4的矩形,顶部有计数(当前点击数)和计时(当前用时)

玩法:鼠标点击,或者键盘输入DFJK(依次代表横向块顺序),判定位置为从顶部到底部的倒数第二层矩形黑块,点击则向下刷新方块,点击其他位置则游戏结束。

技术栈:C语言、easyx库(图形库)

运行结果:

初始:

游玩一段时间后:

游戏结束:

以下为源码:

#include<stdio.h>
#include<easyx.h> // 图形库,绘制图形,输出文字
#include<stdlib.h>
#include<time.h>
#include<conio.h>
/*
* 别踩白块儿:C语言+easyx
* 宽100,高150
*/

#define INTERVAL 100
#define GRID_W 100
#define GRID_H 150
#define WINDOW_W 400
#define WINDOW_H 700
#define LINESIZE 2

// 定义标志数组,下标代表行,值代表列
int flags[4] = { 0 };
int gCount = 0;
char timeStr[20];
time_t startTime;

void getDot(int i, int* x, int* y)
{
    *x = flags[i] * GRID_W;
    *y = i * GRID_H + INTERVAL;
}
void getTime()
{
    time_t currentTime;
    int hours, minutes, seconds;

    currentTime = time(NULL) - startTime; // 计算经过的秒数
    hours = currentTime / 3600;
    minutes = (currentTime % 3600) / 60;
    seconds = currentTime % 60;
    sprintf_s(timeStr, "%02d:%02d:%02d", hours, minutes, seconds); // 格式化时间
}
void init()
{
    flags[3] = -1;
    for (int i = 1; i < 3; i++)
    {
        flags[i] = rand() % 4;//0,1,2,3
    }
}

void draw()
{
    setlinestyle(PS_SOLID, LINESIZE);
    // 设置线条颜色,默认为白色
    setlinecolor(BLACK);
    getTime();


    for (int i = 0; i < 5; i++)
    {
        line(0, i * GRID_H + INTERVAL, WINDOW_W, i * GRID_H + INTERVAL);
        line(i * GRID_W, INTERVAL, i * GRID_W, WINDOW_H);
    }
    // 修改项目属性字符集为多字节字符集
    settextstyle(38, 0, "Arial");//宽为0,表示自适应
    settextcolor(BLACK);

    char title[30];
    snprintf(title, sizeof(title), "别踩白块儿:%d", gCount); // 直接格式化写入
    int spaceH = (getwidth() - textwidth(title)) / 2;
    int spaceV = (INTERVAL - textheight(title)) / 2;
    outtextxy(spaceH, spaceV, title);
    outtextxy(WINDOW_W - textwidth(timeStr), spaceV - textheight(title), timeStr);

    // 根据flags数组绘制黑块
    setfillcolor(BLACK);
    for (int i = 0; i < 4; i++)
    {
        int x,y;
        getDot(i, &x, &y);
        if (i == 3)
        {
            setfillcolor(RGB(156, 156, 156));
        }
        fillrectangle(x, y, x + GRID_W, y + GRID_H);
    }
}
void updateFlags()
{
    // 更新黑块下移
    for (int i = 3; i > 0; i--)
    {
        flags[i] = flags[i - 1];
    }
    flags[0] = rand() % 4;//0,1,2,3
    gCount++;
    printf("你点中黑块了欸~");
}
bool mousePressMsg(ExMessage* msg)
{
    // 获取下标为2的黑块的坐标
    int x, y;
    getDot(2, &x, &y);
    
    // 判断鼠标点击位置是否在黑块矩形内
    if ((msg->x > x && msg->x < x + GRID_W) && (msg->y > y && msg->y < y + GRID_H))
    {
        updateFlags();
        return true;
    }

    printf("%s\n", __FUNCTION__); // 所在输出函数名
    return false;
}
bool keyDownMsg(int i)
{
    if (flags[2] == i)
    {
        updateFlags();
        return true;
    }
    return false;
}
void gameOver(int width, int heigh)
{
    int spaceH = (getwidth() - width) / 2;
    int spaceV = (getheight() - heigh) / 2;
    setlinecolor(GREEN);
    setfillcolor(RGB(255, 228, 160));
    fillrectangle(spaceH, spaceV, spaceH + width, spaceV + heigh);
    settextstyle(24, 0, "Arial");//宽为0,表示自适应
    const char* title = "游戏结束,重新来过!";
    int textH = (width - textwidth(title)) / 2;
    int textV = (heigh - textheight(title)) / 2;
    outtextxy(spaceH + textH, spaceV + textV, title);
}

void gaming()
{
    ExMessage msg = { 0 }; // 消息结构体
    bool isDone = false;
    startTime = time(NULL); // 获取启动时间戳
    while (!isDone)
    {
        // 绘制
        BeginBatchDraw();//双缓冲
        cleardevice();
        draw();
        EndBatchDraw();
        /*
        * 双缓冲的核心思想:“不要边擦边画,而是全部画好再展示”,从而避免用户看到中间过程。
        * 这就是为什么即使每秒绘制 60 次,画面也不会闪烁的原因。
        */
        if (peekmessage(&msg)) // 判断是否有消息并获取消息
        {
  
            switch (msg.message) 
            {
            case WM_KEYDOWN: // 处理键盘消息
                if (msg.vkcode == VK_ESCAPE) // 如果是esc键,退出游戏
                {
                    isDone = true;
                    printf("已退出游戏!\n");
                }
                // 处理键盘按键
                else if (msg.vkcode == 'D' || msg.vkcode == 'd') 
                {
                    if (!keyDownMsg(0)) isDone = true;
                }
                else if (msg.vkcode == 'F' || msg.vkcode == 'f') 
                {
                    if (!keyDownMsg(1)) isDone = true;
                }
                else if (msg.vkcode == 'J' || msg.vkcode == 'j') 
                {
                    if (!keyDownMsg(2)) isDone = true;
                }
                else if (msg.vkcode == 'K' || msg.vkcode == 'k') 
                {
                    if (!keyDownMsg(3)) isDone = true;
                }
                break;
            case WM_LBUTTONDOWN: // 处理鼠标左键按下消息
                if(!mousePressMsg(&msg))
                {
                    isDone = true;
                }
                break;
            default:
                break;
            }
        }
       
    }
    gameOver(300, 100);

}

int main()
{
    //随机数种子,必须放在函数里面,全局只是声明,不会执行函数调用
    srand(time(NULL));

    // 绘制游戏窗口
    initgraph(WINDOW_W, WINDOW_H, EX_SHOWCONSOLE);
    setbkmode(TRANSPARENT);

    // 设置背景颜色
    setbkcolor(WHITE);
    cleardevice();

    // 初始化
    init();

    //游戏
    gaming();

    getchar();
    return 0;
}

// 后续可能会添加更多模式与玩法,现在的游戏界面确实有点简陋。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

物往fd

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

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

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

打赏作者

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

抵扣说明:

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

余额充值