欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言實現(xiàn)消消樂游戲的代碼分享

 更新時間:2023年02月15日 09:09:35   作者:編程小魚六六六  
本章我們將編寫十字消除游戲,用戶點擊空白方塊,沿其上下左右方向?qū)ふ业谝粋€彩色方塊,如果有兩個或兩個以上顏色一致,就將其消除,感興趣的可以了解一下

C和C++游戲趣味編程》一書各個章節(jié)的案例代碼,每章案例逐步利用學(xué)到的語法知識。

本章我們將編寫十字消除游戲,用戶點擊空白方塊,沿其上下左右方向?qū)ふ业谝粋€彩色方塊,如果有兩個或兩個以上顏色一致,就將其消除。在進(jìn)度條時間結(jié)束前消除足夠的方塊,可以進(jìn)入下一關(guān),效果如圖所示。

首先實現(xiàn)隨機顏色方塊的表示與繪制,鼠標(biāo)點擊與十字消除算法;然后繪制了提示框,繪制倒計時進(jìn)度條;接著進(jìn)行了得分計算、勝負(fù)判斷、多關(guān)卡功能的開發(fā);學(xué)習(xí)了地址與指針的概念,并利用地址傳遞使得程序更加模塊化;最后學(xué)習(xí)了指針和數(shù)組的知識,應(yīng)用動態(tài)數(shù)組實現(xiàn)了游戲尺寸的動態(tài)大小調(diào)整。

源碼

#include <graphics.h>  
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
 
# define BlockSize 40 // 小方塊的長寬大小
# define ColorTypeNum 9 // 除了空白方塊外,其他方塊的顏色的個數(shù)
 
struct Block // 小方塊結(jié)構(gòu)體
{
	int x,y; // x y坐標(biāo)
	int colorId; // 對應(yīng)顏色的下標(biāo)
	int i,j;  // 小方塊在二維數(shù)組中的i j下標(biāo)
};
 
// 全局變量
int RowNum; // 游戲畫面一共RowNum行小方塊
int ColNum; // 游戲畫面一共ColNum列小方塊
Block **blocks = NULL; // 動態(tài)二維數(shù)組指針,存儲所有方塊數(shù)據(jù)
COLORREF  colors[ColorTypeNum+1]; // 顏色數(shù)組,小方塊可能的幾種顏色
int score; // 得分?jǐn)?shù),也就是消去的方塊的個數(shù)
float maxTime; // 這一關(guān)游戲的總時長
float totalTime; // 減去扣分項后的游戲總時長
float remainTime; // 剩余時間
clock_t start, finish; // 用于計時的變量
int level = 1; // 當(dāng)前關(guān)卡序號
int noZeroBlockNum; // 非空白區(qū)域的磚塊的個數(shù)
 
void drawBlockHint(int i,int j,COLORREF color,int isfill) // 繪制出一個提示線框出來
{
	setlinecolor(color);
	setfillcolor(color);
	if (isfill==1) // 鼠標(biāo)點擊中的方塊,畫填充方塊提示
		fillrectangle(blocks[i][j].x,blocks[i][j].y,blocks[i][j].x+BlockSize,blocks[i][j].y+BlockSize);
	if (isfill==0) // 上下左右四個方向找到的4個方塊,畫線框提示
		rectangle(blocks[i][j].x,blocks[i][j].y,blocks[i][j].x+BlockSize,blocks[i][j].y+BlockSize);
}
 
 
void writeRecordFile(int recordScore)  //保存最高分?jǐn)?shù)據(jù)文件
{ 
	FILE *fp;
	fp = fopen(".\\gameRecord.dat","w");
	fprintf(fp,"%d",recordScore);
	fclose(fp);
}
 
int readRecordFile()  //讀取最高分?jǐn)?shù)據(jù)文件
{ 
	int recordScore;
	FILE *fp;
	fp = fopen(".\\gameRecord.dat","r");
 
	// 如果打不開的話,就新建一個文件,其得分記錄為0分
	if (fp==NULL)
	{
		writeRecordFile(0);
		return 0;
	}
	else // 能打開這個文件,就讀取下最高分記錄
	{
		fscanf(fp,"%d",&recordScore);
		fclose(fp);
		return recordScore;
	}
}
 
