C/C++:实现象棋游戏
-
大體思路
采用面相過程的設計方式實現,類似于我們平時做的課程設計,實現這樣的小游戲無非就是多了圖形處理庫。這里使用的是acllib圖形庫。設計這種小游戲,首先要從宏觀上去認識:象棋,要有棋盤,要有棋子,棋子要移動。
對于棋盤,十行九列畫出即可。
對于棋子,分黑紅兩方,按照指定位置畫出。
如何移動棋子,我們有mouseEvent函數。初始化棋盤棋子:initmap,initpaint
利用鼠標實現棋子移動分兩步(mouseEvent):
第一次點擊,記錄點擊棋子的信息
第二次點擊,將第一次點擊記錄的棋子信息移動到第二次點擊的位置。
最后在添加億點細節。 -
首先畫棋盤——chessboard()
-
初始化棋子信息——initmp()
-
將棋子畫到棋盤上——initpaint()
-
注冊鼠標,通過鼠標點擊不同位置實現棋子的移動(按照象棋行棋規范)——mouseEvent(int x, int y, int button, int e)x、y為點擊位置,button(鼠標左右鍵與滑輪)、e(點擊或抬起)為事件。
-
行棋規范——judge_piece(int x, int y)代表能否從上一步走到x,y處。
此外,實現象棋必然缺不了人機對戰。對于人機算法我們可以采用最簡單的遍歷。每次遍歷獲取所有人機方棋子能走的地方,然后根據評估函數找出這些步中對人機方來說收益最大的一步。思路很簡單,但是想寫出走一步看很多步的算法也很難。首先評估函數要盡量具有代表性,這直接決定了人機的棋力;其次需要迭代遍歷,這樣次數多了時間復雜度就會很高。
這里只寫了走一步看一步的人機代碼供參考,更深入的可以自行去了解:
1、void Get_All_path()——獲取人機所有可能走的方式(將step存入向量v中)
2、int calculate_value()——評估函數
3、void Get_max_way()——得到對人機最有利的那一步(傳到prex,prey與nowx,nowy中,即從pre走到now)。
不含人機的代碼如下:
#include"acllib.h" #include<math.h> #include<stdio.h> #include<queue> #define INTERVAL 50 using namespace std; ACL_Image chessimg; const double pi = 3.14; //左上角為:(102,100) // width:55 //height:55 //棋盤大小:440*495 //棋子半徑:20 const char* chessname[] = { "車","馬","象","士","將","炮","卒","車","馬","相","仕","帥","砲","兵" }; struct piece {int x, y;int index;int is;char color;int pos;//兵 卒是否過河int row, col; }; deque<piece>q;//悔棋——三步 void paint(piece s); struct piece mp[10][9]; void initmp(); void initpaint(); void mouseEvent(int x, int y, int button, int e); void paint_rect(int tmpx, int tmpy); int judge_piece(int x, int y); void chessboard(); int mouseflag = 0; int prex, prey; int black_general_x = 0, black_general_y = 4, black_general_isexist = 1; int red_general_x = 9, red_general_y = 4, red_general_isexist = 1; piece tmp; int judge_general(int x, int y); int Setup() {//initConsole();initWindow("chess", DEFAULT, DEFAULT, 650, 701);chessboard();//loadImage("qipan.bmp", &chessimg);/*beginPaint();putImageScale(&chessimg, 0, 0, 650, 701);endPaint();*/registerMouseEvent(mouseEvent);//paint(piece s);initmp();initpaint();return 0; } void mouseEvent(int x, int y, int button, int e) {if (button == LEFT_BUTTON && e == BUTTON_DOWN){if (x >= INTERVAL + 8 * 55 + 33 && x <= INTERVAL + 8 * 55 + 33 + 100 && y >= INTERVAL + 55 && y <= INTERVAL + 55 + 100)// INTERVAL + 8 * 55 + 33, INTERVAL + 55){/*beginPaint();setPenColor(BLACK);setPenWidth(3);setBrushColor(EMPTY);rectangle(INTERVAL + 8 * 55 + 33, INTERVAL + 55, INTERVAL + 8 * 55 + 33 + 100, INTERVAL + 55 + 50);endPaint();*/if (!q.empty()){piece p1 = q.back();q.pop_back();piece p2 = q.back();q.pop_back();//piece p3 = p1;mp[p1.row][p1.col].color = p1.color;mp[p1.row][p1.col].index = p1.index;mp[p1.row][p1.col].is = p1.is;mp[p1.row][p1.col].pos = p1.pos;mp[p2.row][p2.col].color = p2.color;mp[p2.row][p2.col].index = p2.index;mp[p2.row][p2.col].is = p2.is;mp[p2.row][p2.col].pos = p2.pos;initpaint();}}int tmpx, tmpy, f = 0;for (int a = 0; a < 10; a++){if (f == 1)break;for (int b = 0; b < 9; b++){if (sqrt(((double)x - mp[a][b].x) * ((double)x - mp[a][b].x) + ((double)y - mp[a][b].y) * ((double)y - mp[a][b].y)) <= 20){f = 1;tmpx = a;tmpy = b;break;}}}if (f == 1)//有格子{initpaint();//paint_rect(tmpx, tmpy);/*tmp.x = mp[tmpx][tmpy].x;tmp.y = mp[tmpx][tmpy].y;tmp.is = mp[tmpx][tmpy].is;tmp.index = mp[tmpx][tmpy].index;*/if (mp[tmpx][tmpy].is == 1)//格子內有棋子{if (tmp.color == mp[tmpx][tmpy].color || tmp.color == NULL)//同色copy{paint_rect(tmpx, tmpy);prex = tmpx;prey = tmpy;tmp.is = mp[tmpx][tmpy].is;tmp.index = mp[tmpx][tmpy].index;tmp.color = mp[tmpx][tmpy].color;}else if (judge_piece(tmpx, tmpy) == 1) //異色吃掉{q.push_back(mp[tmpx][tmpy]);q.push_back(mp[prex][prey]);while (q.size() > 6) {q.pop_front();q.pop_front();}if (mp[tmpx][tmpy].pos == 1)//若被吃掉的是南兵{mp[tmpx][tmpy].pos = 0;}else if (mp[prex][prey].pos == 1)//南兵吃別人{mp[prex][prey].pos = 0;mp[tmpx][tmpy].pos = 1;}if (mp[prex][prey].index == 4)//若是黑將移動,黑將位置重新賦值{black_general_x = tmpx;black_general_y = tmpy;}else if (mp[prex][prey].index == 11)//若是紅將移動,紅將位置重新賦值{red_general_x = tmpx;red_general_y = tmpy;}if (mp[tmpx][tmpy].index == 11)red_general_isexist = 0;else if (mp[tmpx][tmpy].index == 4)black_general_isexist = 0;mp[tmpx][tmpy].color = tmp.color;mp[tmpx][tmpy].index = tmp.index;mp[prex][prey].is = 0;mp[prex][prey].color = NULL;tmp.is = 0;tmp.color = NULL;initpaint();if (judge_general(tmpx, tmpy) == 1){beginPaint();setTextColor(RED);setTextSize(30);setTextBkColor(EMPTY);paintText(250, 600, "將 軍!");endPaint();}}else{beginPaint();setTextColor(RED);setTextSize(30);setTextBkColor(EMPTY);paintText(250, 600, "請規范行棋");endPaint();tmp.is = 0;tmp.color = NULL;}}else//格子內沒有棋子{//paint_rect(tmpx, tmpy);if (tmp.is == 1){if (judge_piece(tmpx, tmpy) == 1){q.push_back(mp[tmpx][tmpy]);q.push_back(mp[prex][prey]);if (q.size() > 6) {q.pop_front();q.pop_front();}if (mp[prex][prey].pos == 1){mp[prex][prey].pos = 0;mp[tmpx][tmpy].pos = 1;}if (mp[prex][prey].index == 4)//若是黑將移動,黑將位置重新賦值{black_general_x = tmpx;black_general_y = tmpy;}else if (mp[prex][prey].index == 11)//若是紅將移動,紅將位置重新賦值{red_general_x = tmpx;red_general_y = tmpy;}mp[prex][prey].is = 0;mp[prex][prey].color = NULL;mp[tmpx][tmpy].index = tmp.index;mp[tmpx][tmpy].is = tmp.is;mp[tmpx][tmpy].color = tmp.color;tmp.is = 0;tmp.color = NULL;initpaint();if (judge_general(tmpx, tmpy) == 1){beginPaint();setTextColor(RED);setTextSize(30);setTextBkColor(EMPTY);paintText(250, 600, "將 軍!");endPaint();}}else{beginPaint();setTextColor(RED);setTextSize(30);setTextBkColor(EMPTY);paintText(250, 600, "請規范行棋");endPaint();tmp.is = 0;tmp.color = NULL;}//initpaint();}else paint_rect(tmpx, tmpy);//initpaint();}}if (red_general_isexist == 0){beginPaint();setTextSize(70);setTextColor(BLACK);setTextBkColor(RGB(3, 168, 158));paintText(130, 270, "黑方獲勝");endPaint();}else if (black_general_isexist == 0){beginPaint();setTextSize(70);setTextColor(RED);setTextBkColor(RGB(3, 168, 158));paintText(130, 270, "紅方獲勝");endPaint();}}else if (button == RIGHT_BUTTON && e == BUTTON_DOWN){initpaint();tmp.is = 0;tmp.color = NULL;}//initpaint(); } void paint(piece s) {beginPaint();//clearDevice();//putImageScale(&chessimg, 0, 0, 650, 701);setPenColor(RGB(245, 222, 179));setPenWidth(3);setBrushColor(RGB(245, 222, 179));ellipse(s.x - 20, s.y - 20, s.x + 20, s.y + 20);if (s.color == 'B')setTextColor(BLACK);else setTextColor(RED);setTextSize((int)(20 * sin(pi / 4)) * 2);setTextBkColor(EMPTY);paintText(s.x - (int)(20 * sin(pi / 4)), s.y - (int)(20 * sin(pi / 4)), chessname[s.index]);endPaint(); } /*void paintb(piece s) {beginPaint();//clearDevice();setPenColor(RGB(245, 222, 179));setPenWidth(3);setBrushColor(RGB(245, 222, 179));ellipse(s.x - 20, s.y - 20, s.x + 20, s.y + 20);setTextColor(BLACK);setTextSize((int)(20 * sin(pi / 4)) * 2);setTextBkColor(EMPTY);paintText(s.x - (int)(20 * sin(pi / 4)), s.y - (int)(20 * sin(pi / 4)), chessname[s.index]);endPaint(); }*/ void initmp() {for (int a = 0; a < 10; a++){for (int b = 0; b < 9; b++){mp[a][b].x = INTERVAL + 55 * (b);mp[a][b].y = INTERVAL + 55 * (a);mp[a][b].color = NULL;mp[a][b].index = -1;mp[a][b].is = 0;mp[a][b].pos = 0;mp[a][b].row = a;mp[a][b].col = b;}}int j = 0;for (int a = 0; a < 5; a++){mp[0][a].index = j++;mp[0][a].is = 1;mp[0][a].color = 'B';}j = 3;for (int a = 5; a < 9; a++){mp[0][a].index = j--;mp[0][a].is = 1;mp[0][a].color = 'B';}int i = 7;for (int a = 0; a < 5; a++){mp[9][a].index = i++;mp[9][a].is = 1;mp[9][a].color = 'R';}i = 10;for (int a = 5; a < 9; a++){mp[9][a].index = i--;mp[9][a].is = 1;mp[9][a].color = 'R';}mp[2][1].index = 5;mp[2][7].index = 5;mp[2][1].color = 'B';mp[2][7].color = 'B';mp[7][1].index = 12;mp[7][7].index = 12;mp[7][1].color = 'R';mp[7][7].color = 'R';mp[2][1].is = 1;mp[2][7].is = 1;mp[7][1].is = 1;mp[7][7].is = 1;for (int a = 0; a < 9; a += 2){mp[3][a].index = 6;mp[6][a].index = 13;mp[3][a].is = 1;mp[6][a].is = 1;mp[3][a].color = 'B';mp[6][a].color = 'R';mp[6][a].pos = 1;} } void initpaint() {/*for (int a = 0; a < 9; a++){//mp[0][a].is = 1;paintb(mp[0][a]);}paintb(mp[2][1]);paintb(mp[2][7]);//mp[2][1].is = 1;//mp[2][7].is = 1;for (int a = 0; a < 9; a += 2){//mp[3][a].is = 1;paintb(mp[3][a]);}for (int a = 0; a < 9; a++){//mp[9][a].is = 1;paintr(mp[9][a]);}paintr(mp[7][1]);paintr(mp[7][7]);mp[7][1].is = 1;mp[7][7].is = 1;for (int a = 0; a < 9; a += 2){//mp[6][a].is = 1;paintr(mp[6][a]);}*//*beginPaint();clearDevice();putImageScale(&chessimg, 0, 0, 650, 701);endPaint();*/chessboard();for (int a = 0; a < 10; a++)for (int b = 0; b < 9; b++){if (mp[a][b].is == 1){paint(mp[a][b]);}} } void paint_rect(int tmpx, int tmpy) {//initpaint();beginPaint();setPenColor(RGB(0, 0, 225));setBrushColor(EMPTY);rectangle(mp[tmpx][tmpy].x - 25, mp[tmpx][tmpy].y - 25, mp[tmpx][tmpy].x + 25, mp[tmpx][tmpy].y + 25);endPaint(); } int judge_piece(int x, int y)//18ma07che5 12pao29xiang3 10shi6 13zu else jiang {if (mp[prex][prey].index == 1 || mp[prex][prey].index == 8){if ((x == prex - 2 && y == prey - 1 && mp[prex - 1][prey].is == 0) || (x == prex - 2 && y == prey + 1 && mp[prex - 1][prey].is == 0)|| (x == prex - 1 && y == prey + 2 && mp[prex][prey + 1].is == 0) || (x == prex + 1 && y == prey + 2 && mp[prex][prey + 1].is == 0)|| (x == prex + 2 && y == prey + 1 && mp[prex + 1][prey].is == 0) || (x == prex + 2 && y == prey - 1 && mp[prex + 1][prey].is == 0)|| (x == prex + 1 && y == prey - 2 && mp[prex][prey - 1].is == 0) || (x == prex - 1 && y == prey - 2 && mp[prex][prey - 1].is == 0)){return 1;}else return 0;}else if (mp[prex][prey].index == 0 || mp[prex][prey].index == 7){if (prey == y){for (int i = min(prex, x) + 1; i < max(prex, x); i++){if (mp[i][prey].is == 1)return 0;}return 1;}else if (prex == x){for (int i = min(prey, y) + 1; i < max(prey, y); i++){if (mp[prex][i].is == 1)return 0;}return 1;}else return 0;}else if (mp[prex][prey].index == 5 || mp[prex][prey].index == 12){if (mp[x][y].is == 1){if (prey == y){int ant = 0;for (int i = min(prex, x) + 1; i < max(prex, x); i++){if (mp[i][prey].is == 1)ant++;}if (ant == 1)return 1;else return 0;}else if (prex == x){int ant = 0;for (int i = min(prey, y) + 1; i < max(prey, y); i++){if (mp[prex][i].is == 1)ant++;}if (ant == 1)return 1;else return 0;}else return 0;}else{if (prey == y){for (int i = min(prex, x) + 1; i < max(prex, x); i++){if (mp[i][prey].is == 1)return 0;}return 1;}else if (prex == x){for (int i = min(prey, y) + 1; i < max(prey, y); i++){if (mp[prex][i].is == 1)return 0;}return 1;}else return 0;}}else if (mp[prex][prey].index == 2 || mp[prex][prey].index == 9){if (prex <= 4){if (x <= 4){if ((x == prex - 2 && y == prey - 2 && mp[prex - 1][prey - 1].is == 0)|| (x == prex - 2 && y == prey + 2 && mp[prex - 1][prey + 1].is == 0)|| (x == prex + 2 && y == prey + 2 && mp[prex + 1][prey + 1].is == 0)|| (x == prex + 2 && y == prey - 2 && mp[prex + 1][prey - 1].is == 0)){return 1;}else return 0;}else return 0;}else if (prex >= 5){if (x > 4){if ((x == prex - 2 && y == prey - 2 && mp[prex - 1][prey - 1].is == 0)|| (x == prex - 2 && y == prey + 2 && mp[prex - 1][prey + 1].is == 0)|| (x == prex + 2 && y == prey + 2 && mp[prex + 1][prey + 1].is == 0)|| (x == prex + 2 && y == prey - 2 && mp[prex + 1][prey - 1].is == 0)){return 1;}else return 0;}else return 0;}}else if (mp[prex][prey].index == 3 || mp[prex][prey].index == 10){if (prex <= 4){if (x > 2 || y < 3 || y>5)return 0;else{if ((x == prex - 1 && y == prey - 1) || (x == prex - 1 && y == prey + 1)|| (x == prex + 1 && y == prey + 1) || (x == prex + 1 && y == prey - 1)){return 1;}else return 0;}}else{if (x < 7 || y < 3 || y>5)return 0;else{if ((x == prex - 1 && y == prey - 1) || (x == prex - 1 && y == prey + 1)|| (x == prex + 1 && y == prey + 1) || (x == prex + 1 && y == prey - 1)){return 1;}else return 0;}}}else if (mp[prex][prey].index == 6 || mp[prex][prey].index == 13){if (mp[prex][prey].pos == 0)//北卒{if (prex <= 4){if ((x == prex + 1) && (y == prey))return 1;else return 0;}else{if (((x == prex + 1) && (y == prey)) || ((x == prex) && (y = prey - 1)) || ((x == prex) && (y = prey + 1)))return 1;else return 0;}}else//南兵{if (prex >= 5){if ((x == prex - 1) && (y == prey)) { return 1; }else return 0;}else{if (((x == prex - 1) && (y == prey)) || ((x == prex) && (y = prey - 1)) || ((x == prex) && (y = prey + 1))) {return 1;}else return 0;}}}else{//int ant = 0;if (prex <= 4){int ant = 0;for (int i = prex + 1; i <= 9; i++){if (mp[i][prey].index == 4 || mp[i][prey].index == 11)break;if (mp[i][prey].is == 1)ant++;}if (ant == 0)return 1;}else{int ant = 0;for (int i = prex - 1; i >= 0; i--){if (mp[i][prey].index == 4 || mp[i][prey].index == 11)break;if (mp[i][prey].is == 1)ant++;}if (ant == 0)return 1;}if (mp[prex][prey].pos == 0){if (((x == prex) && (y == prey + 1)) || ((x == prex) && (y == prey - 1)) || ((y == prey) && (x == prex - 1)) || ((y == prey) && (x == prex + 1))){return 1;}else return 0;}else{if (((x == prex) && (y == prey + 1)) || ((x == prex) && (y == prey - 1)) || ((y == prey) && (x == prex - 1)) || ((y == prey) && (x == prex + 1))){return 1;}else return 0;}}//return 1; } void chessboard() {beginPaint();clearDevice();setPenColor(RED);setPenWidth(1);for (int a = 0; a <= 9; a++){line(INTERVAL, INTERVAL + a * 55, INTERVAL + 440, INTERVAL + a * 55);}for (int a = 0; a <= 8; a++){line(INTERVAL + a * 55, INTERVAL, INTERVAL + a * 55, INTERVAL + 495);}line(INTERVAL + 3 * 55, INTERVAL, INTERVAL + 5 * 55, INTERVAL + 2 * 55);line(INTERVAL + 5 * 55, INTERVAL, INTERVAL + 3 * 55, INTERVAL + 2 * 55);line(INTERVAL + 3 * 55, INTERVAL + 7 * 55, INTERVAL + 5 * 55, INTERVAL + 9 * 55);line(INTERVAL + 5 * 55, INTERVAL + 7 * 55, INTERVAL + 3 * 55, INTERVAL + 9 * 55);setBrushColor(EMPTY);rectangle(INTERVAL - 5, INTERVAL - 5, INTERVAL + 5 + 440, INTERVAL + 5 + 495);setBrushColor(WHITE);rectangle(INTERVAL, INTERVAL + 220, INTERVAL + 440 + 1, INTERVAL + 275 + 1);setTextColor(BLACK);setTextFont("楷體");setTextSize(30);setTextBkColor(WHITE);paintText(INTERVAL + 73, INTERVAL + 235, "楚河 漢界");setTextBkColor(RGB(218, 112, 214));setTextSize(50);paintText(INTERVAL + 8 * 55 + 33, INTERVAL + 55, "悔棋");endPaint();} int judge_general(int x, int y)//判斷是否被將軍 {if (mp[x][y].index == 1 || mp[x][y].index == 8){if (mp[x][y].color == 'B'){if ((red_general_x == x - 2 && red_general_y == y - 1) || (red_general_x == x - 2 && red_general_y == y + 1)|| (red_general_x == x - 1 && red_general_y == y + 2) || (red_general_x == x + 1 && red_general_y == y + 2)|| (red_general_x == x + 2 && red_general_y == y + 1) || (red_general_x == x + 2 && red_general_y == y - 1)|| (red_general_x == x + 1 && red_general_y == y - 2) || (red_general_x == x - 1 && red_general_y == y - 2)){return 1;}else return 0;}else{if ((black_general_x == x - 2 && black_general_y == y - 1) || (black_general_x == x - 2 && black_general_y == y + 1)|| (black_general_x == x - 1 && black_general_y == y + 2) || (black_general_x == x + 1 && black_general_y == y + 2)|| (black_general_x == x + 2 && black_general_y == y + 1) || (black_general_x == x + 2 && black_general_y == y - 1)|| (black_general_x == x + 1 && black_general_y == y - 2) || (black_general_x == x - 1 && black_general_y == y - 2)){return 1;}else return 0;}}else if (mp[x][y].index == 0 || mp[x][y].index == 7){if (mp[x][y].color == 'B'){if (red_general_y == y){for (int i = min(red_general_x, x) + 1; i < max(red_general_x, x); i++){if (mp[i][red_general_y].is == 1)return 0;}return 1;}else if (red_general_x == x){for (int i = min(red_general_y, y) + 1; i < max(red_general_y, y); i++){if (mp[red_general_x][i].is == 1)return 0;}return 1;}else return 0;}else{if (black_general_y == y){for (int i = min(black_general_x, x) + 1; i < max(black_general_x, x); i++){if (mp[i][black_general_y].is == 1)return 0;}return 1;}else if (black_general_x == x){for (int i = min(black_general_y, y) + 1; i < max(black_general_y, y); i++){if (mp[black_general_x][i].is == 1)return 0;}return 1;}else return 0;}}else if (mp[x][y].index == 5 || mp[x][y].index == 12){if (mp[x][y].color == 'B'){if (red_general_y == y){int ant = 0;for (int i = min(red_general_x, x) + 1; i < max(red_general_x, x); i++){if (mp[i][red_general_y].is == 1)ant++;}if (ant == 1)return 1;else return 0;}else if (red_general_x == x){int ant = 0;for (int i = min(red_general_y, y) + 1; i < max(red_general_y, y); i++){if (mp[red_general_x][i].is == 1)ant++;}if (ant == 1)return 1;else return 0;}else return 0;}else{if (black_general_y == y){int ant = 0;for (int i = min(black_general_x, x) + 1; i < max(black_general_x, x); i++){if (mp[i][black_general_y].is == 1)ant++;}if (ant == 1)return 1;else return 0;}else if (black_general_x == x){int ant = 0;for (int i = min(black_general_y, y) + 1; i < max(black_general_y, y); i++){if (mp[black_general_x][i].is == 1)ant++;}if (ant == 1)return 1;else return 0;}else return 0;}return 0;}else if (mp[x][y].index == 6 || mp[x][y].index == 13){if (mp[x][y].color == 'B'){if ((red_general_x == x + 1 && red_general_y == y) || (red_general_x == x && red_general_y == y - 1)|| (red_general_x == x && red_general_y == y + 1)){return 1;}else return 0;}else{if ((black_general_x == x - 1 && black_general_y == y) || (black_general_x == x && black_general_y == y - 1)|| (black_general_x == x && black_general_y == y + 1)){return 1;}else return 0;}} }打完收工!
總結
以上是生活随笔為你收集整理的C/C++:实现象棋游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 斗破苍穹java_安卓斗破苍穹游戏源码
- 下一篇: 编译原理王者之路