每天一個(gè)C語(yǔ)言小項(xiàng)目,提升你的編程能力!
基于 EasyX 的五子棋軟件。
算法部分想了很久,也參考了網(wǎng)上的其他游戲的。原理主要就是:遍歷每個(gè)空閑的點(diǎn),根據(jù)下在那個(gè)點(diǎn)后連成的棋形來(lái)判斷其分值,再選出分值最高的位置并返回給游戲函數(shù)。
還在上小學(xué),更深層次的判定算法還沒(méi)學(xué),就先將就一下吧。
運(yùn)行效果如下:
完整的游戲源代碼如下:
#include#include #include #include #include // 類(lèi)定義 // 保存位置的類(lèi) class seat { public: int i = 0; // y 坐標(biāo) int j = 0; // x 坐標(biāo) int number = 0; // 分?jǐn)?shù) }; // 保存棋盤(pán)的類(lèi) class box { public: void draw(); // 繪制 public: int x = 0; // x 坐標(biāo) int y = 0; // y 坐標(biāo) int value = -1; // 值(黑棋:1,白棋:0,空位:-1) int modle; // 模式 bool isnew = false; // 是否有選擇框 int number = 0; // 分?jǐn)?shù) COLORREF color = WHITE; // 棋盤(pán)背景色 }; // 函數(shù)聲明 void draw(); // 繪制 void init(); // 初始化 seat findbestseat(int color); // 尋找最佳位置 void isWIN(); // 判斷輸贏 void game(); // 游戲主函數(shù) // main函數(shù) int main() { initgraph(700, 700, NOMINIMIZE); // 初始化繪圖環(huán)境 setbkcolor(WHITE); cleardevice(); setbkmode(TRANSPARENT); // 設(shè)置透明文字輸出背景 while (1) { init(); // 初始化 game(); // 游戲開(kāi)始 cleardevice(); } } // 全局變量 box BOX[19][19]; // 棋盤(pán) int win = -1; // 誰(shuí)贏了(0:白棋,1:黑棋,2:平局) int whoplay = 0; // 輪到誰(shuí)下棋了 int playercolor = 0; // 玩家顏色 int dx[4]{ 1,0,1,1 }; // - | / 四個(gè)方向 int dy[4]{ 0,1,1,-1 }; // 類(lèi)函數(shù)定義 // 繪制函數(shù) void box::draw() { COLORREF thefillcolor = getfillcolor(); // 備份填充顏色 setlinestyle(PS_SOLID, 2); // 線樣式設(shè)置 setfillcolor(color); // 填充顏色設(shè)置 solidrectangle(x, y, x + 30, y + 30); // 繪制無(wú)邊框的正方形 if (isnew) { // 如果是新下的 // 繪制邊框線 setlinecolor(LIGHTGRAY); line(x + 1, y + 2, x + 8, y + 2); line(x + 2, y + 1, x + 2, y + 8); line(x + 29, y + 2, x + 22, y + 2); line(x + 29, y + 1, x + 29, y + 8); line(x + 2, y + 29, x + 8, y + 29); line(x + 2, y + 22, x + 2, y + 29); line(x + 29, y + 29, x + 22, y + 29); line(x + 29, y + 22, x + 29, y + 29); } setlinecolor(BLACK); switch (modle) { // 以下是不同位置棋盤(pán)的樣式 case 0: line(x + 15, y, x + 15, y + 30); line(x - 1, y + 15, x + 30, y + 15); break; // * // *** // * case 1: line(x + 14, y + 15, x + 30, y + 15); setlinestyle(PS_SOLID, 3); line(x + 15, y, x + 15, y + 30); setlinestyle(PS_SOLID, 2); break; // * // *** // * case 2: line(x - 1, y + 15, x + 15, y + 15); setlinestyle(PS_SOLID, 3); line(x + 15, y, x + 15, y + 30); setlinestyle(PS_SOLID, 2); break; // * // *** // * case 3: line(x + 15, y + 15, x + 15, y + 30); setlinestyle(PS_SOLID, 3); line(x - 1, y + 15, x + 30, y + 15); setlinestyle(PS_SOLID, 2); break; // *** // * // * case 4: line(x + 15, y, x + 15, y + 15); setlinestyle(PS_SOLID, 3); line(x - 1, y + 15, x + 30, y + 15); setlinestyle(PS_SOLID, 2); break; // * // * // *** case 5: setlinestyle(PS_SOLID, 3); line(x + 15, y, x + 15, y + 15); line(x + 15, y + 15, x + 30, y + 15); setlinestyle(PS_SOLID, 2); break; // * // * // *** case 6: setlinestyle(PS_SOLID, 3); line(x + 15, y, x + 15, y + 15); line(x - 1, y + 15, x + 15, y + 15); setlinestyle(PS_SOLID, 2); break; // * // * // *** case 7: setlinestyle(PS_SOLID, 3); line(x - 1, y + 15, x + 15, y + 15); line(x + 15, y + 15, x + 15, y + 30); setlinestyle(PS_SOLID, 2); break; // *** // * // * case 8: setlinestyle(PS_SOLID, 3); line(x + 15, y + 15, x + 30, y + 15); line(x + 15, y + 15, x + 15, y + 30); setlinestyle(PS_SOLID, 2); break; // *** // * // * case 9: line(x + 15, y, x + 15, y + 30); line(x - 1, y + 15, x + 30, y + 15); setfillcolor(BLACK); setlinestyle(PS_SOLID, 1); fillcircle(x + 15, y + 15, 4); break; // * // *O* // * } switch (value) { case 0: // 白棋 setfillcolor(WHITE); setlinestyle(PS_SOLID, 1); fillcircle(x + 15, y + 15, 13); break; case 1: // 黑棋 setfillcolor(BLACK); setlinestyle(PS_SOLID, 1); fillcircle(x + 15, y + 15, 13); break; } setfillcolor(thefillcolor); // 還原填充色 } // 其他函數(shù)定義 // 繪制棋盤(pán) void draw() { int modle = 0; // 棋盤(pán)樣式 int number = 0; // 坐標(biāo)輸出的位置 // 坐標(biāo)(數(shù)值) TCHAR strnum[19][3] = { _T("1"),_T("2") ,_T("3") ,_T("4"),_T("5") ,_T("6") ,_T("7"),_T("8"),_T("9"),_T("10"), _T("11"),_T("12") ,_T("13") ,_T("14"),_T("15") ,_T("16") ,_T("17"),_T("18"),_T("19") }; // 坐標(biāo)(字母) TCHAR strabc[19][3] = { _T("A"),_T("B") ,_T("C") ,_T("D"),_T("E") ,_T("F") ,_T("G"),_T("H"),_T("I"),_T("J"), _T("K"),_T("L") ,_T("M") ,_T("N"),_T("O") ,_T("P") ,_T("Q"),_T("R"),_T("S") }; for (int i = 0, k = 0; i < 570; i += 30) { for (int j = 0, g = 0; j < 570; j += 30) { BOX[k][g].color = RGB(255, 205, 150);// 棋盤(pán)底色 // x、y 坐標(biāo) BOX[k][g].x = 65 + j; BOX[k][g].y = 50 + i; BOX[k][g].number = 0;// 初始化分?jǐn)?shù) // 棋盤(pán)樣式的判斷 if (k == 0 && g == 0) { modle = 8; } else if (k == 0 && g == 18) { modle = 7; } else if (k == 18 && g == 18) { modle = 6; } else if (k == 18 && g == 0) { modle = 5; } else if (k == 0) { modle = 3; } else if (k == 18) { modle = 4; } else if (g == 0) { modle = 1; } else if (g == 18) { modle = 2; } else if ((k == 3 && g == 3) || (k == 3 && g == 15) || (k == 15 && g == 3) || (k == 15 && g == 15) || (k == 3 && g == 9) || (k == 9 && g == 3) || (k == 15 && g == 9) || (k == 9 && g == 15) || (k == 9 && g == 9)) { modle = 9; } else { modle = 0; } BOX[k][g].modle = modle; BOX[k][g].draw(); // 繪制 if (BOX[k][g].isnew == true) { BOX[k][g].isnew = false; // 把上一個(gè)下棋位置的黑框清除 } g++; } k++; } // 畫(huà)坐標(biāo) LOGFONT nowstyle; gettextstyle(&nowstyle); settextstyle(0, 0, NULL); for (int i = 0; i < 19; i++) { outtextxy(75 + number, 35, strnum[i]); outtextxy(53, 55 + number, strabc[i]); number += 30; } settextstyle(&nowstyle); } // 對(duì)局初始化 void init() { win = -1;// 誰(shuí)贏了 for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { BOX[i][j].number = 0;// 分?jǐn)?shù) BOX[i][j].value = -1;// 值 } } } // 核心函數(shù) // 尋找最佳位置 seat findbestseat(int color) { // 評(píng)分表 int Score[3][5] = { { 0, 20, 360, 5800, 92840 }, // 防守0子 { 0, 0, 20, 360, 92840 }, // 防守1子 { 0, 0, 0, 0, 92840 } // 防守2子 }; seat bestseat; // 最佳位置 int MAXnumber[361] = { 0 }; // 最佳分?jǐn)?shù)(可能有多個(gè)) int MAXx[361] = { 0 }; // 最佳 x 坐標(biāo)(可能有多個(gè)) int MAXy[361] = { 0 }; // 最佳 y 坐標(biāo)(可能有多個(gè)) int number = 0; // 下一個(gè)最佳分?jǐn)?shù)儲(chǔ)存位置 int truenumber; // 輸出的最佳分?jǐn)?shù)位置 int nowi = 0; // 現(xiàn)在遍歷到的y坐標(biāo) int nowj = 0; // 現(xiàn)在遍歷到的x坐標(biāo) int length[4]; // 四個(gè)方向的長(zhǎng)度 int emeny[4]; // 四個(gè)方向的敵子 for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { if (BOX[i][j].value == -1) { // 遍歷每一個(gè)可能的位置 // 自己 BOX[i][j].value = color; // 嘗試下在這里 for (int k = 0; k < 4; k++) { length[k] = 0; emeny[k] = 0; nowi = i; nowj = j; while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == color) { length[k]++; nowj += dx[k]; nowi += dy[k]; } if (BOX[nowi][nowj].value == 1 - color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18) { emeny[k]++; } nowi = i; nowj = j; while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == color) { length[k]++; nowj -= dx[k]; nowi -= dy[k]; } if (BOX[nowi][nowj].value == 1 - color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18) { emeny[k]++; } length[k] -= 2; // 判斷長(zhǎng)度 if (length[k] > 4) { length[k] = 4; } BOX[i][j].number += Score[emeny[k]][length[k]] * 4 + !(!length[k]) * 20;//加分系統(tǒng) length[k] = 0; emeny[k] = 0; } // 敵人(原理同上) BOX[i][j].value = 1 - color; for (int k = 0; k < 4; k++) { length[k] = 0; emeny[k] = 0; nowi = i; nowj = j; while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == 1 - color) { length[k]++; nowj += dx[k]; nowi += dy[k]; } if (BOX[nowi][nowj].value == color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18) { emeny[k]++; } nowi = i; nowj = j; while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == 1 - color) { length[k]++; nowj -= dx[k]; nowi -= dy[k]; } if (BOX[nowi][nowj].value == color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18) { emeny[k]++; } length[k] -= 2; if (length[k] > 4) { length[k] = 4; } BOX[i][j].number += Score[emeny[k]][length[k]]; length[k] = 0; emeny[k] = 0; } BOX[i][j].value = -1; } if (BOX[i][j].number == MAXnumber[0]) { // 如果和最高分?jǐn)?shù)相同 MAXnumber[number] = BOX[i][j].number; MAXy[number] = i; MAXx[number] = j; number++; // 新增一個(gè)分?jǐn)?shù)及坐標(biāo) } if (BOX[i][j].number > MAXnumber[0]) { // 如果比最高分?jǐn)?shù)高 for (int k = 0; k < number; k++) { MAXnumber[k] = 0; MAXy[k] = 0; MAXx[k] = 0; } number = 0; MAXnumber[number] = BOX[i][j].number; MAXy[number] = i; MAXx[number] = j; number++; // 清空數(shù)組再加入 } } } // 生成隨機(jī)位置 srand(time(NULL)); truenumber = rand() % number; bestseat.i = MAXy[truenumber]; bestseat.j = MAXx[truenumber]; bestseat.number = MAXnumber[truenumber]; // 返回位置 return bestseat; } // 判斷輸贏 void isWIN() { bool isinit = true; // 是否剛剛開(kāi)局 for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { if (BOX[i][j].value != -1) { // 遍歷每個(gè)可能的位置 isinit = false; // 如果有,那么就不是剛剛開(kāi)局 int nowcolor = BOX[i][j].value; // 現(xiàn)在遍歷到的顏色 int length[4] = { 0,0,0,0 }; // 四個(gè)方向的長(zhǎng)度 for (int k = 0; k < 4; k++) { // 原理同尋找最佳位置 int nowi = i; int nowj = j; while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == nowcolor) { length[k]++; nowj += dx[k]; nowi += dy[k]; } nowi = i; nowj = j; while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == 1 - nowcolor) { length[k]++; nowj -= dx[k]; nowi -= dy[k]; } } for (int k = 0; k < 4; k++) { if (length[k] >= 5) { // 如果滿五子 if (nowcolor == playercolor) { win = playercolor; // 玩家勝 } if (nowcolor == 1 - playercolor) { win = 1 - playercolor; // 電腦勝 } } } if ((!isinit) && findbestseat(playercolor).number == 0 && findbestseat(1 - playercolor).number == 0) { // 如果不是開(kāi)局且雙方無(wú)最佳位置 win = 2; // 平局 } } } } } // 游戲主函數(shù) void game() { // 上一個(gè)鼠標(biāo)停的坐標(biāo) int oldi = 0; int oldj = 0; // 隨機(jī)化玩家顏色 srand(time(NULL)); playercolor = rand() % 2; // 繪制背景 setfillcolor(RGB(255, 205, 150)); solidrectangle(40, 25, 645, 630); // 設(shè)置字體樣式 settextstyle(30, 15, 0, 0, 0, 1000, false, false, false); settextcolor(BLACK); // 輸出標(biāo)示語(yǔ) if (playercolor == 0) { outtextxy(150, 650, _T("玩家執(zhí)白后行,電腦執(zhí)黑先行")); whoplay = 1; } else { outtextxy(150, 650, _T("玩家執(zhí)黑先行,電腦執(zhí)白后行")); whoplay = 0; } draw(); // 繪制 while (1) { NEXTPLAYER: if (whoplay == 0) { // 玩家下棋 MOUSEMSG mouse = GetMouseMsg(); // 獲取鼠標(biāo)信息 for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { if (mouse.x > BOX[i][j].x && mouse.x BOX[i][j].y && mouse.y < BOX[i][j].y + 30//判斷y坐標(biāo) && BOX[i][j].value == -1)//判斷是否是空位置 { // 如果停在某一個(gè)空位置上面 if (mouse.mkLButton) { // 如果按下了 BOX[i][j].value = playercolor; // 下棋 BOX[i][j].isnew = true; // 新位置更新 oldi = -1; oldj = -1; // 下一個(gè)玩家 whoplay = 1; goto DRAW; } // 更新選擇框 BOX[oldi][oldj].isnew = false; BOX[oldi][oldj].draw(); BOX[i][j].isnew = true; BOX[i][j].draw(); oldi = i; oldj = j; } } } } else { // 電腦下棋 seat best; best = findbestseat(1 - playercolor); // 尋找最佳位置 if (best.number == 0) { // 開(kāi)局情況 int drawi = 9; int drawj = 9; while (BOX[drawi][drawj].value != -1) { drawi--; drawj++; } BOX[drawi][drawj].value = 1 - playercolor; BOX[drawi][drawj].isnew = true; } else { BOX[best.i][best.j].value = 1 - playercolor;//下在最佳位置 BOX[best.i][best.j].isnew = true; } whoplay = 0; goto DRAW; // 輪到下一個(gè) } } DRAW: // 繪制 isWIN(); // 檢測(cè)輸贏 draw(); if (win == -1) { // 如果沒(méi)有人勝利 Sleep(500); goto NEXTPLAYER; // 前往下一個(gè)玩家 } // 勝利處理 settextcolor(RGB(0, 255, 0)); Sleep(1000); if (win == 0) { outtextxy(320, 320, _T("白勝")); } if (win == 1) { outtextxy(320, 320, _T("黑勝")); } if (win == 2) { outtextxy(320, 320, _T("平局")); } // 給反應(yīng)時(shí)間 Sleep(5000); return; }
大家趕緊去動(dòng)手試試吧!
審核編輯:湯梓紅
-
游戲
+關(guān)注
關(guān)注
2文章
749瀏覽量
26338 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7614瀏覽量
137249 -
編程
+關(guān)注
關(guān)注
88文章
3633瀏覽量
93854 -
源碼
+關(guān)注
關(guān)注
8文章
649瀏覽量
29312 -
C++
+關(guān)注
關(guān)注
22文章
2113瀏覽量
73742
原文標(biāo)題:【項(xiàng)目實(shí)戰(zhàn)】輕松實(shí)現(xiàn)C/C++大作業(yè):五子棋游戲!附帶源碼
文章出處:【微信號(hào):cyuyanxuexi,微信公眾號(hào):C語(yǔ)言編程學(xué)習(xí)基地】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論