void startup() // 初始化函數(shù)
{
	int i,j;
	start = clock(); // 記錄當(dāng)前運行時刻
 
	if (level>1) // 如果不是第1關(guān),則先清除二維數(shù)組內(nèi)存,再重新開辟內(nèi)存空間
	{
		for (i=0;i<RowNum;i++)
			free(blocks[i]);
		free(blocks);
	}
 
	// 根據(jù)是第幾關(guān),調(diào)整這一關(guān)對應(yīng)的游戲畫面的大小
	RowNum = 12 + level/2;  // 行數(shù)添加的慢一些,是一個長方形的形狀
	ColNum = 20 + level;
 
	// 開辟動態(tài)二維數(shù)組
	blocks = (Block **) malloc(RowNum*sizeof(Block *));
	for (i=0;i<RowNum;i++)
		blocks[i] = (Block *) malloc(ColNum*sizeof(Block));
 
	maxTime = 200 + level*10; // 這一關(guān)游戲設(shè)定的總時長,每關(guān)時長+10秒
	totalTime = maxTime; // 游戲總時長,每次出錯,會扣10秒鐘
 
	int width = BlockSize*ColNum;      // 設(shè)定游戲畫面的大小
	int height = BlockSize*(RowNum+3); // 最下面用來顯示一些提示信息
	initgraph(width,height);
	setbkcolor(RGB(220,220,220));
	setlinestyle(PS_SOLID,2);
	cleardevice();
	srand(time(0));
	BeginBatchDraw(); // 開始批量繪制
 
	score = 0; // 得分?jǐn)?shù),也就是消去的方塊的個數(shù)
	noZeroBlockNum = 0; // 非空白區(qū)域的磚塊的個數(shù)
 
	colors[0] = RGB(220,220,220); // 顏色數(shù)組第一種顏色為灰白色,表示空白小方塊
	for (i=1;i<ColorTypeNum+1;i++) // 其他幾種顏色為彩色
		colors[i] = HSVtoRGB((i-1)*40,0.6,0.8);
 
	// 對blocks二維數(shù)組進(jìn)行初始化
	for (i=0;i<RowNum;i++)
	{
		for (j=0;j<ColNum;j++)
		{
			// 取隨機數(shù),1-6設(shè)為彩色色塊,其他為空白色塊,這樣為空白色塊的幾率高一些
			// 初始化時,空白色塊多一些,符合游戲的設(shè)定
			int t = rand()%(int(ColorTypeNum*1.5));  // 取隨機數(shù)
			if (t<ColorTypeNum+1) 
				blocks[i][j].colorId = t; // 小方塊的顏色序號
			else // 其他情況,都為空白顏色方塊
				blocks[i][j].colorId = 0; // 小方塊的顏色序號
			blocks[i][j].x = j*BlockSize; // 小方塊左上角坐標(biāo)
			blocks[i][j].y = i*BlockSize; // 
			blocks[i][j].i = i;   // 存儲當(dāng)前小方塊在二維數(shù)組中的下標(biāo)
			blocks[i][j].j = j; 
			if (blocks[i][j].colorId != 0)
				noZeroBlockNum++; // 統(tǒng)計隨機產(chǎn)生的方塊中,非零方塊的個數(shù)
		}
	}
}
 
void show() // 繪制函數(shù)
{
	cleardevice(); // 清屏
	setlinecolor(RGB(255,255,255)); // 白色線條
	int i,j;
	for (i=0;i<RowNum;i++)
	{
		for (j=0;j<ColNum;j++)
		{
			// 以對應(yīng)的顏色、坐標(biāo)畫出所有的小方塊
			setfillcolor(colors[blocks[i][j].colorId]);
			fillrectangle(blocks[i][j].x,blocks[i][j].y,blocks[i][j].x+BlockSize,blocks[i][j].y+BlockSize);
		}
	}
 
	// 根據(jù)剩余時間,繪制一個倒計時進(jìn)度條,進(jìn)度條按最大時間maxTime秒繪制
	setlinecolor(RGB(255,0,0));
	setfillcolor(RGB(255,0,0));
	fillrectangle(0,BlockSize*(RowNum+0.2),remainTime*BlockSize*ColNum/maxTime,BlockSize*(RowNum+0.8));
 
	// 輸出得分文字
	TCHAR s[80];
	setbkmode(TRANSPARENT);
	_stprintf(s, _T("%d"), score);	
	settextcolor(RGB(0,0,0)); 
	settextstyle(22, 0, _T("宋體"));
	outtextxy(BlockSize*(ColNum/2-0.1), BlockSize*(RowNum+0.2), s);
	// 輸出一些游戲提示信息
	_stprintf(s, _T("點擊空白方塊,其十字區(qū)域有兩個或以上相同顏色方塊則消除;不能消除扣時間"));	
	outtextxy(BlockSize*(ColNum/15.0), BlockSize*(RowNum+1.2), s);
	_stprintf(s, _T("目前第 %d 關(guān),時間結(jié)束前得分達(dá)到 %d 可進(jìn)入下一關(guān)"),level,int(noZeroBlockNum*0.9));	
	outtextxy(BlockSize*(ColNum/5.0), BlockSize*(RowNum+2.2), s);
 
	FlushBatchDraw(); // 批量繪制
}	
 
