C++ 小程序——中国象棋
C++ 象棋小游戏,内置简易 AI,欢迎试用并提出宝贵建议。
链接:https://github.com/Chenaknoip/xiangqi
更新日志:
a1.0:创建项目
a1.1:修复走子异常的 bug
a1.2:添加了主界面
b1.0:添加了 AI,现在支持人机对战了
b1.1:修复了偶发崩溃的 Bug
注意:代码需要 windows.h。
使用本程序的部分或全部代码时,请注明原作者。
/****** XIANGQI GAME ******/
/* */
/* Author: CWKAPN */
/* Version: b1.1 */
/**************************/
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
const char SWVER[] = "b1.1";
int nor[12][11] = {77, 97, 100, 101, 32, 98, 121, 0, 0, 0, 0,
0, 21, 22, 23, 24, 25, 24, 23, 22, 21,0,
0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0,
0, 0 , 27, 0 , 0 , 0 , 0 , 0 , 27, 0 ,0,
0, 26, 0 , 26, 0 , 26, 0 , 26, 0 , 26,0,
0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0,
0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0,
0, 16, 0 , 16, 0 , 16, 0 , 16, 0 , 16,0,
0, 0 , 17, 0 , 0 , 0 , 0 , 0 , 17, 0 ,0,
0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0,
0, 11, 12, 13, 14, 15, 14, 13, 12, 11,0,
67, 87, 75, 41, 80, 78, 0, 0, 0, 0, 0
};
int dsk[12][11];
void output(int x, int y) {
if (dsk[x][y] == 0) {
if (x == 2 && y == 5) cout << "╳ ";
else if (x == 9 && y == 5) cout << "╳ ";
else if (x == 1) {
if (y == 1) cout << "└ ";
else if (y == 9) cout << "┌ ";
else cout << "├ ";
} else if (x == 10) {
if (y == 1) cout << "┘ ";
else if (y == 9) cout << "┐ ";
else cout << "┤ ";
} else if (y == 1) cout << "┴ ";
else if (y == 9) cout << "┬ ";
else if (x == 5) cout << "┤ ";
else if (x == 6) cout << "├ ";
else cout << "┼ ";
} else {
if (dsk[x][y] / 10 == 1) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
else SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
string s;
int tmp = dsk[x][y] % 10;
if (tmp == 1) s = "車";
if (tmp == 2) s = "马";
if (tmp == 3) s = "象";
if (tmp == 4) s = "士";
if (tmp == 5) s = (dsk[x][y] / 10 == 1) ? "帅" : "将";
if (tmp == 6) s = (dsk[x][y] / 10 == 1) ? "卒" : "兵";
if (tmp == 7) s = "炮";
cout << s;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
}
bool ok(int fang, int x, int y, int nx, int ny) {
if (x == -1 && y == 0 && nx == 0 && ny == 0) return true;
if (x < 1 || x > 10 || y < 1 || y > 9 || nx < 1 || nx > 10 || ny < 1 || ny > 9) return false;
if (dsk[x][y] == 0) return false;
if (dsk[x][y] / 10 == dsk[nx][ny] / 10) return false;
int tmp = dsk[x][y];
if (tmp / 10 != fang) return false;
tmp %= 10;
if (tmp == 1) {
if (x != nx && y != ny) return false;
if (x == nx) {
for (int yy = min(y, ny) + 1; yy < max(y, ny); yy++) if (dsk[x][yy] != 0) return false;
return true;
} else {
for (int xx = min(x, nx) + 1; xx < max(x, nx); xx++) if (dsk[xx][y] != 0) return false;
return true;
}
} else if (tmp == 2) {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (min(tx, ty) != 1 || max(tx, ty) != 2) return false; // bu ri
if (tx == 2) {
tx = (dx > 0) ? 1 : -1;
ty = 0;
} else {
ty = (dy > 0) ? 1 : -1;
tx = 0;
}
if (dsk[x + tx][y + ty] != 0) return false;
return true;
} else if (tmp == 3) {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (tx != 2 || ty != 2) return false; // bu tian
tx = (dx > 0) ? 1 : -1, ty = (dy > 0) ? 1 : -1;
if (dsk[x + tx][y + ty] != 0) return false;
if (dsk[x][y] / 10 == 1) {
if (nx < 6) return false;
} else {
if (nx > 5) return false;
}
return true;
} else if (tmp == 4) {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (tx != 1 || ty != 1) return false; // bu ri
if (ny < 4 || ny > 6) return false;
if (x < 5) {
return nx <= 3;
} else {
return nx >= 8;
}
return true;
} else if (tmp == 5) {
if (dsk[nx][ny] % 10 == 5) {
if (y != ny) return false;
for (int i = min(x, nx) + 1; i < max(x, nx); i++) {
if (dsk[i][y] != 0) return false;
}
return true;
} else {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (min(tx, ty) != 0 || max(tx, ty) != 1) return false;
if (ny < 4 || ny > 6) return false;
if (x < 5) {
return nx <= 3;
} else {
return nx >= 8;
}
}
} else if (tmp == 6) {
if (dsk[x][y] / 10 == 1) {
if (nx < 6) { // ctr
int dx = nx - x, dy = ny - y;
return dx == -1 && dy == 0 || dx == 0 && abs(dy) == 1;
} else {
int dx = nx - x, dy = ny - y;
return dx == -1 && dy == 0;
}
} else {
if (nx > 5) { // ctr
int dx = nx - x, dy = ny - y;
return dx == 1 && dy == 0 || dx == 0 && abs(dy) == 1;
} else {
int dx = nx - x, dy = ny - y;
return dx == 1 && dy == 0;
}
}
} else { // tmp == 7
if (x != nx && y != ny) return false;
if (x == nx) {
int cnt = 0;
if (y < ny) {
for (int yy = y + 1; yy <= ny; yy++) {
if (dsk[x][yy] != 0) cnt++;
}
} else {
for (int yy = y - 1; yy >= ny; yy--) {
if (dsk[x][yy] != 0) cnt++;
}
}
if (cnt == 0) return true;
else if (cnt == 2 && dsk[nx][ny] != 0) return true;
else return false;
} else {
int cnt = 0;
if (x < nx) {
for (int xx = x + 1; xx <= nx; xx++) {
if (dsk[xx][y] != 0) cnt++;
}
} else {
for (int xx = x - 1; xx >= nx; xx--) {
if (dsk[xx][y] != 0) cnt++;
}
}
if (cnt == 0) return true;
else if (cnt == 2 && dsk[nx][ny] != 0) return true;
else return false;
}
}
return true;
}
bool canmove(int x, int y, int nx, int ny) {
if (dsk[x][y] == 0) return false;
if (dsk[x][y] / 10 == dsk[nx][ny] / 10) return false;
int tmp = dsk[x][y];
tmp %= 10;
if (tmp == 1) {
if (x != nx && y != ny) return false;
if (x == nx) {
for (int yy = min(y, ny) + 1; yy < max(y, ny); yy++) if (dsk[x][yy] != 0) return false;
return true;
} else {
for (int xx = min(x, nx) + 1; xx < max(x, nx); xx++) if (dsk[xx][y] != 0) return false;
return true;
}
} else if (tmp == 2) {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (min(tx, ty) != 1 || max(tx, ty) != 2) return false; // bu ri
if (tx == 2) {
tx = (dx > 0) ? 1 : -1;
ty = 0;
} else {
ty = (dy > 0) ? 1 : -1;
tx = 0;
}
if (dsk[x + tx][y + ty] != 0) return false;
return true;
} else if (tmp == 3) {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (tx != 2 || ty != 2) return false; // bu tian
tx = (dx > 0) ? 1 : -1, ty = (dy > 0) ? 1 : -1;
if (dsk[x + tx][y + ty] != 0) return false;
if (dsk[x][y] / 10 == 1) {
if (nx < 6) return false;
} else {
if (nx > 5) return false;
}
return true;
} else if (tmp == 4) {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (tx != 1 || ty != 1) return false; // bu ri
if (ny < 4 || ny > 6) return false;
if (x < 5) {
return nx <= 3;
} else {
return nx >= 8;
}
return true;
} else if (tmp == 5) {
if (dsk[nx][ny] % 10 == 5) {
if (y != ny) return false;
for (int i = min(x, nx) + 1; i < max(x, nx); i++) {
if (dsk[i][y] != 0) return false;
}
return true;
} else {
int dx = nx - x, dy = ny - y;
int tx = abs(dx), ty = abs(dy);
if (min(tx, ty) != 0 || max(tx, ty) != 1) return false;
if (ny < 4 || ny > 6) return false;
if (x < 5) {
return nx <= 3;
} else {
return nx >= 8;
}
}
} else if (tmp == 6) {
if (dsk[x][y] / 10 == 1) {
if (nx < 6) { // ctr
int dx = nx - x, dy = ny - y;
return dx == -1 && dy == 0 || dx == 0 && abs(dy) == 1;
} else {
int dx = nx - x, dy = ny - y;
return dx == -1 && dy == 0;
}
} else {
if (nx > 5) { // ctr
int dx = nx - x, dy = ny - y;
return dx == 1 && dy == 0 || dx == 0 && abs(dy) == 1;
} else {
int dx = nx - x, dy = ny - y;
return dx == 1 && dy == 0;
}
}
} else { // tmp == 7
if (x != nx && y != ny) return false;
if (x == nx) {
int cnt = 0;
if (y < ny) {
for (int yy = y + 1; yy <= ny; yy++) {
if (dsk[x][yy] != 0) cnt++;
}
} else {
for (int yy = y - 1; yy >= ny; yy--) {
if (dsk[x][yy] != 0) cnt++;
}
}
if (cnt == 0) return true;
else if (cnt == 2 && dsk[nx][ny] != 0) return true;
else return false;
} else {
int cnt = 0;
if (x < nx) {
for (int xx = x + 1; xx <= nx; xx++) {
if (dsk[xx][y] != 0) cnt++;
}
} else {
for (int xx = x - 1; xx >= nx; xx--) {
if (dsk[xx][y] != 0) cnt++;
}
}
if (cnt == 0) return true;
else if (cnt == 2 && dsk[nx][ny] != 0) return true;
else return false;
}
}
return true;
}
bool check(bool f) {
int jx = 0, jy = 0;
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 9; j++) {
if (dsk[i][j] == ((int)f + 1) * 10 + 5) {
jx = i;
jy = j;
break;
}
}
if (jx && jy) break;
}
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 9; j++) {
if (canmove(i, j, jx, jy)) return true;
}
}
return false;
}
int is_checkmated(bool f) {
for (int x = 1; x <= 10; x++) {
for (int y = 1; y <= 9; y++) {
if (dsk[x][y] / 10 == f + 1) {
for (int nx = 1; nx <= 10; nx++) {
for (int ny = 1; ny <= 9; ny++) {
if (canmove(x, y, nx, ny)) {
int tmp = dsk[nx][ny];
dsk[nx][ny] = dsk[x][y];
dsk[x][y] = 0;
if (!check(f)) {
dsk[x][y] = dsk[nx][ny];
dsk[nx][ny] = tmp;
return false;
}
dsk[x][y] = dsk[nx][ny];
dsk[nx][ny] = tmp;
}
}
}
}
}
}
return (int)check(f) + 1;
}
bool done() {
bool flag1 = false, flag2 = false;
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 9; j++) {
if (dsk[i][j] == 15) flag1 = true;
if (dsk[i][j] == 25) flag2 = true;
}
}
return !(flag1 && flag2);
}
void workpar() {
bool fang = 0;
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 9; j++) {
dsk[i][j] = nor[i][j];
}
}
while (!done()) {
if (is_checkmated(fang) == 2) {
system("cls");
cout << (fang ? "蓝" : "红") << "方被将死,";
break;
} else if (is_checkmated(fang) == 1) {
system("cls");
cout << (fang ? "蓝" : "红") << "方被困毙,";
break;
}
system("cls");
cout << "y\n";
for (int i = 9; i >= 1; i--) {
cout << i << " ";
for (int j = 1; j <= 10; j++) {
output(j, i);
}
putchar('\n');
}
cout << " ";
for (int i = 1; i <= 10; i++) {
cout << i << " ";
}
cout << "x\n\n";
int x, y, nx, ny;
cout << "现在轮" << ((fang == 0) ? "红" : "蓝") << "走。\n";
if (check(fang)) cout << ((fang == 0) ? "红" : "蓝") << "方正在被将军。\n";
cout << "认输输入 -1 0 0 0。\n";
cout << "(x1, y1) 表示棋子坐标,(x2, y2) 表示目标坐标。\n";
cout << "输入坐标, x1 y1 x2 y2:";
cin >> x >> y >> nx >> ny;
while (!ok(fang + 1, x, y, nx, ny)) {
input:
cout << "输入非法,重新输入:";
x = y = nx = ny = 0;
cin >> x >> y >> nx >> ny;
}
if (x == -1) {
system("cls");
cout << (fang ? "蓝" : "红") << "方认输,";
break;
}
int ss = dsk[x][y], yuan = dsk[nx][ny];
dsk[x][y] = 0;
dsk[nx][ny] = ss;
if (check(fang)) {
dsk[x][y] = ss;
dsk[nx][ny] = yuan;
goto input;
}
fang ^= 1;
}
cout << (fang ? "红" : "蓝") << "方胜!\n";
cout << "y\n";
for (int i = 9; i >= 1; i--) {
cout << i << " ";
for (int j = 1; j <= 10; j++) {
output(j, i);
}
putchar('\n');
}
cout << " ";
for (int i = 1; i <= 10; i++) {
cout << i << " ";
}
cout << "x\n\n";
system("pause");
}
void workai() {
bool fang = 0;
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 9; j++) {
dsk[i][j] = nor[i][j];
}
}
int human = 0;
cout << "人类先手输入 1,电脑先手输入 2:";
while (true) {
human = 0;
cin >> human;
if (human == 1 || human == 2) break;
cout << "输入非法请重试:";
}
human--;
// Written by Cwkapn
while (!done()) {
if (is_checkmated(fang) == 2) {
system("cls");
cout << ((int)fang == human ? "人类" : "电脑") << "被将死,";
break;
} else if (is_checkmated(fang) == 1) {
system("cls");
cout << ((int)fang == human ? "人类" : "电脑") << "被困毙,";
break;
}
system("cls");
cout << "y\n";
for (int i = 9; i >= 1; i--) {
cout << i << " ";
for (int j = 1; j <= 10; j++) {
output(j, i);
}
putchar('\n');
}
cout << " ";
for (int i = 1; i <= 10; i++) {
cout << i << " ";
}
cout << "x\n\n";
if (fang == human) {
int x, y, nx, ny;
cout << "请您走棋。\n";
if (check(fang)) cout << "您正在被将军。\n";
cout << "认输请输入 -1 0 0 0。\n";
cout << "(x1, y1) 表示棋子坐标,(x2, y2) 表示目标坐标。\n";
cout << "输入坐标, x1 y1 x2 y2:";
cin >> x >> y >> nx >> ny;
while (!ok(fang + 1, x, y, nx, ny)) {
inpu:
cout << "输入非法请重试:";
x = y = nx = ny = 0;
cin >> x >> y >> nx >> ny;
}
if (x == -1) {
system("cls");
cout << "人类认输,";
break;
}
int ss = dsk[x][y], yuan = dsk[nx][ny];
dsk[x][y] = 0;
dsk[nx][ny] = ss;
if (check(fang)) {
dsk[x][y] = ss;
dsk[nx][ny] = yuan;
goto inpu;
}
fang ^= 1;
} else {
cout << "电脑计算中……\n";
Sleep(rand() % 3000);
int x, y, nx, ny;
x = rand() % 10 + 1; y = rand() % 9 + 1; nx = rand() % 10 + 1; ny = rand() % 9 + 1;
while (!ok(fang + 1, x, y, nx, ny)) {
cinpu:
x = rand() % 10 + 1; y = rand() % 9 + 1; nx = rand() % 10 + 1; ny = rand() % 9 + 1;
}
int ss = dsk[x][y], yuan = dsk[nx][ny];
dsk[x][y] = 0;
dsk[nx][ny] = ss;
if (check(fang)) {
dsk[x][y] = ss;
dsk[nx][ny] = yuan;
goto cinpu;
}
fang ^= 1;
}
}
cout << ((int)fang == human ? "电脑" : "人类") << "胜利!\n";
cout << "y\n";
for (int i = 9; i >= 1; i--) {
cout << i << " ";
for (int j = 1; j <= 10; j++) {
output(j, i);
}
putchar('\n');
}
cout << " ";
for (int i = 1; i <= 10; i++) {
cout << i << " ";
}
cout << "x\n\n";
system("pause");
}
int main() {
srand(time(NULL));
while (true) {
system("cls");
cout << "\n\t中 国 象 棋\t\n\n\t版本号:" << SWVER << "\t\n\n";
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 9; j++) {
dsk[i][j] = nor[i][j];
}
}
for (int i = 9; i >= 1; i--) {
cout << "\t";
for (int j = 1; j <= 10; j++) {
output(j, i);
}
cout << "\t";
putchar('\n');
}
cout << "\n";
cout << "人机对战输入 1,双人对战输入 2:";
int op = 0;
while (true) {
cin >> op;
if (op == 1 || op == 2) break;
cout << "输入非法请重试:";
}
if (op == 1) workai();
else workpar();
}
return 0;
}
本文来自博客园,作者:cwkapn,转载请注明原文链接:https://www.cnblogs.com/cwkapn/p/18847044


浙公网安备 33010602011771号