C/C++ 五子棋遊戲

今天分享一篇使用vs2010,配合easy-X圖形庫編寫的五子棋控制檯遊戲。
自帶遊戲資源。 且免費下載

下面是百度網盤下載連接:
鏈接:https://pan.baidu.com/s/1MMJKNDvNJy5UvT9mtM30xw
提取碼:4rvv

遊戲棋盤是15 * 15 的,應該符合很多大專院校的期末大作業!!!

具體過程就不詳細解釋了,等哪天心情好就把他完善一下,使用C++的面向對象在搞一遍。

代碼中關鍵地方也有註釋,自己去看!!!

代碼一共650行,其中很多地方都還可以去優化的,寫了很多重複的代碼,也寫了很多垃圾代碼。

不過遊戲界面基本完善,遊戲功能該有還是會有,比如 音樂, 悔棋等。

遊戲還有一個BUG,當棋盤下滿棋子也還沒有分出勝負,程序是不會做任何操作的,唯有點擊重新開始遊戲或者退出遊戲或者悔棋。我就懶得再加代碼了,其實很簡單的,有興趣的小夥也可以自行完善一下!
思路:再寫一個函數用於判斷數組是否存滿了(數組中已經沒有0值了),如果滿了,就顯示“棋盤已滿”的字體,然後等待用戶點擊開始遊戲或者退出遊戲即可。重新開始遊戲後記得回覆白棋先出,將悔棋記錄刪除掉,將數組全部值都賦值0.

或許還有其他的BUG是我沒有發現的,有興趣的也可以找一下!!!

另外代碼運行需要的文件可以點擊我的頭像去下載,免費的!
或者點這裏

對了,代碼中有使用到vector容器作爲悔棋記錄,不懂的點這裏

不說了,上代碼:

#include <iostream>
#include <Windows.h>
#include <graphics.h>	// 圖形庫
#include <vector>		// 動態數組,該地方用於悔棋
#include <mmsystem.h>	// 背景音樂

// 加載 winmm.lid庫文件
#pragma comment(lib,"winmm.lib")


using namespace std;

#define GRAPHICS_X 880
#define GRAPHICS_Y 780

// 遊戲棋盤
#define PLATE_X	 30				//////
#define PLATE_Y  50				/////	棋盤的矩形的座標值
#define PLATE_XX 50*14+PLATE_X	////
#define PLATE_YY 50*15			///
// 偏移量
#define	OFFSET   50	// 每個棋盤空格相隔50像素

// 記錄悔棋的容器
typedef struct VECTOR {
	vector<int> x;
	vector<int> y;
};
// 悔棋標誌
VECTOR pullBack;	// 記錄棋盤上一下好的棋子的座標,好用於悔棋



// 遊戲初始化界面
void initgraphGame(void) {
	// 初始化圖像界面
	initgraph(1080, 720);

	// 將圖片應用於界面中
	loadimage(0, _T("begin-1.jpg"));

	// 設置字體顏色
	settextcolor(RGB(255, 255, 255));

	// 設置字體
	settextstyle(35, 0, _T("微軟雅黑"));

	// 設置字體的背景顏色爲透明
	setbkmode(TRANSPARENT);

	// 寫字
	outtextxy(415, 60, _T("正在加載遊戲...")); 

	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 5);

	// 畫一個空心矩形
	rectangle(220, 195, 820, 305);

	// 設置字體顏色
	settextcolor(RGB(0, 0, 0));

	// 設置字體
	settextstyle(120, 0, _T("微軟雅黑"));

	// 寫字
	outtextxy(244, 190, _T("編程使我快樂")); 

	// 設置字體顏色
	settextcolor(RGB(255, 200, 88));

	// 寫字
	outtextxy(110, 410, _T("歡迎進入五子棋遊戲")); 

	Sleep(3000);
	closegraph();
}


// 遊戲背景音樂
void music(void) {
	mciSendString("play Sunburst.mp3 repeat", 0, 0, 0);
}

// 背景音樂標識
bool gameMusicFlag = true;

// 遊戲背景音樂開關
void musicFlag(void) {
	if (gameMusicFlag) {
		gameMusicFlag = false;
		mciSendString("pause Sunburst.mp3",NULL,0,NULL);	// 暫停
		//mciSendString("close Sunburst.mp3",NULL,0,NULL);	// 停止
	} else {
		gameMusicFlag = true;
		music();
	}
}



