基于EasyX和Raylib的十字消除
基于 EasyX
// 根据《C和C++游戏趣味编程》第10章 十字消除 写出
#include <graphics.h>
#include <conio.h> // _kbhit()
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Block
{
// 小方块在画面中的 x,y 坐标
int x;
int y;
// 小方块在二维数组中的 i,j 下标
int i;
int j;
int colorId; // 对应颜色的下标
};
// 全局变量
#define WIDTH 21
#define HEIGHT 13
#define BLOCK_SIZE 40
Block blocks[HEIGHT][WIDTH];
#define ColorTypeNum 9 // 方块颜色为彩色的个数. 第0种为灰色,其他为彩色
COLORREF colors[ColorTypeNum + 1]; // 颜色数组,小方块可能的几种颜色
float maxTime; // 游戏允许的总时长
float remainTime; // 游戏剩余时长
void startup()
{
int height = BLOCK_SIZE * (HEIGHT + 1);
maxTime = 200;
remainTime = maxTime;
colors[0] = RGB(220, 220, 220);
for (int i = 1; i < ColorTypeNum + 1; i++)
{
colors[i] = HSVtoRGB((i-1) * 40, 0.6, 0.8);
}
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
blocks[i][j].x = j * BLOCK_SIZE;
blocks[i][j].y = i * BLOCK_SIZE;
blocks[i][j].i = i;
blocks[i][j].j = j;
int t = rand() % ((int)(ColorTypeNum * 1.5));
if (t < ColorTypeNum + 1)
{
blocks[i][j].colorId = t;
}
else
{
blocks[i][j].colorId = 0; // 生成更多的空白方块
}
}
}
initgraph(WIDTH * BLOCK_SIZE, (HEIGHT + 1) * BLOCK_SIZE, SHOWCONSOLE);
setbkcolor(RGB(150, 150, 150));
setfillcolor(RGB(255, 0, 0));
setlinestyle(PS_SOLID, 2);
cleardevice();
BeginBatchDraw();
}
// 对于 blocks[i][j], 绘制一个颜色为 color, isfill 填充冲的提示方块
void drawBlockHint(int i, int j, COLORREF color, int isfill)
{
setlinecolor(color);
setfillcolor(color);
if (isfill == 1)
{
fillrectangle(blocks[i][j].x, blocks[i][j].y, blocks[i][j].x + BLOCK_SIZE,
blocks[i][j].y + BLOCK_SIZE);
}
if (isfill == 0)
{
rectangle(blocks[i][j].x, blocks[i][j].y,
blocks[i][j].x + BLOCK_SIZE, blocks[i][j].y + BLOCK_SIZE);
}
}
void show()
{
cleardevice();
setlinecolor(RGB(255, 255, 255));
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
setfillcolor(colors[blocks[i][j].colorId]);
fillrectangle(blocks[i][j].x, blocks[i][j].y,
blocks[i][j].x + BLOCK_SIZE, blocks[i][j].y + BLOCK_SIZE
);
}
}
setlinecolor(RGB(255, 0, 0));
setfillcolor(RGB(255, 0, 0));
fillrectangle(0, BLOCK_SIZE * (HEIGHT + 0.2),
remainTime * BLOCK_SIZE * WIDTH / maxTime, BLOCK_SIZE * (HEIGHT + 0.8));
FlushBatchDraw();
}
void updateWithoutInput()
{
static clock_t start = clock();
clock_t now = clock();
double duration = (double(now - start) / CLOCKS_PER_SEC);
remainTime = maxTime - duration;
}
void updateWithInput()
{
MOUSEMSG m;
if (MouseHit())
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN)
{
// 通过鼠标位置计算出点击的小方块在二维数组中的下标
int clicked_i = (int)m.y / BLOCK_SIZE;
int clicked_j = (int)m.x / BLOCK_SIZE;
// 对于不是灰色的方块, 判定鼠标点击为无效
if (blocks[clicked_i][clicked_j].colorId != 0)
{
return;
}
show();
drawBlockHint(clicked_i, clicked_j, RGB(100, 100, 100), 1);
// 定义数组, 存储上下左右4个方向找到的第一个不是空白的方块
blocks[clicked_i][clicked_j].colorId = 0;
Block fourBlocks[4] = { blocks[clicked_i][clicked_j] };
// 向上寻找
int search;
for (search = 0; clicked_i - search >= 0; search++)
{
if (blocks[clicked_i - search][clicked_j].colorId != 0)
{
fourBlocks[0] = blocks[clicked_i - search][clicked_j];
break;
}
}
// 向下寻找
for (search = 0; clicked_i + search < HEIGHT; search++)
{
if (blocks[clicked_i + search][clicked_j].colorId != 0)
{
fourBlocks[1] = blocks[clicked_i + search][clicked_j];
break;
}
}
// 向左寻找
for (search = 0; clicked_j - search >= 0; search++)
{
if (blocks[clicked_i][clicked_j - search].colorId != 0)
{
fourBlocks[2] = blocks[clicked_i][clicked_j - search];
break;
}
}
// 向右寻找
for (search = 0; clicked_j + search < WIDTH; search++)
{
if (blocks[clicked_i][clicked_j + search].colorId != 0)
{
fourBlocks[3] = blocks[clicked_i][clicked_j + search];
break;
}
}
// 统计 fourBlocks 中的颜色出现次数, 如果某个颜色出现 >= 2次,则“消除”(修改为灰色)
int colorStatistics[ColorTypeNum + 1] = { 0 };
for (int i = 1; i <= ColorTypeNum; i++)
{
// 遍历 fourBlocks
for (int j = 0; j < 4; j++)
{
if (fourBlocks[j].colorId == i)
{
colorStatistics[i]++;
}
}
if (colorStatistics[i] >= 2)
{
for (int j = 0; j < 4; j++)
{
if (fourBlocks[j].colorId == i)
{
drawBlockHint(fourBlocks[j].i, fourBlocks[j].j, RGB(0, 0, 0), 0);
blocks[fourBlocks[j].i][fourBlocks[j].j].colorId = 0;
}
}
}
}
FlushBatchDraw(); // 批量绘制
Sleep(300); // 绘制好提示框后暂停300毫秒
}
}
}
int main()
{
startup();
while (1)
{
show();
updateWithInput();
updateWithoutInput();
}
closegraph();
return 0;
}
基于 Raylib
// 根据《C和C++游戏趣味编程》第10章 十字消除 写出
#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include "raylib_helper.hpp"
#include <time.h>
struct Block
{
// 小方块在画面中的 x,y 坐标
int x;
int y;
// 小方块在二维数组中的 i,j 下标
int i;
int j;
int fillColorId; // 对应颜色的下标
int borderColorId; // 边框颜色
};
// 全局变量
#define WIDTH 21
#define HEIGHT 13
#define BLOCK_SIZE 40
Block blocks[HEIGHT][WIDTH];
#define ColorTypeNum 9 // 方块颜色为彩色的个数. 第0种为灰色,其他为彩色
Color colors[1 + ColorTypeNum + 1 + 2]; // 灰色, 彩色, 选中空白框的黑色, 边框白色, 边框黑色
#define CLICKED_ID (ColorTypeNum + 1)
#define BORDER_ID (ColorTypeNum + 2)
#define ELIMINATED_ID (ColorTypeNum + 3)
int frameCount = 5;
int clicked_i = 0;
int clicked_j = 0;
int colorStatistics[ColorTypeNum + 1] = { 0 };
Block fourBlocks[4];
float maxTime; // 游戏允许的总时长
float remainTime; // 游戏剩余时长
void startup()
{
maxTime = 200;
remainTime = maxTime;
colors[0] = make_color(220, 220, 220, 255);
for (int i = 1; i < ColorTypeNum + 1; i++)
{
colors[i] = ColorFromHSV((i-1) * 40, 0.6, 0.8);
}
colors[ColorTypeNum + 1] = make_color(100, 100, 100, 255);
colors[ColorTypeNum + 2] = make_color(255, 255, 255, 255);
colors[ColorTypeNum + 3] = make_color(0, 0, 0, 255);
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
blocks[i][j].x = j * BLOCK_SIZE;
blocks[i][j].y = i * BLOCK_SIZE;
blocks[i][j].i = i;
blocks[i][j].j = j;
int t = rand() % ((int)(ColorTypeNum * 1.5));
if (t < ColorTypeNum + 1)
{
blocks[i][j].fillColorId = t;
}
else
{
blocks[i][j].fillColorId = 0; // 生成更多的空白方块
}
blocks[i][j].borderColorId = BORDER_ID;
}
}
InitWindow(WIDTH * BLOCK_SIZE, (HEIGHT + 1) * BLOCK_SIZE, "Eliminate Cross");
SetTargetFPS(60);
}
void show()
{
BeginDrawing();
{
ClearBackground(make_color(150, 150, 150, 255));
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
DrawRectangle(blocks[i][j].x, blocks[i][j].y, BLOCK_SIZE, BLOCK_SIZE, colors[blocks[i][j].fillColorId]);
DrawRectangleLines(blocks[i][j].x, blocks[i][j].y, BLOCK_SIZE, BLOCK_SIZE, colors[blocks[i][j].borderColorId]);
}
}
DrawRectangle(0, BLOCK_SIZE * (HEIGHT + 0.2), remainTime * BLOCK_SIZE * WIDTH / maxTime, BLOCK_SIZE * (HEIGHT + 0.8), make_color(255, 0, 0, 255));
}
EndDrawing();
}
void updateWithoutInput()
{
static clock_t start = clock();
clock_t now = clock();
double duration = (double(now - start) / CLOCKS_PER_SEC);
remainTime = maxTime - duration;
}
void updateWithInput()
{
frameCount++;
if (frameCount > 18)
{
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
if (blocks[i][j].fillColorId == CLICKED_ID)
{
blocks[i][j].fillColorId = 0;
}
if (blocks[i][j].borderColorId == ELIMINATED_ID)
{
blocks[i][j].fillColorId = 0;
}
blocks[i][j].borderColorId = BORDER_ID;
}
}
if (!IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
return;
Vector2 pos = GetMousePosition();
// 通过鼠标位置计算出点击的小方块在二维数组中的下标
clicked_i = (int)pos.y / BLOCK_SIZE;
clicked_j = (int)pos.x / BLOCK_SIZE;
// 对于不是灰色的方块, 判定鼠标点击为无效
if (blocks[clicked_i][clicked_j].fillColorId != 0)
{
return;
}
// 定义数组, 存储上下左右4个方向找到的第一个不是空白的方块
blocks[clicked_i][clicked_j].fillColorId = 0;
for (int i = 0; i < 4; i++)
{
fourBlocks[i] = blocks[clicked_i][clicked_j];
}
// 向上寻找
int search;
for (search = 0; clicked_i - search >= 0; search++)
{
if (blocks[clicked_i - search][clicked_j].fillColorId != 0)
{
fourBlocks[0] = blocks[clicked_i - search][clicked_j];
break;
}
}
// 向下寻找
for (search = 0; clicked_i + search < HEIGHT; search++)
{
if (blocks[clicked_i + search][clicked_j].fillColorId != 0)
{
fourBlocks[1] = blocks[clicked_i + search][clicked_j];
break;
}
}
// 向左寻找
for (search = 0; clicked_j - search >= 0; search++)
{
if (blocks[clicked_i][clicked_j - search].fillColorId != 0)
{
fourBlocks[2] = blocks[clicked_i][clicked_j - search];
break;
}
}
// 向右寻找
for (search = 0; clicked_j + search < WIDTH; search++)
{
if (blocks[clicked_i][clicked_j + search].fillColorId != 0)
{
fourBlocks[3] = blocks[clicked_i][clicked_j + search];
break;
}
}
// 统计 fourBlocks 中的颜色出现次数, 如果某个颜色出现 >= 2次,则“消除”(修改为灰色)
for (int i = 1; i <= ColorTypeNum; i++)
{
colorStatistics[i] = 0;
// 遍历 fourBlocks
for (int j = 0; j < 4; j++)
{
if (fourBlocks[j].fillColorId == i)
{
colorStatistics[i]++;
}
}
blocks[clicked_i][clicked_j].fillColorId = CLICKED_ID;
for (int i = 1; i <= ColorTypeNum; i++)
{
if (colorStatistics[i] >= 2)
{
for (int j = 0; j < 4; j++)
{
if (fourBlocks[j].fillColorId == i)
{
blocks[fourBlocks[j].i][fourBlocks[j].j].borderColorId = ELIMINATED_ID;
//blocks[fourBlocks[j].i][fourBlocks[j].j].fillColorId = 0;
}
}
}
}
}
frameCount = 0;
}
}
int main()
{
startup();
while (!WindowShouldClose())
{
updateWithInput();
updateWithoutInput();
show();
}
CloseWindow();
}
Greatness is never a given, it must be earned.