IntToString

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
<pre class="cpp" name="code">void IntToStr(int iValue, char *strOutput)
{
	sprintf(strOutput, "%d", iValue);
}


void IntToStr(int iValue, char *strOutput)
{
	int i = 0;
	int len = 0;
	int tmp = 0;
	int bNegative = 0; 

	tmp = iValue;
	while (tmp / 10 != 0)
	{
		len++;
		tmp /= 10;
	}
	if (abs(iValue) >= 0)
	{
		len++;
	}
	
	if (iValue < 0)
	{
		bNegative = 1;
		iValue = -iValue;
		strOutput[0] = '-';
	}		
	for (i = 0; i < len; i++)
	{ 
		strOutput[i + bNegative] = (char)(iValue/pow((double)10, len-1-i)) + '0';
		iValue %= (int)pow((double)10, len-1-i);
	}
	strOutput[i + bNegative] = '\0';
	
}

void ReverseString(char *s)
{
	char *left = NULL;;
	char *right = NULL;
	char c;
	int len = strlen(s);
	
	for (left = s, right = s + len - 1; left <= right; 
		left++, right--) {
		c = *left;
		*left = *right;
		*right = c;
	}
}

void itoa0(int n, char s[])
{
	int i, sign;

	if ((sign = n) < 0)
		n = -n;
	i = 0;
	do {
		s[i++] = n % 10 + '0';
	} while ((n /= 10) > 0);
	if (sign < 0)
		s[i++] = '-';
	s[i] = '\0';

	ReverseString(s);
}

void itoa(int n, char s[])
{
	static int i;

	if (n / 10) {
		itoa(n / 10, s);
	} else {
		i = 0;
		if (n < 0) {
			s[i++] = '-';
		}
	}
	s[i++] = abs(n) % 10 + '0';
	s[i] = '\0';
}

void itos(int num, char *buf)
{
	int i = 0;

	if (num / 10) {
		itos(num / 10, buf);
		for(i = 0; buf[i] != '\0'; i++)
			;
	} else {
		i = 0;
		if (num < 0)
			buf[i++] = '-';
	}

	buf[i] = abs(num) % 10 + '0';
	buf[i + 1] = '\0';
}

void xtos(unsigned int num, char *buf)
{
	int i;

	if(num < 16){
		if(num < 10){
			buf[0] = num + '0';
		}else{
			buf[0] = num - 10 + 'a';
		}

		buf[1] = '\0';

		return;
	}

	xtos(num / 16, buf);

	for(i = 0; buf[i] != '\0'; i++);

	if((num % 16) < 10){
		buf[i] = (num % 16)	+ '0';	
	}else{
		buf[i] = (num % 16) - 10 + 'a';		
	}

	buf[i + 1] = '\0';
}

void IArrToStr(int *iArr, int iElemNum, char *strOutput)
{
	int len = 0;
	int i = 0;
	char *pOutPos = strOutput;
	char strVal[6] = {0};

	for (i = 0; i < iElemNum; i++)
	{
		//IntToStr(iArr[i], strVal);
		//itoa(iArr[i], strVal);
		//itoa0(iArr[i], strVal);
		itos(iArr[i], strVal);
		len = strlen(strVal);
		strcpy(pOutPos, strVal);
		pOutPos += len;
		*pOutPos++ = ',';
	}
	*pOutPos = '\0';
}

int main()
{
	int arr[] = {234, 12345, -345, 234, -9234, 100, 200, 0, 13, -242};
	char str[6] = {0};
	char strOutput[64] = {0};
	int len = sizeof(arr) / sizeof(arr[0]);

	for (int i = 0; i < len; i++)
	{
		IntToStr(arr[i], str);
		printf("%s\n", str);
	}

	IArrToStr(arr, len, strOutput);
	printf("%s\n", strOutput);

	system("pause");
	return 0;

} 