// 棋盤繪製
void plate(void) {
	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 2);

	for (int i=0; i<13; i++) {
		//	固定值加上一個偏移量
		line(PLATE_X, PLATE_Y+(OFFSET*(i+1)), PLATE_XX, PLATE_Y+(OFFSET*(i+1)));	// 行
		line(PLATE_X+(OFFSET*(i+1)), PLATE_Y, PLATE_X+(OFFSET*(i+1)), PLATE_YY);	// 縱
	}
}

// 遊戲 開始 和 結束 和 悔棋 和 音樂開關 和 五子棋 繪製
void gameButton(void) {
	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 2);

	// 設置字體顏色
	settextcolor(RGB(0, 0, 0));

	// 設置字體
	settextstyle(25, 0, _T("微軟雅黑"));

	// 字體外的方框
	rectangle(760, 175, 850, 225);
	
	// 寫字
	outtextxy(767, 185, _T("音樂開關")); 


	// 字體外的方框
	rectangle(760, 250, 850, 300);
	
	// 寫字
	outtextxy(767, PLATE_Y*5+10, _T("開始遊戲")); 

	// 字體外的方框
	rectangle(760, 450, 850, 500);

	// 寫字
	outtextxy(767, 460, _T("結束遊戲")); 

	// 字體外的方框
	rectangle(760, 650, 850, 700);

	// 寫字
	outtextxy(785, 662, _T("悔棋")); 


	// 設置字體
	settextstyle(30, 0, _T("微軟雅黑"));

	// 五子棋
	outtextxy(700/2, 10, _T("五子棋"));
}

// 開始遊戲提示
void gameHints(void) {
	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 2);

	// 設置字體顏色
	settextcolor(RGB(0, 0, 0));

	// 設置字體
	settextstyle(28, 0, _T("微軟雅黑"));

	// 字體外的方框
	rectangle(760, 50, 850, 150);
	
	// 寫字
	outtextxy(775, 65, _T("請點擊")); 
	outtextxy(763, 100, _T("開始遊戲")); 
}

// 清楚提示
void deleteHints(void) {
	IMAGE image;
	loadimage(&image, _T("cheng.jpg"));
	putimage(758, 48, &image);
}

// 遊戲界面
void gameInterface(void) {
	// 初始化圖像界面
	initgraph(GRAPHICS_X, GRAPHICS_Y);

	// 設置圖像的背景顏色
	setbkcolor(RGB(255,200,88));
	// 應用到圖像中
	cleardevice();

	// 設置畫筆顏色
	setlinecolor(RGB(0,0,0));

	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 3);

	// 畫一個空心矩形
	rectangle(PLATE_X, PLATE_Y, PLATE_XX, PLATE_YY);

	// 畫棋板
	plate();

	// 遊戲按鈕
	gameButton();

	// 開始遊戲提示
	gameHints();
}

// 遊戲選手
typedef struct PLAYER {
	int white;
	int black;
};
PLAYER player;	// 用於左上角提示選手下棋

// frame of reference 座標
typedef struct FOR {
	int x;
	int y;
};
FOR fofr;	// 用於更新數組

// 鼠標座標
typedef struct MOUSES {
	int x;
	int y;
};
MOUSES mouses;	// 用於下棋

int Map[15][15] = {		// int Map[15][15] = {0};	<== 可以寫成這樣
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};


IMAGE imageBlack;	// 黑棋圖片存儲變量
IMAGE imageWhite;	// 白棋圖片存儲變量
// 遊戲選手顯示
void gamePlayerShow(void) {
	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 2);

	// 設置字體
	settextstyle(30, 0, _T("微軟雅黑"));

	// 字體外的方框
	rectangle(750, 40, 860, 160);
	
	// 清除提示
	deleteHints();

	if (player.white) {
		// 設置字體顏色
		settextcolor(RGB(255, 255, 255));

		// 寫字
		outtextxy(780, 52, _T("白方")); 
		outtextxy(780, 80, _T("下棋"));

		// 預先加載圖片
		loadimage(&imageWhite, _T("white.jpg"), 30, 30);
		// 顯示棋子
		putimage(790, 110, &imageWhite);

	} else if (player.black) {
		// 設置字體顏色
		settextcolor(RGB(0, 0, 0));

		// 寫字
		outtextxy(780, 52, _T("黑方")); 
		outtextxy(780, 80, _T("下棋")); 

		// 預先加載圖片
		loadimage(&imageBlack, _T("black.jpg"), 30, 30);
		// 顯示棋子
		putimage(790, 110, &imageBlack);

	} else {
		outtextxy(780, 52, _T("第三方")); 
		outtextxy(780, 80, _T("下棋")); 
	}
}