void updateWithoutInput() // 和輸入無關(guān)的更新
{
	// 倒計時減少
	finish = clock(); // 當(dāng)前時刻
	// 從startup運行后,這一關(guān)游戲運行了多少秒
	double duration = (double)(finish - start) / CLOCKS_PER_SEC; 
	remainTime = totalTime-duration; // 游戲剩余的時間
 
	// 如果時間到了
	if (remainTime<=0) 
	{
		// 讀一下文件記錄,如果當(dāng)前得分超過記錄
		if (score > readRecordFile())
		{
			// 更新下得分記錄
			writeRecordFile(score);
 
			// 顯示恭喜超過記錄
			show();
			settextcolor(RGB(255,0,0)); 
			settextstyle(100, 0, _T("黑體"));
			outtextxy(BlockSize*(ColNum/30.0), BlockSize*(RowNum/3.0), _T("恭喜打破得分記錄"));
			FlushBatchDraw(); // 批量繪制
			Sleep(2000);
		}
 
		if (score>=int(noZeroBlockNum*0.9))
		{
			level ++; // 如果得分達(dá)到要求,消除掉非空白方塊數(shù)目的90%,關(guān)卡加1
		}
		startup(); // 調(diào)用初始化函數(shù),重新開始游戲
		return;
	}
}
 
void updateWithInput() // 和輸入有關(guān)的更新
{
	if (remainTime<=0) // 時間到了,不要操作
		return;
 
	int i,j;
	MOUSEMSG m;		
	if (MouseHit())  
	{
		m = GetMouseMsg();  	
		if(m.uMsg == WM_LBUTTONDOWN) // 當(dāng)按下鼠標(biāo)左鍵時
		{
			// 獲得點擊的小方塊的下標(biāo)
			int clicked_i = int(m.y)/BlockSize;
			int clicked_j = int(m.x)/BlockSize;
			// 點擊到下面提示部分了,不用處理,函數(shù)返回
			if (clicked_i>=RowNum) 
				return; 
			// 如果當(dāng)前點擊的不是空白方塊,不需要處理,返回
			if (blocks[clicked_i][clicked_j].colorId!=0)
				return;
 
			show(); // 先顯示其他方塊,再繪制提示框,后繪制的在最前面
			// 被點擊到的空白方塊,繪制下填充灰色方塊提示框
			drawBlockHint(clicked_i,clicked_j,RGB(100,100,100),1);			
 
			// 定義數(shù)組,存儲上、下、左、右四個方向找到第一個不是空白的方塊
			Block fourBlocks[4] = {blocks[clicked_i][clicked_j]}; // 初始化為這個空白的點擊的方塊
			int search; // 尋找下標(biāo)
 
			// 向上找
			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]; // 賦給這個存儲的數(shù)組
					break;
				}
			}
			// 向下找
			for (search=0;clicked_i+search<RowNum;search++)
			{
				if (blocks[clicked_i+search][clicked_j].colorId!=0) // 找到第一個顏色不是空白的方塊
				{
					fourBlocks[1] = blocks[clicked_i+search][clicked_j]; // 賦給這個存儲的數(shù)組
					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]; // 賦給這個存儲的數(shù)組
					break;
				}
			}
			// 向右找
			for (search=0;clicked_j+search<ColNum;search++)
			{
				if (blocks[clicked_i][clicked_j+search].colorId!=0) // 找到第一個顏色不是空白的方塊
				{
					fourBlocks[3] = blocks[clicked_i][clicked_j+search]; // 賦給這個存儲的數(shù)組
					break;
				}
			}
 
			// 統(tǒng)計fourBlocks的四個小方塊,有沒有同樣顏色數(shù)目大于等于2的
			int colorStatistics[ColorTypeNum+1] = {0}; // 初始化個數(shù)為0
			int isBadClick = 1; // 假設(shè)點擊的方塊不合適,十字區(qū)域沒有有效消除的方塊
			for (i=1;i<ColorTypeNum+1;i++) // i=0是空白顏色,不要統(tǒng)計
			{
				for (j=0;j<4;j++) // 遍歷fourBlocks
				{
					if (fourBlocks[j].colorId==i)
						colorStatistics[i]++; // 方塊顏色為非零的i的話,把對應(yīng)的統(tǒng)計個數(shù)+1
				}
				if (colorStatistics[i]>=2) // 如果這種顏色方塊個數(shù)大于等于2
				{					
					isBadClick = 0; // 能消除了,這次點擊是好的操作
					// 把對應(yīng)十字區(qū)域要消除的方塊顏色改成空白顏色
					for (j=0;j<4;j++) // 遍歷fourBlocks
					{
						if (fourBlocks[j].colorId==i)
						{
							// 要消除的方塊區(qū)域繪制提示框							
							drawBlockHint(fourBlocks[j].i,fourBlocks[j].j,RGB(0,0,0),0);	
							// 顏色序號設(shè)為0,也就是空白的灰白色
							blocks[fourBlocks[j].i][fourBlocks[j].j].colorId = 0; 
						}
					}
					score += colorStatistics[i]; // 得分加上消除的方塊數(shù)
				}				
			}
 
			// 點擊的方塊,十字區(qū)域沒有能消除的方塊,為錯誤點擊,減去10秒鐘時間
			if (isBadClick==1) 
				totalTime -= 10; 
 
			FlushBatchDraw(); // 批量繪制
			Sleep(300); // 繪制好提示框后暫停300毫秒
 
		} // while 當(dāng)按下鼠標(biāo)左鍵時
	}
}
 
