基於 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();
}