// 鼠標事件:點擊開始遊戲與退出遊戲
bool beginGame(void) {
	MOUSEMSG mouse;	// 鼠標變量

	while (1) {
		mouse = GetMouseMsg();	// 調用系統的函數

		// 如果有鼠標左鍵點擊操作
		if (mouse.uMsg == WM_LBUTTONDOWN) {
			if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 250 && mouse.y < 300)) {
				return true;
			} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 450 && mouse.y < 500)) {
				return false;
			} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 175 && mouse.y < 225)) {
				musicFlag();	// 音樂控制
				continue;
			}
		}

		Sleep(10);	// 讓CPU休息一下下
	}
}



// 重新開始遊戲
void newGame(void) {
	// 重新開始遊戲
	gameInterface();	// 初始化地圖
	for (int i=0; i<15; i++) {	// 地圖全部置爲零
		for (int j=0; j<15; j++) {
			Map[i][j] = 0;
		}
	}

	// 重新開始遊戲,將悔棋標誌清空
	pullBack.x.clear();
	pullBack.y.capacity();

	// 重新開始遊戲之後,恢復白棋先出
	player.black = 0;
	player.white = 1;
}



// 鼠標點擊操作
int ifbool(void) {
	MOUSEMSG mouse;	// 鼠標變量

	while (1) {
		mouse = GetMouseMsg();	// 調用系統的函數

		// 如果有鼠標左鍵點擊操作
		if (mouse.uMsg == WM_LBUTTONDOWN) {		// 下棋操作
			for (int i=0; i<15; i++) {
				for (int j=0; j<15; j++) {		// 判斷鼠標的座標是否在該區域
					if ((mouse.x >= i*50+PLATE_X-15 && mouse.x <= i*50+PLATE_X+15) &&
						(mouse.y >= j*50+PLATE_Y-15 && mouse.y <= j*50+PLATE_Y+15)) {

							// 等於零,該區域沒有棋子
							if (Map[i][j] == 0) {
								fofr.x = i;		// 用於更新數組
								fofr.y = j;

								mouses.x = i*50+PLATE_X;	// 用於下棋
								mouses.y = j*50+PLATE_Y;

								pullBack.x.push_back(i);	// 用於悔棋
								pullBack.y.push_back(j);
								return 1;

							} else {
								return 2;
							}

					} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 250 && mouse.y < 300)) {	// 重新開始遊戲
						newGame();	// 重新開始遊戲函數
						return 3;

					} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 650 && mouse.y < 700)) {		// 悔棋操作
						if (pullBack.x.size() > 0 && pullBack.y.size() > 0) {	// 大於零,說明有棋子記錄,可以悔棋
							int x = pullBack.x[pullBack.x.size()-1];
							int y = pullBack.y[pullBack.y.size()-1];

							// 刪除容器上的一個悔棋記錄
								pullBack.x.pop_back();
								pullBack.y.pop_back();

				

								Map[x][y] = 0;
								// 重新加載遊戲
								gameInterface();	// 初始化地圖

	
								for (int i=0; i<15; i++) {	// 將地圖上的棋子擺回來
									for (int j=0; j<15; j++) {
										if (Map[i][j] == 1) {
											loadimage(&imageWhite, _T("white.jpg"), 30, 30);
											putimage(i*50+PLATE_X-15, j*50+PLATE_Y-15, &imageWhite);
				
										} else if (Map[i][j] == 2) {
											loadimage(&imageBlack, _T("black.jpg"), 30, 30);
											putimage(i*50+PLATE_X-15, j*50+PLATE_Y-15, &imageBlack);
											
										}
									}
								}

								if (player.black == 1) {
									player.black = 0;
									player.white = 1;
								} else {
									player.black = 1;
									player.white = 0;
								}
								return 4;
						}
						
					} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 450 && mouse.y < 500)) {		// 推出遊戲操作
						// 結束程序
						closegraph();
						exit(1);

					} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 175 && mouse.y < 225)) {
						musicFlag();	// 音樂控制
						continue;
					} 
				}
			}
		}

		Sleep(10);
	}
}


