基於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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章