基于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();
}
posted @ 2023-01-25 20:30  ChrisZZ  阅读(95)  评论(0编辑  收藏  举报