// 下棋
void playChess(void) {
	
	if (player.black) { // 如果爲真
		// 預先加載圖片
		loadimage(&imageBlack, _T("black.jpg"), 30, 30);
		// 將棋子下到棋板上面
		putimage(mouses.x-15, mouses.y-15, &imageBlack);
		player.black = 0;	// 下棋順序標誌
		player.white = 1;	// 下棋順序標誌
		Map[fofr.x][fofr.y] = 2;	// 更新數組
	} else {
		// 預先加載圖片
		loadimage(&imageWhite, _T("white.jpg"), 30, 30);
		// 將棋子下到棋板上面
		putimage(mouses.x-15, mouses.y-15, &imageWhite);
		player.black = 1;
		player.white = 0;
		Map[fofr.x][fofr.y] = 1;
	}
}

// 提示該處已有棋子
void hint(void) {
	// 清除提示
	deleteHints();

	// 設置畫筆粗細
	setlinestyle(PS_SOLID, 2);

	// 設置字體顏色
	settextcolor(RGB(0, 0, 0));

	// 設置字體
	settextstyle(25, 0, _T("微軟雅黑"));

	// 字體外的方框
	rectangle(760, 50, 850, 150);
	
	// 寫字
	outtextxy(788, 52, _T("此處")); 
	outtextxy(768, 80, _T("已有棋子")); 


	// 確認 字體外的方框
	rectangle(765, 110, 845, 145);
	// 設置字體
	settextstyle(25, 0, _T("微軟雅黑"));
	// 寫字
	outtextxy(790, 115, _T("確認")); 


	MOUSEMSG mouse;	// 鼠標變量

	while (1) {
		mouse = GetMouseMsg();	// 調用系統的函數

		// 如果有鼠標左鍵點擊操作
		if (mouse.uMsg == WM_LBUTTONDOWN) {
			if ((mouse.x > 765 && mouse.x < 845) && (mouse.y > 90 && mouse.y < 145)) {
				// 清除提示
				deleteHints();
				break;

			} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 250 && mouse.y < 300)) {
						newGame();	// 重新開始遊戲函數
						break;

					} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 450 && mouse.y < 500)) {
						// 結束程序
						closegraph();
						exit(1);

					} else if ((mouse.x > 760 && mouse.x < 850) && (mouse.y > 175 && mouse.y < 225)) {
						musicFlag();	// 音樂控制
						continue;
					}
		}

		Sleep(10);
	}
}


void playGames(void);
// 執行勝利界面
void Victory(int victory) {
	Sleep(300);
	//closegraph();
	//initgraph(680, 417);

	//IMAGE image;

	//// 加載圖片
	//loadimage(&image, _T("timg.jpg"));
	//putimage(0, 0, &image);

	settextstyle(77, 0, _T("微軟雅黑"));

	// 設置字體的背景顏色爲透明
	setbkmode(TRANSPARENT);

	if (victory == 1) {
		settextcolor(RGB(255, 255, 255));
		outtextxy(180, 150, _T("恭喜白棋獲勝"));

	} else if (victory == 2) {
		settextcolor(RGB(0, 0, 0));
		outtextxy(180, 150, _T("恭喜黑棋獲勝"));

	} else {
		outtextxy(200, 150, _T("參數有問題!"));
	}


	// 點擊開始遊戲
	if (beginGame()) {
		newGame();	// 重新加載遊戲

		// 玩遊戲
		playGames();
	} else {
		closegraph();
		exit(1);
	}

	/*system("pause");
	closegraph();
	exit(1);*/
}