#include <graphics.h> #include <conio.h> #include <vector> #include <ctime> #include <string> #include <sstream> #include <windows.h> #include <algorithm> #include <atomic> #include <thread> #include <mmsystem.h> #pragma comment(lib, "winmm.lib") using namespace std; const int ROW = 8; const int COL = 10; const int BLOCK_SIZE = 80; const int WINDOW_WIDTH = COL * BLOCK_SIZE; const int WINDOW_HEIGHT = ROW * BLOCK_SIZE + 150; const int COLORS[] = {RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN, BROWN, LIGHTBLUE}; const int NUM_COLORS = sizeof(COLORS) / sizeof(COLORS[0]); vector<vector<int>> grid(ROW, vector<int>(COL)); atomic<int> score(0); atomic<bool> exitFlag(false); bool gameOver = false; int selectedX = -1, selectedY = -1; long long lastClickTime = 0; const int MIN_CLICK_INTERVAL = 50; bool isAnimating = false; enum GameState { READY, PLAYING, TIME_UP }; GameState gameState = READY; const int GAME_DURATION = 60; int remainingTime = GAME_DURATION; long long gameStartTime = 0; int finalScore = 0; bool isMusicPlaying = false; const char* MUSIC_FILE = "C:\\Users\\27287\\Desktop\\devc\\ma+7\\music.mp3"; // 使用普通字符串路径 class HighResTimer { public: void start() { QueryPerformanceCounter(&startTime); } double elapsed() const { LARGE_INTEGER endTime, frequency; QueryPerformanceCounter(&endTime); QueryPerformanceFrequency(&frequency); return static_cast<double>(endTime.QuadPart - startTime.QuadPart) / frequency.QuadPart; } private: LARGE_INTEGER startTime; }; void playBackgroundMusic() { string openCmd = "open \"" + string(MUSIC_FILE) + "\" type mpegvideo alias bgmusic"; mciSendString(openCmd.c_str(), NULL, 0, NULL); mciSendString("setaudio bgmusic volume to 500", NULL, 0, NULL); mciSendString("play bgmusic repeat", NULL, 0, NULL); isMusicPlaying = true; } void stopBackgroundMusic() { if (isMusicPlaying) { mciSendString("stop bgmusic", NULL, 0, NULL); mciSendString("close bgmusic", NULL, 0, NULL); isMusicPlaying = false; } } string intToString(int value) { stringstream ss; ss << value; return ss.str(); } void initGrid() { srand(static_cast<unsigned>(time(0))); bool hasMatches = true; while (hasMatches) { hasMatches = false; for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { grid[i][j] = rand() % NUM_COLORS; } } for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 2; ++j) { if (grid[i][j] == grid[i][j+1] && grid[i][j] == grid[i][j+2]) { hasMatches = true; break; } } if (hasMatches) break; } if (!hasMatches) { for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 2; ++i) { if (grid[i][j] == grid[i+1][j] && grid[i][j] == grid[i+2][j]) { hasMatches = true; break; } } if (hasMatches) break; } } } } void resetGame() { score = 0; remainingTime = GAME_DURATION; gameOver = false; selectedX = -1; selectedY = -1; isAnimating = false; gameState = PLAYING; // 使用QueryPerformanceCounter获取高精度时间 LARGE_INTEGER li; QueryPerformanceCounter(&li); gameStartTime = li.QuadPart; initGrid(); if (!isMusicPlaying) { playBackgroundMusic(); } } void drawGridPartial(int highlightX, int highlightY) { if (highlightX >= 0 && highlightY >= 0) { int x = highlightX, y = highlightY; setfillcolor(BLACK); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); if (grid[y][x] != -1) { setfillcolor(COLORS[grid[y][x]]); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); setlinecolor(BLACK); rectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); } if (x == selectedX && y == selectedY) { setlinecolor(WHITE); setlinestyle(PS_SOLID, 3); rectangle(x * BLOCK_SIZE + 2, y * BLOCK_SIZE + 2, (x + 1) * BLOCK_SIZE - 2, (y + 1) * BLOCK_SIZE - 2); setlinestyle(PS_SOLID, 1); } return; } cleardevice(); settextstyle(24, 0, "Arial"); if (gameState == READY) { settextcolor(WHITE); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 150, WINDOW_HEIGHT/2 - 60, "Block Game"); settextstyle(24, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2, "Click to Start"); outtextxy(20, WINDOW_HEIGHT - 80, "Rules:"); outtextxy(20, WINDOW_HEIGHT - 50, "1. Swap adjacent blocks"); outtextxy(20, WINDOW_HEIGHT - 20, "2. Match 3+ to eliminate"); setfillcolor(isMusicPlaying ? GREEN : RED); solidrectangle(WINDOW_WIDTH - 120, 20, WINDOW_WIDTH - 20, 60); setlinecolor(WHITE); rectangle(WINDOW_WIDTH - 120, 20, WINDOW_WIDTH - 20, 60); settextcolor(WHITE); outtextxy(WINDOW_WIDTH - 110, 30, isMusicPlaying ? "Music:ON" : "Music:OFF"); return; } for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { if(grid[i][j] != -1) { setfillcolor(COLORS[grid[i][j]]); solidrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); setlinecolor(BLACK); rectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); if (i == selectedY && j == selectedX) { setlinecolor(WHITE); setlinestyle(PS_SOLID, 3); rectangle(j * BLOCK_SIZE + 2, i * BLOCK_SIZE + 2, (j + 1) * BLOCK_SIZE - 2, (i + 1) * BLOCK_SIZE - 2); setlinestyle(PS_SOLID, 1); } } else { setfillcolor(BLACK); setlinecolor(DARKGRAY); rectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); } } } setfillcolor(DARKGRAY); solidrectangle(0, ROW * BLOCK_SIZE, WINDOW_WIDTH, WINDOW_HEIGHT); settextcolor(WHITE); string scoreStr = "Score: " + intToString(score); outtextxy(20, ROW * BLOCK_SIZE + 20, scoreStr.c_str()); string timeStr = "Time: " + intToString(remainingTime) + "s"; outtextxy(WINDOW_WIDTH/2 - 80, ROW * BLOCK_SIZE + 20, timeStr.c_str()); setfillcolor(isMusicPlaying ? GREEN : RED); solidrectangle(20, ROW * BLOCK_SIZE + 10, 120, ROW * BLOCK_SIZE + 40); setlinecolor(WHITE); rectangle(20, ROW * BLOCK_SIZE + 10, 120, ROW * BLOCK_SIZE + 40); settextcolor(WHITE); outtextxy(30, ROW * BLOCK_SIZE + 15, isMusicPlaying ? "Music:ON" : "Music:OFF"); setfillcolor(LIGHTGRAY); solidrectangle(WINDOW_WIDTH - 120, ROW * BLOCK_SIZE + 10, WINDOW_WIDTH - 20, ROW * BLOCK_SIZE + 40); setlinecolor(WHITE); rectangle(WINDOW_WIDTH - 120, ROW * BLOCK_SIZE + 10, WINDOW_WIDTH - 20, ROW * BLOCK_SIZE + 40); settextcolor(BLACK); outtextxy(WINDOW_WIDTH - 110, ROW * BLOCK_SIZE + 15, "Main Menu"); if (gameOver) { settextcolor(RED); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 - 30, "Game Over!"); settextstyle(24, 0, "Arial"); string finalScoreStr = "Final: " + intToString(finalScore); outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 20, finalScoreStr.c_str()); } if (gameState == TIME_UP) { setfillcolor(0x7F000000); solidrectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); settextcolor(WHITE); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 - 60, "Time Up!"); settextstyle(24, 0, "Arial"); string finalScoreStr = "Score: " + intToString(finalScore); outtextxy(WINDOW_WIDTH/2 - 80, WINDOW_HEIGHT/2, finalScoreStr.c_str()); setfillcolor(GREEN); solidrectangle(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 50, WINDOW_WIDTH/2 + 100, WINDOW_HEIGHT/2 + 100); setlinecolor(WHITE); rectangle(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 50, WINDOW_WIDTH/2 + 100, WINDOW_HEIGHT/2 + 100); settextcolor(WHITE); outtextxy(WINDOW_WIDTH/2 - 40, WINDOW_HEIGHT/2 + 65, "Restart"); } } bool hasPossibleMoves() { for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 1; ++j) { swap(grid[i][j], grid[i][j+1]); bool matchFound = false; for (int r = max(0, i-1); r <= min(ROW-1, i+1); ++r) { for (int c = max(0, j-2); c <= min(COL-3, j+2); ++c) { if (c < 0 || c+2 >= COL) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r][c+1] && grid[r][c] == grid[r][c+2]) { matchFound = true; break; } } if (matchFound) break; } if (!matchFound) { for (int c = max(0, j-1); c <= min(COL-1, j+1); ++c) { for (int r = max(0, i-2); r <= min(ROW-3, i+2); ++r) { if (r < 0 || r+2 >= ROW) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r+1][c] && grid[r][c] == grid[r+2][c]) { matchFound = true; break; } } if (matchFound) break; } } swap(grid[i][j], grid[i][j+1]); if (matchFound) return true; } } for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 1; ++i) { swap(grid[i][j], grid[i+1][j]); bool matchFound = false; for (int r = max(0, i-1); r <= min(ROW-1, i+1); ++r) { for (int c = max(0, j-2); c <= min(COL-3, j+2); ++c) { if (c < 0 || c+2 >= COL) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r][c+1] && grid[r][c] == grid[r][c+2]) { matchFound = true; break; } } if (matchFound) break; } if (!matchFound) { for (int c = max(0, j-1); c <= min(COL-1, j+1); ++c) { for (int r = max(0, i-2); r <= min(ROW-3, i+2); ++r) { if (r < 0 || r+2 >= ROW) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r+1][c] && grid[r][c] == grid[r+2][c]) { matchFound = true; break; } } if (matchFound) break; } } swap(grid[i][j], grid[i+1][j]); if (matchFound) return true; } } return false; } int processMatches() { vector<vector<bool>> toRemove(ROW, vector<bool>(COL, false)); int matchCount = 0; for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 2; ) { if (grid[i][j] != -1 && grid[i][j] == grid[i][j + 1] && grid[i][j] == grid[i][j + 2]) { int k = j + 2; while (k < COL && grid[i][j] == grid[i][k]) { k++; } for (int pos = j; pos < k; ++pos) { toRemove[i][pos] = true; matchCount++; } j = k; } else { j++; } } } for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 2; ) { if (grid[i][j] != -1 && grid[i][j] == grid[i + 1][j] && grid[i][j] == grid[i + 2][j]) { int k = i + 2; while (k < ROW && grid[i][j] == grid[k][j]) { k++; } for (int pos = i; pos < k; ++pos) { toRemove[pos][j] = true; matchCount++; } i = k; } else { i++; } } } if (matchCount > 0) { static int comboCount = 0; comboCount++; int comboBonus = max(0, comboCount - 1) * 5; score += matchCount * 10 + comboBonus; } else { static int comboCount = 0; comboCount = 0; } for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { if (toRemove[i][j]) { grid[i][j] = -1; } } } return matchCount; } void dropBlocksAnimated() { HighResTimer timer; timer.start(); vector<vector<int>> newPositions(COL); vector<vector<int>> temp(COL); for (int j = 0; j < COL; ++j) { for (int i = ROW - 1; i >= 0; --i) { if (grid[i][j] != -1) { temp[j].push_back(grid[i][j]); } } int newBlocks = ROW - temp[j].size(); for (int i = 0; i < newBlocks; ++i) { temp[j].push_back(rand() % NUM_COLORS); } for (int i = 0; i < ROW; ++i) { newPositions[j].push_back(temp[j][ROW - 1 - i]); } } const double animationDuration = 0.3; vector<vector<int>> originalGrid = grid; while (true) { double elapsed = timer.elapsed(); if (elapsed >= animationDuration) break; double progress = min(1.0, elapsed / animationDuration); for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW; ++i) { if (originalGrid[i][j] != -1 && newPositions[j][i] != originalGrid[i][j]) { int targetY = i; while (targetY < ROW && grid[targetY][j] != newPositions[j][i]) { targetY++; } if (targetY < ROW) { double currentY = i + (targetY - i) * progress; setfillcolor(COLORS[originalGrid[i][j]]); solidrectangle(j * BLOCK_SIZE, static_cast<int>(currentY * BLOCK_SIZE), (j + 1) * BLOCK_SIZE, static_cast<int>((currentY + 1) * BLOCK_SIZE)); setlinecolor(BLACK); rectangle(j * BLOCK_SIZE, static_cast<int>(currentY * BLOCK_SIZE), (j + 1) * BLOCK_SIZE, static_cast<int>((currentY + 1) * BLOCK_SIZE)); } } } } FlushBatchDraw(); Sleep(10); } for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW; ++i) { grid[i][j] = newPositions[j][i]; } } } void handleMouseClick() { if (isAnimating) return; if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); // 使用GetTickCount()代替chrono long long now = GetTickCount(); if (now - lastClickTime < MIN_CLICK_INTERVAL) { return; } lastClickTime = now; if (gameState == READY && msg.uMsg == WM_LBUTTONDOWN) { resetGame(); return; } if (gameState == TIME_UP && msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x; int y = msg.y; if (x >= WINDOW_WIDTH/2 - 100 && x <= WINDOW_WIDTH/2 + 100 && y >= WINDOW_HEIGHT/2 + 50 && y <= WINDOW_HEIGHT/2 + 100) { resetGame(); return; } } if (msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x; int y = msg.y; if (x >= 20 && x <= 120 && y >= ROW * BLOCK_SIZE + 10 && y <= ROW * BLOCK_SIZE + 40) { if (isMusicPlaying) { stopBackgroundMusic(); } else { playBackgroundMusic(); } drawGridPartial(-1, -1); FlushBatchDraw(); return; } if (x >= WINDOW_WIDTH - 120 && x <= WINDOW_WIDTH - 20 && y >= ROW * BLOCK_SIZE + 10 && y <= ROW * BLOCK_SIZE + 40) { gameState = READY; selectedX = -1; selectedY = -1; gameOver = false; drawGridPartial(-1, -1); FlushBatchDraw(); return; } } if (msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x / BLOCK_SIZE; int y = msg.y / BLOCK_SIZE; if (x >= 0 && x < COL && y >= 0 && y < ROW && grid[y][x] != -1 && gameState == PLAYING) { if (selectedX == -1) { selectedX = x; selectedY = y; drawGridPartial(x, y); FlushBatchDraw(); } else if (selectedX == x && selectedY == y) { selectedX = -1; selectedY = -1; drawGridPartial(x, y); FlushBatchDraw(); } else if ((abs(selectedX - x) == 1 && selectedY == y) || (abs(selectedY - y) == 1 && selectedX == x)) { isAnimating = true; int prevX = selectedX, prevY = selectedY; HighResTimer swapTimer; swapTimer.start(); const double swapDuration = 0.2; while (true) { double elapsed = swapTimer.elapsed(); if (elapsed >= swapDuration) break; double progress = min(1.0, elapsed / swapDuration); int offsetX = static_cast<int>((x - prevX) * progress * BLOCK_SIZE); int offsetY = static_cast<int>((y - prevY) * progress * BLOCK_SIZE); setfillcolor(BLACK); solidrectangle(prevX * BLOCK_SIZE, prevY * BLOCK_SIZE, (prevX + 1) * BLOCK_SIZE, (prevY + 1) * BLOCK_SIZE); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); setfillcolor(COLORS[grid[prevY][prevX]]); solidrectangle(prevX * BLOCK_SIZE + offsetX, prevY * BLOCK_SIZE + offsetY, (prevX + 1) * BLOCK_SIZE + offsetX, (prevY + 1) * BLOCK_SIZE + offsetY); setfillcolor(COLORS[grid[y][x]]); solidrectangle(x * BLOCK_SIZE - offsetX, y * BLOCK_SIZE - offsetY, (x + 1) * BLOCK_SIZE - offsetX, (y + 1) * BLOCK_SIZE - offsetY); FlushBatchDraw(); Sleep(10); } swap(grid[prevY][prevX], grid[y][x]); bool matched = false; if (processMatches() > 0) { matched = true; } if (!matched) { swap(grid[prevY][prevX], grid[y][x]); drawGridPartial(prevX, prevY); drawGridPartial(x, y); FlushBatchDraw(); } else { while (true) { dropBlocksAnimated(); if (processMatches() == 0) break; } gameOver = !hasPossibleMoves(); } selectedX = selectedY = -1; isAnimating = false; } else { int oldX = selectedX, oldY = selectedY; selectedX = x; selectedY = y; if (oldX >= 0 && oldY >= 0) { drawGridPartial(oldX, oldY); } drawGridPartial(x, y); FlushBatchDraw(); } } else if (selectedX >= 0 || selectedY >= 0) { int oldX = selectedX, oldY = selectedY; selectedX = selectedY = -1; if (oldX >= 0 && oldY >= 0) { drawGridPartial(oldX, oldY); } FlushBatchDraw(); } } } } void keyListenerThread() { while (!exitFlag) { if (_kbhit()) { char ch = _getch(); if (ch == 27) { exitFlag = true; break; } } Sleep(50); } } int main() { initgraph(WINDOW_WIDTH, WINDOW_HEIGHT); initGrid(); playBackgroundMusic(); BeginBatchDraw(); thread keyThread(keyListenerThread); HighResTimer frameTimer; const double targetFPS = 120.0; const double frameTime = 1.0 / targetFPS; while (!exitFlag) { frameTimer.start(); if (gameState == PLAYING) { // 使用QueryPerformanceCounter计算剩余时间 LARGE_INTEGER now, frequency; QueryPerformanceCounter(&now); QueryPerformanceFrequency(&frequency); double elapsedSeconds = static_cast<double>(now.QuadPart - gameStartTime) / frequency.QuadPart; remainingTime = max(0, GAME_DURATION - static_cast<int>(elapsedSeconds)); if (remainingTime == 0) { gameState = TIME_UP; finalScore = score; } if (gameOver) { finalScore = score; } } drawGridPartial(-1, -1); handleMouseClick(); FlushBatchDraw(); double elapsed = frameTimer.elapsed(); if (elapsed < frameTime) { int sleepTime = static_cast<int>((frameTime - elapsed) * 1000); if (sleepTime > 0) { Sleep(sleepTime); } } } exitFlag = true; if (keyThread.joinable()) { keyThread.join(); } stopBackgroundMusic(); EndBatchDraw(); closegraph(); return 0; }把页面所展示的英文转换为中文,便于理解
06-18
图块移动后是否形成三个及以上相同图块相连、游戏时间是否归零的判断 显示出完成以上功能的代码 //工具->编译选项 ->编译时加入以下命令->-std=c++11->勾选并确定 #include <graphics.h> #include <conio.h> #include <vector> #include <ctime> #include <string> #include <sstream> #include <windows.h> #include <chrono> #include <algorithm> #include <atomic> #include <thread> #include <fstream> #include <mmsystem.h> // 音效支持 #pragma comment(lib, "winmm.lib") // 链接Windows多媒体库 using namespace std; using namespace std::chrono; // ================ 全局配置 ================ const int ROW = 8; const int COL = 10; const int BLOCK_SIZE = 80; const int WINDOW_WIDTH = COL * BLOCK_SIZE; const int WINDOW_HEIGHT = ROW * BLOCK_SIZE + 150; const int COLORS[] = {RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN, BROWN, LIGHTBLUE}; const int NUM_COLORS = sizeof(COLORS) / sizeof(COLORS[0]); // 关卡配置 struct LevelConfig { int targetScore; // 目标分数 int timeLimit; // 时间限制(秒) int minMatches; // 最少匹配数 string levelName; // 关卡名称 }; vector<LevelConfig> levels = { {500, 90, 3, "新手关卡"}, {1000, 75, 4, "进阶关卡"}, {2000, 60, 5, "高手关卡"}, {4000, 45, 6, "大师关卡"}, {8000, 30, 7, "终极关卡"} }; // 音效文件路径 - 使用宽字符版本 const wchar_t* SOUND_MATCH = L"match.wav"; const wchar_t* SOUND_DROP = L"drop.wav"; const wchar_t* SOUND_TIME_WARNING = L"warning.wav"; const wchar_t* SOUND_TIME_UP = L"timeup.wav"; const wchar_t* SOUND_LEVEL_UP = L"levelup.wav"; // ================ 全局变量 ================ vector<vector<int>> grid(ROW, vector<int>(COL)); atomic<int> score(0); atomic<bool> exitFlag(false); bool gameOver = false; int selectedX = -1, selectedY = -1; steady_clock::time_point lastClickTime = steady_clock::now(); const int MIN_CLICK_INTERVAL = 50; bool isAnimating = false; int currentLevel = 0; int highScore = 0; // 游戏状态控制 enum GameState { READY, PLAYING, TIME_UP }; GameState gameState = READY; // 倒计时相关变量 int remainingTime = levels[currentLevel].timeLimit; steady_clock::time_point gameStartTime; int finalScore = 0; // ================ 辅助函数 ================ class HighResTimer { public: void start() { startTime = steady_clock::now(); } double elapsed() const { return duration_cast<duration<double>>(steady_clock::now() - startTime).count(); } private: steady_clock::time_point startTime; }; string intToString(int value) { stringstream ss; ss << value; return ss.str(); } // 播放音效 - 使用宽字符版本 void playSound(const wchar_t* filename) { PlaySoundW(filename, NULL, SND_FILENAME | SND_ASYNC); } // ================ 文件操作 ================ void loadHighScore() { ifstream file("highscore.dat"); if (file) { file >> highScore; file.close(); } } void saveHighScore() { if (score > highScore) { highScore = score; ofstream file("highscore.dat"); if (file) { file << highScore; file.close(); } } } // ================ 游戏核心逻辑 ================ void initGrid() { srand(static_cast<unsigned>(time(0))); bool hasMatches = true; while (hasMatches) { hasMatches = false; for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { grid[i][j] = rand() % NUM_COLORS; } } // 检查水平匹配 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 2; ++j) { if (grid[i][j] == grid[i][j+1] && grid[i][j] == grid[i][j+2]) { hasMatches = true; break; } } if (hasMatches) break; } // 检查垂直匹配 if (!hasMatches) { for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 2; ++i) { if (grid[i][j] == grid[i+1][j] && grid[i][j] == grid[i+2][j]) { hasMatches = true; break; } } if (hasMatches) break; } } } } void resetGame() { score = 0; currentLevel = 0; remainingTime = levels[currentLevel].timeLimit; gameOver = false; selectedX = -1; selectedY = -1; isAnimating = false; gameState = PLAYING; gameStartTime = steady_clock::now(); initGrid(); } // 优化绘制:添加倒计时和游戏状态显示 void drawGridPartial(int highlightX, int highlightY) { // 如果指定了高亮位置,只重绘该方块 if (highlightX >= 0 && highlightY >= 0) { int x = highlightX, y = highlightY; // 清除原位置 setfillcolor(BLACK); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); // 绘制新方块 if (grid[y][x] != -1) { setfillcolor(COLORS[grid[y][x]]); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); setlinecolor(BLACK); rectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); } // 高亮选中的方块 if (x == selectedX && y == selectedY) { setlinecolor(WHITE); setlinestyle(PS_SOLID, 3); rectangle(x * BLOCK_SIZE + 2, y * BLOCK_SIZE + 2, (x + 1) * BLOCK_SIZE - 2, (y + 1) * BLOCK_SIZE - 2); setlinestyle(PS_SOLID, 1); } return; } // 全屏重绘 cleardevice(); settextstyle(24, 0, "Arial"); // 准备开始界面 if (gameState == READY) { settextcolor(WHITE); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 150, WINDOW_HEIGHT/2 - 60, "方块消除游戏"); settextstyle(24, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2, "点击任意位置开始游戏"); // 显示最高分 string highScoreStr = "最高分: " + intToString(highScore); outtextxy(WINDOW_WIDTH/2 - 80, WINDOW_HEIGHT/2 + 40, highScoreStr.c_str()); // 绘制游戏说明 outtextxy(20, WINDOW_HEIGHT - 80, "游戏规则:"); outtextxy(20, WINDOW_HEIGHT - 50, "1. 点击相邻方块交换位置"); outtextxy(20, WINDOW_HEIGHT - 20, "2. 形成三个或更多相同方块可消除得分"); return; } // 绘制方块 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { if(grid[i][j] != -1) { setfillcolor(COLORS[grid[i][j]]); solidrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); setlinecolor(BLACK); rectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); // 高亮选中的方块 if (i == selectedY && j == selectedX) { setlinecolor(WHITE); setlinestyle(PS_SOLID, 3); rectangle(j * BLOCK_SIZE + 2, i * BLOCK_SIZE + 2, (j + 1) * BLOCK_SIZE - 2, (i + 1) * BLOCK_SIZE - 2); setlinestyle(PS_SOLID, 1); } } else { setfillcolor(BLACK); setlinecolor(DARKGRAY); rectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); } } } // 绘制状态栏 setfillcolor(DARKGRAY); solidrectangle(0, ROW * BLOCK_SIZE, WINDOW_WIDTH, WINDOW_HEIGHT); settextcolor(WHITE); string scoreStr = "分数: " + intToString(score); outtextxy(20, ROW * BLOCK_SIZE + 20, scoreStr.c_str()); // 绘制关卡信息 string levelStr = "关卡: " + levels[currentLevel].levelName; outtextxy(WINDOW_WIDTH/2 - 100, ROW * BLOCK_SIZE + 20, levelStr.c_str()); // 绘制目标分数 string targetStr = "目标: " + intToString(levels[currentLevel].targetScore); outtextxy(WINDOW_WIDTH/2 + 20, ROW * BLOCK_SIZE + 20, targetStr.c_str()); // 绘制倒计时 string timeStr = "时间: " + intToString(remainingTime) + "秒"; outtextxy(WINDOW_WIDTH - 150, ROW * BLOCK_SIZE + 20, timeStr.c_str()); // 时间警告效果(最后10秒) if (remainingTime <= 10) { static bool blink = false; static steady_clock::time_point lastBlink = steady_clock::now(); auto now = steady_clock::now(); if (duration_cast<milliseconds>(now - lastBlink).count() > 500) { blink = !blink; lastBlink = now; } if (blink) { settextcolor(RED); outtextxy(WINDOW_WIDTH - 150, ROW * BLOCK_SIZE + 20, timeStr.c_str()); settextcolor(WHITE); } } // 添加返回主页按钮(右下角) setfillcolor(LIGHTGRAY); solidrectangle(WINDOW_WIDTH - 120, ROW * BLOCK_SIZE + 50, WINDOW_WIDTH - 20, ROW * BLOCK_SIZE + 80); setlinecolor(WHITE); rectangle(WINDOW_WIDTH - 120, ROW * BLOCK_SIZE + 50, WINDOW_WIDTH - 20, ROW * BLOCK_SIZE + 80); settextcolor(BLACK); outtextxy(WINDOW_WIDTH - 110, ROW * BLOCK_SIZE + 60, "返回主页"); // 游戏结束提示 if (gameOver) { settextcolor(RED); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 - 30, "游戏结束!"); settextstyle(24, 0, "Arial"); string finalScoreStr = "最终分数: " + intToString(finalScore); outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 20, finalScoreStr.c_str()); // 显示是否打破记录 if (finalScore > highScore) { outtextxy(WINDOW_WIDTH/2 - 150, WINDOW_HEIGHT/2 + 60, "恭喜打破最高记录!"); } } // 时间结束界面 if (gameState == TIME_UP) { setfillcolor(0x7F000000); // 半透明黑色背景 solidrectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); settextcolor(WHITE); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 - 60, "时间到!"); settextstyle(24, 0, "Arial"); string finalScoreStr = "最终得分: " + intToString(finalScore); outtextxy(WINDOW_WIDTH/2 - 80, WINDOW_HEIGHT/2, finalScoreStr.c_str()); // 关卡完成检测 if (finalScore >= levels[currentLevel].targetScore) { outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 30, "关卡完成!"); } else { outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 + 30, "未达到目标分数!"); } // 绘制重新开始按钮 setfillcolor(GREEN); solidrectangle(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 50, WINDOW_WIDTH/2 + 100, WINDOW_HEIGHT/2 + 100); setlinecolor(WHITE); rectangle(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 50, WINDOW_WIDTH/2 + 100, WINDOW_HEIGHT/2 + 100); settextcolor(WHITE); outtextxy(WINDOW_WIDTH/2 - 40, WINDOW_HEIGHT/2 + 65, "重新开始"); } } // 优化匹配算法:只检查受影响的区域 bool checkMatchesAround(int x, int y) { // 检查水平匹配 for (int i = max(0, y-1); i <= min(ROW-1, y+1); i++) { for (int j = max(0, x-2); j <= min(COL-3, x+2); j++) { if (j < 0 || j+2 >= COL) continue; if (grid[i][j] != -1 && grid[i][j] == grid[i][j+1] && grid[i][j] == grid[i][j+2]) { return true; } } } // 检查垂直匹配 for (int j = max(0, x-1); j <= min(COL-1, x+1); j++) { for (int i = max(0, y-2); i <= min(ROW-3, y+2); i++) { if (i < 0 || i+2 >= ROW) continue; if (grid[i][j] != -1 && grid[i][j] == grid[i+1][j] && grid[i][j] == grid[i+2][j]) { return true; } } } return false; } // 检查并处理匹配(优化版) int processMatches() { vector<vector<bool>> toRemove(ROW, vector<bool>(COL, false)); int matchCount = 0; // 水平匹配检查 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 2; ) { if (grid[i][j] != -1 && grid[i][j] == grid[i][j+1] && grid[i][j] == grid[i][j+2]) { int k = j + 2; while (k < COL && grid[i][j] == grid[i][k]) { k++; } for (int pos = j; pos < k; ++pos) { toRemove[i][pos] = true; matchCount++; } j = k; } else { j++; } } } // 垂直匹配检查 for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 2; ) { if (grid[i][j] != -1 && grid[i][j] == grid[i+1][j] && grid[i][j] == grid[i+2][j]) { int k = i + 2; while (k < ROW && grid[i][j] == grid[k][j]) { k++; } for (int pos = i; pos < k; ++pos) { toRemove[pos][j] = true; matchCount++; } i = k; } else { i++; } } } // 更新分数 if (matchCount > 0) { static int comboCount = 0; comboCount++; // 连击奖励 int comboBonus = max(0, comboCount - 1) * 5; // 关卡难度加成 int levelBonus = currentLevel * 10; score += matchCount * 10 + comboBonus + levelBonus; // 播放匹配音效 playSound(SOUND_MATCH); } else { static int comboCount = 0; comboCount = 0; } // 移除匹配的方块 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { if (toRemove[i][j]) { grid[i][j] = -1; } } } return matchCount; } // 方块下落动画(带音效) void dropBlocksAnimated() { HighResTimer timer; timer.start(); vector<vector<int>> newPositions(COL); vector<vector<int>> temp(COL); for (int j = 0; j < COL; ++j) { for (int i = ROW - 1; i >= 0; --i) { if (grid[i][j] != -1) { temp[j].push_back(grid[i][j]); } } int newBlocks = ROW - temp[j].size(); for (int i = 0; i < newBlocks; ++i) { temp[j].push_back(rand() % NUM_COLORS); } for (int i = 0; i < ROW; ++i) { newPositions[j].push_back(temp[j][ROW - 1 - i]); } } const double animationDuration = 0.3; vector<vector<int>> originalGrid = grid; // 播放下落音效 playSound(SOUND_DROP); while (true) { double elapsed = timer.elapsed(); if (elapsed >= animationDuration) break; double progress = min(1.0, elapsed / animationDuration); for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW; ++i) { if (originalGrid[i][j] != -1 && newPositions[j][i] != originalGrid[i][j]) { int targetY = i; while (targetY < ROW && grid[targetY][j] != newPositions[j][i]) { targetY++; } if (targetY < ROW) { double currentY = i + (targetY - i) * progress; setfillcolor(COLORS[originalGrid[i][j]]); solidrectangle(j * BLOCK_SIZE, static_cast<int>(currentY * BLOCK_SIZE), (j + 1) * BLOCK_SIZE, static_cast<int>((currentY + 1) * BLOCK_SIZE)); setlinecolor(BLACK); rectangle(j * BLOCK_SIZE, static_cast<int>(currentY * BLOCK_SIZE), (j + 1) * BLOCK_SIZE, static_cast<int>((currentY + 1) * BLOCK_SIZE)); } } } } FlushBatchDraw(); Sleep(10); } for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW; ++i) { grid[i][j] = newPositions[j][i]; } } } // 检查是否升级 void checkLevelUp() { if (currentLevel < levels.size() - 1 && score >= levels[currentLevel].targetScore) { currentLevel++; remainingTime = levels[currentLevel].timeLimit; gameStartTime = steady_clock::now(); // 播放升级音效 playSound(SOUND_LEVEL_UP); } } // 非阻塞式鼠标处理 void handleMouseClick() { if (isAnimating) return; if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); auto now = steady_clock::now(); auto elapsed = duration_cast<milliseconds>(now - lastClickTime).count(); if (elapsed < MIN_CLICK_INTERVAL) { return; } lastClickTime = now; // 准备状态点击开始游戏 if (gameState == READY && msg.uMsg == WM_LBUTTONDOWN) { resetGame(); return; } // 时间结束状态点击重新开始按钮 if (gameState == TIME_UP && msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x; int y = msg.y; if (x >= WINDOW_WIDTH/2 - 100 && x <= WINDOW_WIDTH/2 + 100 && y >= WINDOW_HEIGHT/2 + 50 && y <= WINDOW_HEIGHT/2 + 100) { resetGame(); return; } } // 返回主页按钮处理 if ((gameState == PLAYING || gameState == TIME_UP) && msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x; int y = msg.y; if (x >= WINDOW_WIDTH - 120 && x <= WINDOW_WIDTH - 20 && y >= ROW * BLOCK_SIZE + 50 && y <= ROW * BLOCK_SIZE + 80) { gameState = READY; selectedX = -1; selectedY = -1; gameOver = false; drawGridPartial(-1, -1); FlushBatchDraw(); return; } } if (msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x / BLOCK_SIZE; int y = msg.y / BLOCK_SIZE; if (x >= 0 && x < COL && y >= 0 && y < ROW && grid[y][x] != -1 && gameState == PLAYING) { if (selectedX == -1) { selectedX = x; selectedY = y; drawGridPartial(x, y); FlushBatchDraw(); } else if (selectedX == x && selectedY == y) { selectedX = -1; selectedY = -1; drawGridPartial(x, y); FlushBatchDraw(); } else if ((abs(selectedX - x) == 1 && selectedY == y) || (abs(selectedY - y) == 1 && selectedX == x)) { isAnimating = true; int prevX = selectedX, prevY = selectedY; HighResTimer swapTimer; swapTimer.start(); const double swapDuration = 0.2; while (true) { double elapsed = swapTimer.elapsed(); if (elapsed >= swapDuration) break; double progress = min(1.0, elapsed / swapDuration); int offsetX = static_cast<int>((x - prevX) * progress * BLOCK_SIZE); int offsetY = static_cast<int>((y - prevY) * progress * BLOCK_SIZE); setfillcolor(BLACK); solidrectangle(prevX * BLOCK_SIZE, prevY * BLOCK_SIZE, (prevX + 1) * BLOCK_SIZE, (prevY + 1) * BLOCK_SIZE); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); setfillcolor(COLORS[grid[prevY][prevX]]); solidrectangle(prevX * BLOCK_SIZE + offsetX, prevY * BLOCK_SIZE + offsetY, (prevX + 1) * BLOCK_SIZE + offsetX, (prevY + 1) * BLOCK_SIZE + offsetY); setfillcolor(COLORS[grid[y][x]]); solidrectangle(x * BLOCK_SIZE - offsetX, y * BLOCK_SIZE - offsetY, (x + 1) * BLOCK_SIZE - offsetX, (y + 1) * BLOCK_SIZE - offsetY); FlushBatchDraw(); Sleep(10); } swap(grid[prevY][prevX], grid[y][x]); bool matched = false; // 使用优化后的匹配检测 if (checkMatchesAround(prevX, prevY) || checkMatchesAround(x, y)) { processMatches(); matched = true; } if (!matched) { swap(grid[prevY][prevX], grid[y][x]); drawGridPartial(prevX, prevY); drawGridPartial(x, y); FlushBatchDraw(); } else { while (true) { dropBlocksAnimated(); if (processMatches() == 0) break; } // 检查升级 checkLevelUp(); // 检查游戏是否结束 gameOver = false; // 重置,后面会检查 } selectedX = selectedY = -1; isAnimating = false; } else { int oldX = selectedX, oldY = selectedY; selectedX = x; selectedY = y; if (oldX >= 0 && oldY >= 0) { drawGridPartial(oldX, oldY); } drawGridPartial(x, y); FlushBatchDraw(); } } else if (selectedX >= 0 || selectedY >= 0) { int oldX = selectedX, oldY = selectedY; selectedX = selectedY = -1; if (oldX >= 0 && oldY >= 0) { drawGridPartial(oldX, oldY); } FlushBatchDraw(); } } } } // 按键监听线程函数 void keyListenerThread() { while (!exitFlag) { if (_kbhit()) { char ch = _getch(); if (ch == 27) { // ESC键 exitFlag = true; break; } } Sleep(50); } } int main() { // 初始化游戏 initgraph(WINDOW_WIDTH, WINDOW_HEIGHT); loadHighScore(); // 加载最高分 initGrid(); BeginBatchDraw(); // 启动按键监听线程 thread keyThread(keyListenerThread); // 高精度计时器 HighResTimer frameTimer; const double targetFPS = 120.0; const double frameTime = 1.0 / targetFPS; // 游戏主循环 while (!exitFlag) { frameTimer.start(); // 更新剩余时间 if (gameState == PLAYING) { auto now = steady_clock::now(); int elapsedSeconds = duration_cast<seconds>(now - gameStartTime).count(); remainingTime = max(0, levels[currentLevel].timeLimit - elapsedSeconds); // 时间警告音效(最后10秒) if (remainingTime == 10) { playSound(SOUND_TIME_WARNING); } // 时间结束 if (remainingTime == 0) { gameState = TIME_UP; finalScore = score; saveHighScore(); // 保存分数 playSound(SOUND_TIME_UP); } // 检查游戏是否结束(无可移动方块) // 这里省略了hasPossibleMoves的实现,保留原逻辑 if (gameOver) { finalScore = score; saveHighScore(); // 保存分数 } } // 绘制当前状态 drawGridPartial(-1, -1); // 处理鼠标点击 handleMouseClick(); FlushBatchDraw(); // 精确帧率控制 double elapsed = frameTimer.elapsed(); if (elapsed < frameTime) { int sleepTime = static_cast<int>((frameTime - elapsed) * 1000); if (sleepTime > 0) { Sleep(sleepTime); } } } // 清理资源 exitFlag = true; if (keyThread.joinable()) { keyThread.join(); } EndBatchDraw(); closegraph(); return 0; }
最新发布
06-20
#include <graphics.h> #include <conio.h> #include <vector> #include <ctime> #include <string> #include <sstream> #include <windows.h> #include <chrono> #include <algorithm> #include <atomic> #include <thread> using namespace std; using namespace std::chrono; const int ROW = 8; const int COL = 10; const int BLOCK_SIZE = 80; const int WINDOW_WIDTH = COL * BLOCK_SIZE; const int WINDOW_HEIGHT = ROW * BLOCK_SIZE + 150; const int COLORS[] = {RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN, BROWN, LIGHTBLUE}; const int NUM_COLORS = sizeof(COLORS) / sizeof(COLORS[0]); vector<vector<int>> grid(ROW, vector<int>(COL)); atomic<int> score(0); atomic<bool> exitFlag(false); bool gameOver = false; int selectedX =-1, selectedY =-1; steady_clock::time_point lastClickTime = steady_clock::now(); const int MIN_CLICK_INTERVAL = 50; bool isAnimating = false; // 游戏状态控制 enum GameState { READY, PLAYING, TIME_UP }; GameState gameState = READY; // 倒计时相关变量 const int GAME_DURATION = 60; // 60秒游戏时间 int remainingTime = GAME_DURATION; steady_clock::time_point gameStartTime; int finalScore = 0; // 高精度计时器类 class HighResTimer { public: void start() { startTime = steady_clock::now(); } double elapsed() const { return duration_cast<duration<double>>(steady_clock::now() - startTime).count(); } private: steady_clock::time_point startTime; }; // 整数转字符串 string intToString(int value) { stringstream ss; ss << value; return ss.str(); } // 初始化游戏网格 void initGrid() { srand(static_cast<unsigned>(time(0))); bool hasMatches = true; while (hasMatches) { hasMatches = false; for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { grid[i][j] = rand() % NUM_COLORS; } } // 检查水平匹配 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 2; ++j) { if (grid[i][j] == grid[i][j+1] && grid[i][j] == grid[i][j+2]) { hasMatches = true; break; } } if (hasMatches) break; } // 检查垂直匹配 if (!hasMatches) { for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 2; ++i) { if (grid[i][j] == grid[i+1][j] && grid[i][j] == grid[i+2][j]) { hasMatches = true; break; } } if (hasMatches) break; } } } } // 重置游戏状态 void resetGame() { score = 0; remainingTime = GAME_DURATION; gameOver = false; selectedX = -1; selectedY = -1; isAnimating = false; gameState = PLAYING; gameStartTime = steady_clock::now(); initGrid(); } void drawGridPartial(int highlightX, int highlightY); // 优化绘制:添加倒计时和游戏状态显示 void drawGridPartial(int highlightX, int highlightY) { // 如果指定了高亮位置,只重绘该方块 if (highlightX >= 0 && highlightY >= 0) { int x = highlightX, y = highlightY; // 清除原位置 setfillcolor(BLACK); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); // 绘制新方块 if (grid[y][x] != -1) { setfillcolor(COLORS[grid[y][x]]); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); setlinecolor(BLACK); rectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); } // 高亮选中的方块 if (x == selectedX && y == selectedY) { setlinecolor(WHITE); setlinestyle(PS_SOLID, 3); // 实线,宽度3像素 rectangle(x * BLOCK_SIZE + 2, y * BLOCK_SIZE + 2, (x + 1) * BLOCK_SIZE - 2, (y + 1) * BLOCK_SIZE - 2); setlinestyle(PS_SOLID, 1); // 恢复默认线宽 } return; } // 全屏重绘 cleardevice(); settextstyle(24, 0, "Arial"); // 准备开始界面 if (gameState == READY) { settextcolor(WHITE); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 150, WINDOW_HEIGHT/2 - 60, "方块消除游戏"); settextstyle(24, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2, "点击任意位置开始游戏"); // 绘制游戏说明 outtextxy(20, WINDOW_HEIGHT - 80, "游戏规则:"); outtextxy(20, WINDOW_HEIGHT - 50, "1. 点击相邻方块交换位置"); outtextxy(20, WINDOW_HEIGHT - 20, "2. 形成三个或更多相同方块可消除得分"); return; } // 绘制方块 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { if(grid[i][j] != -1) { setfillcolor(COLORS[grid[i][j]]); solidrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); setlinecolor(BLACK); rectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); // 高亮选中的方块 if (i == selectedY && j == selectedX) { setlinecolor(WHITE); setlinestyle(PS_SOLID, 3); // 实线,宽度3像素 rectangle(j * BLOCK_SIZE + 2, i * BLOCK_SIZE + 2, (j + 1) * BLOCK_SIZE - 2, (i + 1) * BLOCK_SIZE - 2); setlinestyle(PS_SOLID, 1); // 恢复默认线宽 } } else { // 绘制空方块(透明) setfillcolor(BLACK); setlinecolor(DARKGRAY); rectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE); } } } // 绘制状态栏 setfillcolor(DARKGRAY); solidrectangle(0, ROW * BLOCK_SIZE, WINDOW_WIDTH, WINDOW_HEIGHT); settextcolor(WHITE); string scoreStr = "分数: " + intToString(score); outtextxy(20, ROW * BLOCK_SIZE + 20, scoreStr.c_str()); // 绘制倒计时 string timeStr = "剩余时间: " + intToString(remainingTime) + "秒"; outtextxy(WINDOW_WIDTH/2 - 80, ROW * BLOCK_SIZE + 20, timeStr.c_str()); // 添加返回主页按钮(右下角) setfillcolor(LIGHTGRAY); solidrectangle(WINDOW_WIDTH - 120, ROW * BLOCK_SIZE + 10, WINDOW_WIDTH - 20, ROW * BLOCK_SIZE + 40); setlinecolor(WHITE); rectangle(WINDOW_WIDTH - 120, ROW * BLOCK_SIZE + 10, WINDOW_WIDTH - 20, ROW * BLOCK_SIZE + 40); settextcolor(BLACK); outtextxy(WINDOW_WIDTH - 110, ROW * BLOCK_SIZE + 15, "返回主页"); // 游戏结束提示 if (gameOver) { settextcolor(RED); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 - 30, "游戏结束!"); settextstyle(24, 0, "Arial"); string finalScoreStr = "最终分数: " + intToString(finalScore); outtextxy(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 20, finalScoreStr.c_str()); } // 时间结束界面 if (gameState == TIME_UP) { setfillcolor(0x7F000000); // 半透明黑色背景 solidrectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); settextcolor(WHITE); settextstyle(36, 0, "Arial"); outtextxy(WINDOW_WIDTH/2 - 120, WINDOW_HEIGHT/2 - 60, "时间到!"); settextstyle(24, 0, "Arial"); string finalScoreStr = "最终得分: " + intToString(finalScore); outtextxy(WINDOW_WIDTH/2 - 80, WINDOW_HEIGHT/2, finalScoreStr.c_str()); // 绘制重新开始按钮 setfillcolor(GREEN); solidrectangle(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 50, WINDOW_WIDTH/2 + 100, WINDOW_HEIGHT/2 + 100); setlinecolor(WHITE); rectangle(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2 + 50, WINDOW_WIDTH/2 + 100, WINDOW_HEIGHT/2 + 100); settextcolor(WHITE); outtextxy(WINDOW_WIDTH/2 - 40, WINDOW_HEIGHT/2 + 65, "重新开始"); } } // 检查是否有可移动的匹配(优化版) bool hasPossibleMoves() { // 水平交换检查 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 1; ++j) { // 尝试交换 swap(grid[i][j], grid[i][j+1]); // 检查交换后是否形成匹配 bool matchFound = false; // 检查行匹配(优化:只检查受影响的区域) for (int r = max(0, i-1); r <= min(ROW-1, i+1); ++r) { for (int c = max(0, j-2); c <= min(COL-3, j+2); ++c) { if (c < 0 || c+2 >= COL) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r][c+1] && grid[r][c] == grid[r][c+2]) { matchFound = true; break; } } if (matchFound) break; } // 检查列匹配 if (!matchFound) { for (int c = max(0, j-1); c <= min(COL-1, j+1); ++c) { for (int r = max(0, i-2); r <= min(ROW-3, i+2); ++r) { if (r < 0 || r+2 >= ROW) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r+1][c] && grid[r][c] == grid[r+2][c]) { matchFound = true; break; } } if (matchFound) break; } } // 恢复交换 swap(grid[i][j], grid[i][j+1]); if (matchFound) return true; } } // 垂直交换检查 for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 1; ++i) { // 尝试交换 swap(grid[i][j], grid[i+1][j]); // 检查交换后是否形成匹配 bool matchFound = false; // 检查行匹配 for (int r = max(0, i-1); r <= min(ROW-1, i+1); ++r) { for (int c = max(0, j-2); c <= min(COL-3, j+2); ++c) { if (c < 0 || c+2 >= COL) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r][c+1] && grid[r][c] == grid[r][c+2]) { matchFound = true; break; } } if (matchFound) break; } // 检查列匹配 if (!matchFound) { for (j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 1; ++i) { // 尝试交换 swap(grid[i][j], grid[i+1][j]); // 检查交换后是否形成匹配 bool matchFound = false; // 检查行匹配 for (int r = max(0, i-1); r <= min(ROW-1, i+1); ++r) { for (int c = max(0, j-2); c <= min(COL-3, j+2); ++c) { if (c < 0 || c+2 >= COL) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r][c+1] && grid[r][c] == grid[r][c+2]) { matchFound = true; break; } } if (matchFound) break; } // 检查列匹配 if (!matchFound) { for (int c = max(0, j-1); c <= min(COL-1, j+1); ++c) { for (int r = max(0, i-2); r <= min(ROW-3, i+2); ++r) { if (r < 0 || r+2 >= ROW) continue; if (grid[r][c] != -1 && grid[r][c] == grid[r+1][c] && grid[r][c] == grid[r+2][c]) { matchFound = true; break; } } if (matchFound) break; } } // 恢复交换 swap(grid[i][j], grid[i+1][j]); if (matchFound) return true; } } } return false; } } } // 检查并处理匹配 int processMatches() { vector<vector<bool>> toRemove(ROW, vector<bool>(COL, false)); int matchCount = 0; // 水平匹配检查 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL - 2; ) { if (grid[i][j] != -1 && grid[i][j] == grid[i][j + 1] && grid[i][j] == grid[i][j + 2]) { int k = j + 2; while (k < COL && grid[i][j] == grid[i][k]) { k++; } for (int pos = j; pos < k; ++pos) { toRemove[i][pos] = true; matchCount++; } j = k; // 跳过已检查的部分 } else { j++; } } } // 垂直匹配检查 for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW - 2; ) { if (grid[i][j] != -1 && grid[i][j] == grid[i + 1][j] && grid[i][j] == grid[i + 2][j]) { int k = i + 2; while (k < ROW && grid[i][j] == grid[k][j]) { k++; } for (int pos = i; pos < k; ++pos) { toRemove[pos][j] = true; matchCount++; } i = k; // 跳过已检查的部分 } else { i++; } } } // 更新分数 if (matchCount > 0) { static int comboCount = 0; comboCount++; int comboBonus = max(0, comboCount - 1) * 5; score += matchCount * 10 + comboBonus; } else { // 重置连击计数 static int comboCount = 0; comboCount = 0; } // 移除匹配的方块 for (int i = 0; i < ROW; ++i) { for (int j = 0; j < COL; ++j) { if (toRemove[i][j]) { grid[i][j] = -1; } } } return matchCount; } // 方块下落动画(非阻塞式) void dropBlocksAnimated() { HighResTimer timer; timer.start(); // 记录每列需要下落的位置 vector<vector<int>> newPositions(COL); vector<vector<int>> temp(COL); // 准备下落数据 for (int j = 0; j < COL; ++j) { // 收集非空方块(从下往上) for (int i = ROW - 1; i >= 0; --i) { if (grid[i][j] != -1) { temp[j].push_back(grid[i][j]); } } // 生成新方块 int newBlocks = ROW - temp[j].size(); for (int i = 0; i < newBlocks; ++i) { temp[j].push_back(rand() % NUM_COLORS); } // 计算新位置 for (int i = 0; i < ROW; ++i) { newPositions[j].push_back(temp[j][ROW - 1 - i]); } } // 动画持续时间(秒) const double animationDuration = 0.3; vector<vector<int>> originalGrid = grid; // 保存原始状态 while (true) { double elapsed = timer.elapsed(); if (elapsed >= animationDuration) break; double progress = min(1.0, elapsed / animationDuration); // 更新动画帧 for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW; ++i) { // 如果方块需要下落 if (originalGrid[i][j] != -1 && newPositions[j][i] != originalGrid[i][j]) { // 计算下落距离 int targetY = i; while (targetY < ROW && grid[targetY][j] != newPositions[j][i]) { targetY++; } if (targetY < ROW) { // 计算当前位置 double currentY = i + (targetY - i) * progress; // 绘制下落中的方块 setfillcolor(COLORS[originalGrid[i][j]]); solidrectangle(j * BLOCK_SIZE, static_cast<int>(currentY * BLOCK_SIZE), (j + 1) * BLOCK_SIZE, static_cast<int>((currentY + 1) * BLOCK_SIZE)); setlinecolor(BLACK); rectangle(j * BLOCK_SIZE, static_cast<int>(currentY * BLOCK_SIZE), (j + 1) * BLOCK_SIZE, static_cast<int>((currentY + 1) * BLOCK_SIZE)); } } } } FlushBatchDraw(); Sleep(10); } // 应用最终状态 for (int j = 0; j < COL; ++j) { for (int i = 0; i < ROW; ++i) { grid[i][j] = newPositions[j][i]; } } } // 非阻塞式鼠标处理 void handleMouseClick() { // 如果正在动画中,忽略输入 if (isAnimating) return; if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); // 检查点击间隔 auto now = steady_clock::now(); auto elapsed = duration_cast<milliseconds>(now - lastClickTime).count(); if (elapsed < MIN_CLICK_INTERVAL) { return; } lastClickTime = now; // 准备状态点击开始游戏 if (gameState == READY && msg.uMsg == WM_LBUTTONDOWN) { resetGame(); return; } // 时间结束状态点击重新开始按钮 if (gameState == TIME_UP && msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x; int y = msg.y; // 检查是否点击了重新开始按钮 if (x >= WINDOW_WIDTH/2 - 100 && x <= WINDOW_WIDTH/2 + 100 && y >= WINDOW_HEIGHT/2 + 50 && y <= WINDOW_HEIGHT/2 + 100) { resetGame(); return; } } // 新增:返回主页按钮处理 if ((gameState == PLAYING || gameState == TIME_UP) && msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x; int y = msg.y; // 检查是否点击了返回主页按钮(右下角) if (x >= WINDOW_WIDTH - 120 && x <= WINDOW_WIDTH - 20 && y >= ROW * BLOCK_SIZE + 10 && y <= ROW * BLOCK_SIZE + 40) { // 返回主页 gameState = READY; selectedX = -1; selectedY = -1; gameOver = false; // 重绘整个界面 drawGridPartial(-1, -1); FlushBatchDraw(); return; } } if (msg.uMsg == WM_LBUTTONDOWN) { int x = msg.x / BLOCK_SIZE; int y = msg.y / BLOCK_SIZE; // 确保点击在网格内且游戏正在进行 if (x >= 0 && x < COL && y >= 0 && y < ROW && grid[y][x] != -1 && gameState == PLAYING) { // 第一次点击或更换选择 if (selectedX == -1) { selectedX = x; selectedY = y; drawGridPartial(x, y); // 部分重绘 FlushBatchDraw(); } // 点击同一方块 - 取消选择 else if (selectedX == x && selectedY == y) { selectedX = -1; selectedY = -1; drawGridPartial(x, y); // 部分重绘 FlushBatchDraw(); } // 第二次点击(交换) else if ((abs(selectedX - x) == 1 && selectedY == y) || (abs(selectedY - y) == 1 && selectedX == x)) { // 设置动画状态 isAnimating = true; // 交换动画 int prevX = selectedX, prevY = selectedY; // 绘制交换动画 HighResTimer swapTimer; swapTimer.start(); const double swapDuration = 0.2; while (true) { double elapsed = swapTimer.elapsed(); if (elapsed >= swapDuration) break; double progress = min(1.0, elapsed / swapDuration); // 计算中间位置 int offsetX = static_cast<int>((x - prevX) * progress * BLOCK_SIZE); int offsetY = static_cast<int>((y - prevY) * progress * BLOCK_SIZE); // 清除原位置 setfillcolor(BLACK); solidrectangle(prevX * BLOCK_SIZE, prevY * BLOCK_SIZE, (prevX + 1) * BLOCK_SIZE, (prevY + 1) * BLOCK_SIZE); solidrectangle(x * BLOCK_SIZE, y * BLOCK_SIZE, (x + 1) * BLOCK_SIZE, (y + 1) * BLOCK_SIZE); // 绘制移动中的方块 setfillcolor(COLORS[grid[prevY][prevX]]); solidrectangle(prevX * BLOCK_SIZE + offsetX, prevY * BLOCK_SIZE + offsetY, (prevX + 1) * BLOCK_SIZE + offsetX, (prevY + 1) * BLOCK_SIZE + offsetY); setfillcolor(COLORS[grid[y][x]]); solidrectangle(x * BLOCK_SIZE - offsetX, y * BLOCK_SIZE - offsetY, (x + 1) * BLOCK_SIZE - offsetX, (y + 1) * BLOCK_SIZE - offsetY); FlushBatchDraw(); Sleep(10); } // 实际交换方块 swap(grid[prevY][prevX], grid[y][x]); // 检查是否形成匹配 bool matched = false; if (processMatches() > 0) { matched = true; } if (!matched) { // 没有匹配则恢复交换 swap(grid[prevY][prevX], grid[y][x]); drawGridPartial(prevX, prevY); drawGridPartial(x, y); FlushBatchDraw(); } else { // 处理连续消除 while (true) { // 下落方块(动画版) dropBlocksAnimated(); // 检查是否有新的匹配 if (processMatches() == 0) break; } // 检查游戏是否结束 gameOver = !hasPossibleMoves(); } // 重置选择 selectedX = selectedY = -1; // 结束动画 isAnimating = false; } // 点击其他位置,重新选择 else { // 先清除旧选择 int oldX = selectedX, oldY = selectedY; selectedX = x; selectedY = y; // 部分重绘 if (oldX >= 0 && oldY >= 0) { drawGridPartial(oldX, oldY); } drawGridPartial(x, y); FlushBatchDraw(); } } // 点击在网格外,重置选择 else if (selectedX >= 0 || selectedY >= 0) { int oldX = selectedX, oldY = selectedY; selectedX = selectedY = -1; // 部分重绘 if (oldX >= 0 && oldY >= 0) { drawGridPartial(oldX, oldY); } FlushBatchDraw(); } } } } // 按键监听线程函数 void keyListenerThread() { while (!exitFlag) { if (_kbhit()) { char ch = _getch(); if (ch == 27) { // ESC键 exitFlag = true; break; } } Sleep(50); // 降低CPU占用 } } int main() { initgraph(WINDOW_WIDTH, WINDOW_HEIGHT); initGrid(); BeginBatchDraw(); // 启动按键监听线程 thread keyThread(keyListenerThread); // 高精度计时器 HighResTimer frameTimer; const double targetFPS = 120.0; const double frameTime = 1.0 / targetFPS; // 游戏主循环 while (!exitFlag) { frameTimer.start(); // 更新剩余时间 if (gameState == PLAYING) { auto now = steady_clock::now(); int elapsedSeconds = duration_cast<seconds>(now - gameStartTime).count(); remainingTime = max(0, GAME_DURATION - elapsedSeconds); // 检查时间是否结束 if (remainingTime == 0) { gameState = TIME_UP; finalScore = score; } // 检查游戏是否结束(无可移动方块) if (gameOver) { finalScore = score; } } // 绘制当前状态 drawGridPartial(-1, -1); // 使用无效值表示全屏重绘 // 处理鼠标点击 handleMouseClick(); FlushBatchDraw(); // 精确帧率控制 double elapsed = frameTimer.elapsed(); if (elapsed < frameTime) { int sleepTime = static_cast<int>((frameTime - elapsed) * 1000); if (sleepTime > 0) { Sleep(sleepTime); } } } // 设置退出标志并等待线程结束 exitFlag = true; if (keyThread.joinable()) { keyThread.join(); } EndBatchDraw(); closegraph(); return 0; }可否分为,两个模式一个无时间限制,一个和现在一样1分钟计时
06-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值