int main() // 主函數(shù)運行
{
	startup();  	
	while (1) 
	{
		show(); 
		updateWithoutInput(); 
		updateWithInput();  
 
	}
	closegraph(); 
	return 0;
}

這一章主要講解了指針的相關(guān)語法知識,學(xué)習(xí)了倒計時的方法,實現(xiàn)了十字消除游戲。讀者可以嘗試在本章代碼基礎(chǔ)上繼續(xù)改進(jìn):

1、實現(xiàn)隨著游戲的進(jìn)行,通過關(guān)卡要求消除方塊的比例越來越高;

2、利用文件讀寫,實現(xiàn)關(guān)卡數(shù)據(jù)與最高分的記錄與讀取。

到此這篇關(guān)于C語言實現(xiàn)消消樂游戲的代碼分享的文章就介紹到這了,更多相關(guān)C語言消消樂游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 超詳細(xì)解析C++實現(xiàn)歸并排序算法

    超詳細(xì)解析C++實現(xiàn)歸并排序算法

    歸并排序是比較穩(wěn)定的排序方法。它的基本思想是把待排序的元素分解成兩個規(guī)模大致相等的子序列。本文將用C++實現(xiàn)這一排序算法,需要的可以參考一下
    2022-09-09
  • 基于C++ OpenCV制作電子相冊查看器

    基于C++ OpenCV制作電子相冊查看器

    這篇文章主要介紹了如何使用OpenCV C++ 制作電子相冊查看器。類似于win10系統(tǒng)的“照片”功能。感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-01-01
  • C語言 操作符#與##使用方法詳解

    C語言 操作符#與##使用方法詳解

    在類函數(shù)宏中(帶參數(shù)的宏),#號作為一個預(yù)處理運算符,可以把記號轉(zhuǎn)換成字符串。##相當(dāng)于連接符,它會將兩邊的內(nèi)容連接起來,形成新的標(biāo)識符,下面請看詳細(xì)的教程
    2022-04-04
  • C語言實現(xiàn)掃雷游戲(可以自動展開)

    C語言實現(xiàn)掃雷游戲(可以自動展開)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)掃雷游戲,可以自動展開,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • c++編寫String類代碼實例

    c++編寫String類代碼實例

    這篇文章主要介紹了c++編寫String類,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • C語言實現(xiàn)單位車輛調(diào)度管理

    C語言實現(xiàn)單位車輛調(diào)度管理

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)單位車輛調(diào)度管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++實現(xiàn)LeetCode(647.回文子字符串)

    C++實現(xiàn)LeetCode(647.回文子字符串)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(647.回文子字符串),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言?如何用堆解決Topk問題

    C語言?如何用堆解決Topk問題

    TopK問題即在N個數(shù)中找出最大的前K個,這篇文章將詳細(xì)講解如何利用小根堆的方法解決TopK問題,文中代碼具有一定參考價值,快跟隨小編一起學(xué)習(xí)一下吧
    2021-12-12
  • 詳解C語言之柔性數(shù)組

    詳解C語言之柔性數(shù)組

    這篇文章主要介紹了C語言柔性數(shù)組,通過實例分析了不完整類型、結(jié)構(gòu)體及柔性數(shù)組等概念,需要的朋友可以參考下
    2021-11-11
  • C++自動析構(gòu)時的順序問題

    C++自動析構(gòu)時的順序問題

    這篇文章主要介紹了C++自動析構(gòu)時的順序,通過實例代碼給大家講解了C++ 構(gòu)造與析構(gòu)的執(zhí)行順序,代碼簡單易懂,非常不錯對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03

最新評論