// 判斷是否下完了五個一樣的棋子
void ifVictory(void) {
	for (int i=0; i<15; i++) {
		for (int j=0; j<15; j++) {

			// 核心算法,遊戲棋子判斷
			if ((Map[i][j]==1 && Map[i-1][j-1]==1 && Map[i-2][j-2]==1 && Map[i-3][j-3]==1 && Map[i-4][j-4]==1) ||		// 左上角
				(Map[i][j]==1 && Map[i+1][j-1]==1 && Map[i+2][j-2]==1 && Map[i+3][j-3]==1 && Map[i+4][j-4]==1) ||		// 右上角
				(Map[i][j]==1 && Map[i-1][j+1]==1 && Map[i-2][j+2]==1 && Map[i-3][j+3]==1 && Map[i-4][j+4]==1) ||		// 左下角
				(Map[i][j]==1 && Map[i+1][j+1]==1 && Map[i+2][j+2]==1 && Map[i+3][j+3]==1 && Map[i+4][j+4]==1) ||		// 右下角
				(Map[i][j]==1 && Map[i][j-1]==1 && Map[i][j-2]==1 && Map[i][j-3]==1 && Map[i][j-4]==1) ||				// 上
				(Map[i][j]==1 && Map[i][j+1]==1 && Map[i][j+2]==1 && Map[i][j+3]==1 && Map[i][j+4]==1) ||				// 下
				(Map[i][j]==1 && Map[i-1][j]==1 && Map[i-2][j]==1 && Map[i-3][j]==1 && Map[i-4][j]==1) ||				// 左
				(Map[i][j]==1 && Map[i+1][j]==1 && Map[i+2][j]==1 && Map[i+3][j]==1 && Map[i+4][j]==1)) {				// 右
					Victory(1);	// 執行勝利代碼

			} else if ((Map[i][j]==2 && Map[i-1][j-1]==2 && Map[i-2][j-2]==2 && Map[i-3][j-3]==2 && Map[i-4][j-4]==2) ||		// 左上角
					   (Map[i][j]==2 && Map[i+1][j-1]==2 && Map[i+2][j-2]==2 && Map[i+3][j-3]==2 && Map[i+4][j-4]==2) ||		// 右上角
					   (Map[i][j]==2 && Map[i-1][j+1]==2 && Map[i-2][j+2]==2 && Map[i-3][j+3]==2 && Map[i-4][j+4]==2) ||		// 左下角
				   	   (Map[i][j]==2 && Map[i+1][j+1]==2 && Map[i+2][j+2]==2 && Map[i+3][j+3]==2 && Map[i+4][j+4]==2) ||		// 右下角
					   (Map[i][j]==2 && Map[i][j-1]==2 && Map[i][j-2]==2 && Map[i][j-3]==2 && Map[i][j-4]==2) ||				// 上
					   (Map[i][j]==2 && Map[i][j+1]==2 && Map[i][j+2]==2 && Map[i][j+3]==2 && Map[i][j+4]==2) ||				// 下
					   (Map[i][j]==2 && Map[i-1][j]==2 && Map[i-2][j]==2 && Map[i-3][j]==2 && Map[i-4][j]==2) ||				// 左
					   (Map[i][j]==2 && Map[i+1][j]==2 && Map[i+2][j]==2 && Map[i+3][j]==2 && Map[i+4][j]==2)) {				// 右
							Victory(2);	// 執行勝利代碼
			}
		}
	}
}

// 玩遊戲
void playGames(void) {
	while (1) {
		gamePlayerShow();		// 選手下棋提示	

		int keyword = ifbool();	// 鼠標點擊棋盤

		if (keyword == 1) {
			playChess();	// 下棋
			ifVictory();	// 判斷是否下完了五個一樣的棋子

		} else if (keyword == 2) {
			hint();			// 提示該處已有棋子

		} else if (keyword == 3) {
			// 已執行界面重新加載,清楚開始遊戲提示
			deleteHints();
		} else if (keyword == 4) {
			// 已執行界面重新加載,清楚開始遊戲提示
			deleteHints();
		}
	}
}



int main(void) {
	// 白色爲1,白棋先出
	player.black = 0;
	player.white = 1;


	// 加載遊戲
	initgraphGame();

	// 背景音樂
	music();

	// 遊戲界面
	gameInterface();

	// 開始遊戲
	if (beginGame()) {
		// 玩遊戲
		playGames();
	}

	return 0;
}

最後附上游戲截圖:
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章