C++ 中國(guó)象棋的實(shí)現(xiàn)流程詳解
中國(guó)象棋的中國(guó)棋文化,也是中華民族的文化瑰寶,它源遠(yuǎn)流長(zhǎng),趣味濃厚,基本規(guī)則簡(jiǎn)明易懂。中國(guó)象棋在中國(guó)的群眾中基礎(chǔ)遠(yuǎn)遠(yuǎn)超過(guò)圍棋,是普及最廣的棋類(lèi)項(xiàng)目,中國(guó)象棋已流傳到十幾個(gè)國(guó)家和地區(qū)。 中國(guó)象棋使用方形格狀棋盤(pán),圓形棋子共有32個(gè),紅黑二色各有16個(gè)棋子,擺放和活動(dòng)在交叉點(diǎn)上。雙方交替行棋,先把對(duì)方的將(帥)“將死”的一方獲勝。
我們今天就來(lái)看看我們自己能不能寫(xiě)出這樣一個(gè)游戲呢?
今天就不話不多說(shuō)了,先說(shuō)一下,今天我們做的是一個(gè)簡(jiǎn)易版的單機(jī)中國(guó)象棋,希望大家理解,聯(lián)網(wǎng)對(duì)弈的話需要用到的知識(shí)過(guò)多,數(shù)據(jù)庫(kù)以及網(wǎng)絡(luò)協(xié)議這些大部分同學(xué)都沒(méi)有學(xué),所以我們今天就簡(jiǎn)單的實(shí)現(xiàn)《中國(guó)象棋》的簡(jiǎn)單對(duì)弈,主要是希望同學(xué)們可以理解其中的邏輯關(guān)系,之后就可以更好的去完善
行吧,我們現(xiàn)在就開(kāi)始吧?。?!
今天先出場(chǎng)的就不是我們的老朋友結(jié)構(gòu)體了,而是我們的新朋友枚舉類(lèi)型
enum Pieces //棋子 { NONE = -1, 車(chē), 馬, 象, 士, 將, 砲, 卒, 俥, 馬, 相, 仕, 帥, 炮, 兵, BEGIN, END, }; //給id賦值 enum Pieces redChess[] = { 車(chē), 馬, 象, 士, 將, 砲, 卒 }; enum Pieces blackChess[] = { 俥, 馬, 相, 仕, 帥, 炮, 兵 }; //繪制時(shí)轉(zhuǎn)化成字符串 const char* ChessName[] = { "車(chē)","馬","象","士","將","砲","卒","俥", "馬", "相", "仕", "帥", "炮", "兵" };
接下來(lái)出場(chǎng)的是我們的老朋友結(jié)構(gòu)體
//每一個(gè)棋子的屬性 struct Chess { enum Pieces id; //棋子名稱(chēng) DWORD type; //棋子類(lèi)型,紅?黑? short x; short y; bool isRiver; //是否過(guò)了河 }; //游戲地圖 struct Chess map[ROW][COL]; struct State { int begr; int begc; int endr; int endc; int state; }state = {-1,-1,-1,-1,BEGIN};
我們的初始化函數(shù),一定要想好其中的邏輯
//初始化數(shù)據(jù) void init() { //遍歷地圖 for (size_t i = 0; i < ROW; i++) { size_t temp = 0; for (size_t k = 0; k < COL; k++) { map[i][k].id = NONE; //先把棋子置為沒(méi)有 if (i <= 4) //黑棋子 { map[i][k].type = BLACK; if (i == 0) //放置第一行的棋子 { //0 1 2 3 4 if (k <= 4) { temp = k; } // 3 2 1 0 else { // k == 5 temp = 4 - (k - 4); /* 4 - (5-4) //3 4 - (6-4) //2 4 - (7-4) //1 4 - (8-4) //0 */ } map[i][k].id = blackChess[temp]; } //設(shè)置炮 if (i == 2 && (k == 1 || k == 7)) { map[i][k].id = blackChess[5]; } //設(shè)置兵 if (i == 3 && k % 2 == 0) { map[i][k].id = blackChess[6]; } } else //紅棋 { map[i][k].type = RED; if (i == 9) //放置第一行的棋子 { //0 1 2 3 4 if (k <= 4) { temp = k; } // 3 2 1 0 else { // k == 5 temp = 4 - (k - 4); /* 4 - (5-4) //3 4 - (6-4) //2 4 - (7-4) //1 4 - (8-4) //0 */ } map[i][k].id = redChess[temp]; } //設(shè)置炮 if (i == 7 && (k == 1 || k == 7)) { map[i][k].id = redChess[5]; } //設(shè)置兵 if (i == 6 && k % 2 == 0) { map[i][k].id = redChess[6]; } } map[i][k].isRiver = false; map[i][k].x = k * GRID_SIZE + INTERVAL; map[i][k].y = i * GRID_SIZE + INTERVAL; } } }
接下來(lái)是我們的繪制函數(shù)
//繪制 void draw() { setfillcolor(RGB(252, 215, 162)); setlinestyle(PS_SOLID, 2); //設(shè)置文字的樣式 settextstyle(30, 0, "楷體"); for (size_t i = 0; i < ROW; i++) { for (size_t k = 0; k < COL; k++) { if (map[i][k].id == NONE) continue; settextcolor(map[i][k].type); setlinecolor(map[i][k].type); //繪制棋子 fillcircle(map[i][k].x, map[i][k].y, 30); fillcircle(map[i][k].x, map[i][k].y, 25); outtextxy(map[i][k].x - 15, map[i][k].y - 15, ChessName[map[i][k].id]); } } }
后面是我們的重點(diǎn),鼠標(biāo)控制函數(shù),以后類(lèi)似的游戲項(xiàng)目都會(huì)有這樣的函數(shù),好好理解
//鼠標(biāo)操作 void mouseEvent() { ExMessage msg; //定義消息結(jié)構(gòu)體變量 if(peekmessage(&msg, EM_MOUSE)) { if (msg.message == WM_LBUTTONDOWN) //鼠標(biāo)左鍵按下 { //通過(guò)鼠標(biāo)坐標(biāo)得出點(diǎn)擊的數(shù)組的下標(biāo) //k * GRID_SIZE + INTERVAL = x; int col = (msg.x - INTERVAL) / GRID_SIZE; int row = (msg.y - INTERVAL) / GRID_SIZE; //下標(biāo)校準(zhǔn) if (msg.x > map[row][col].x + 30 && msg.y < map[row][col].y + 30) { col++; } if (msg.x < map[row][col].x + 30 && msg.y > map[row][col].y + 30) { row++; } if (msg.x > map[row][col].x + 30 && msg.y > map[row][col].y + 30) { row++; col++; } //printf("(%d %d)\n", row, col); if (state.state == BEGIN) { state.begr = row; state.begc = col; state.state = END; } else if (state.state == END) { state.endr = row; state.endc = col; state.state = BEGIN; } chessMove(); } } }
重點(diǎn)中的重點(diǎn),棋子的移動(dòng)函數(shù),游戲的規(guī)則也就在這里體現(xiàn)出來(lái)
//移動(dòng)棋子 void chessMove() { printf("beg(%d %d) end(%d %d)\n", state.begr, state.begc, state.endr, state.endc); bool canMove = false; //什么情況下能夠移動(dòng)棋子 if (!(state.begr == state.endr && state.begc == state.endc) && //點(diǎn)擊的不是同一個(gè)棋子 state.endr!=-1 && state.begr!=-1&& //下標(biāo)必須合法 map[state.begr][state.begc].id != NONE//沒(méi)有棋子不能移動(dòng) /*&&map[state.begr][state.begc].type != map[state.endr][state.endc].type*/) //不能自己吃自己 { switch (map[state.begr][state.begc].id) { case 車(chē): case 俥: if (state.begr == state.endr || state.begc == state.endc) { //起始點(diǎn)和結(jié)束點(diǎn)之間是否有阻礙 if (hasBlock(&state)) { canMove = true; } } break; case 馬: case 馬: break; case 象: case 相: break; case 士: case 仕: break; case 將: case 帥: break; case 砲: case 炮: break; case 卒: case 兵: break; default: break; } if (canMove) { printf("canMove\n"); map[state.endr][state.endc].id = map[state.begr][state.begc].id; map[state.begr][state.begc].id = NONE; map[state.endr][state.endc].isRiver = map[state.begr][state.begc].isRiver; map[state.endr][state.endc].type = map[state.begr][state.begc].type; } } }
最后就是我們的主函數(shù),進(jìn)行調(diào)用,讓項(xiàng)目運(yùn)行起來(lái)
int main() { //創(chuàng)建圖形窗口 initgraph(740, 820,EW_SHOWCONSOLE); //設(shè)置背景模式 setbkmode(TRANSPARENT); //貼棋盤(pán) IMAGE img_board; loadimage(&img_board, "./res/ChessBoard.png"); init(); //雙緩沖繪圖,防止閃屏 BeginBatchDraw(); while (true) { cleardevice(); putimage(0, 0, &img_board); draw(); mouseEvent(); FlushBatchDraw(); } EndBatchDraw(); getchar(); return 0; }
這樣一個(gè)簡(jiǎn)易版的《中國(guó)象棋》游戲項(xiàng)目就解決啦,重點(diǎn)就是邏輯,一定要想清楚,想要實(shí)現(xiàn)聯(lián)網(wǎng)的同學(xué)就要更加的去想清楚,以及去提高自己的能力,好啦,希望可以讓大家從中感受到編程的快樂(lè)吧,也希望大家可以給UP主一個(gè)關(guān)注,非常感謝大家了?。?!
到此這篇關(guān)于C++ 中國(guó)象棋的實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)C++ 中國(guó)象棋內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入解析Radix Sort基數(shù)排序算法思想及C語(yǔ)言實(shí)現(xiàn)示例
基數(shù)排序和桶排序、計(jì)數(shù)排序共同是三種最常用的線性排序算法,這里我們就來(lái)深入解析Radix Sort基數(shù)排序算法思想及C語(yǔ)言實(shí)現(xiàn)示例,需要的朋友可以參考下2016-07-07C++通過(guò)類(lèi)實(shí)現(xiàn)控制臺(tái)貪吃蛇
這篇文章主要為大家詳細(xì)介紹了C++通過(guò)類(lèi)實(shí)現(xiàn)控制臺(tái)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04C語(yǔ)言單鏈表實(shí)現(xiàn)多項(xiàng)式相加
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言單鏈表實(shí)現(xiàn)多項(xiàng)式相加,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Qt數(shù)據(jù)庫(kù)應(yīng)用之實(shí)現(xiàn)數(shù)據(jù)分組導(dǎo)出
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)數(shù)據(jù)庫(kù)數(shù)據(jù)分組導(dǎo)出,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以了解一下2022-06-06C++實(shí)現(xiàn)簡(jiǎn)單班級(jí)成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單班級(jí)成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02vscode使用cmake時(shí)將命令行參數(shù)傳遞給調(diào)試目標(biāo)的方法
這篇文章主要介紹了vscode使用cmake時(shí)將命令行參數(shù)傳遞給調(diào)試目標(biāo),下面介紹了一個(gè)示例,將參數(shù)first_arg, second-arg和third arg傳遞給程序(此處需要注意,third arg中間雖然存在空格,但是仍然被視作一個(gè)參數(shù)),需要的朋友參考下吧2024-03-03C語(yǔ)言的隨機(jī)數(shù)rand()函數(shù)詳解
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的隨機(jī)數(shù)rand()函數(shù),使用數(shù)據(jù)庫(kù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02