中国象棋小游戏
ez_lcw
2018-08-30 21:11:19
# 中国象棋小游戏
这个新游戏是本人第一次创作,如果有任何BUG(反正我相信会有很多,请发现的人在评论指出),但希望大家还是玩一玩,(毕竟我是花了九九八十一天才完成的~~我才不会告诉你我是一个下午搞完的~~)
代码如下:
```cpp
#include<cstdio>
#include<windows.h>
#include<iostream>
#define N 10
#define M 9
using namespace std;
int have[N+1][M+1],stx,sty,edx,edy;
//0 无
//1 红車,2红马,3红象,4红士,5红将,6红炮,7红兵
//8 黑車,9黑马,10黑象,11黑士,12黑将,13黑炮,14黑兵
int horsex[8]= {-2,-2,2,2,-1,1,-1,1},horsey[8]= {-1,1,-1,1,-2,-2,2,2};
int xiangx[4]= {-2,-2,2,2},xiangy[4]= {-2,2,-2,2};
int shix[4]= {-1,-1,1,1},shiy[4]= {-1,1,-1,1};
int jiangx[4]= {-1,0,1,0},jiangy[4]= {0,1,0,-1};
bool red,blue,Hint;
// 0 = 黑色 8 = 灰色
// 1 = 蓝色 9 = 淡蓝色
// 2 = 绿色 A = 淡绿色
// 3 = 浅绿色 B = 淡浅绿色
// 4 = 红色 C = 淡红色
// 5 = 紫色 D = 淡紫色
// 6 = 黄色 E = 淡黄色
// 7 = 白色 F = 亮白色
enum ConsoleForegroundColor
{
enmCFC_Red = FOREGROUND_INTENSITY | FOREGROUND_RED,
enmCFC_Green = FOREGROUND_INTENSITY | FOREGROUND_GREEN,
enmCFC_Blue = FOREGROUND_INTENSITY | FOREGROUND_BLUE,
enmCFC_Yellow = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
enmCFC_Purple = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,
enmCFC_Cyan = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
enmCFC_Gray = FOREGROUND_INTENSITY,
enmCFC_White = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
enmCFC_HighWhite = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
enmCFC_Black = 0,
};
enum ConsoleBackGroundColor
{
enmCBC_Red = BACKGROUND_INTENSITY | BACKGROUND_RED,
enmCBC_Green = BACKGROUND_INTENSITY | BACKGROUND_GREEN,
enmCBC_Blue = BACKGROUND_INTENSITY | BACKGROUND_BLUE,
enmCBC_Yellow = BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN,
enmCBC_Purple = BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE,
enmCBC_Cyan = BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE,
enmCBC_White = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
enmCBC_HighWhite = BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
enmCBC_Black = 0,
};
void SetConsoleColor(ConsoleForegroundColor foreColor = enmCFC_White, ConsoleBackGroundColor backColor = enmCBC_Black)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, foreColor | backColor);
}
//int allForeColors[] = { enmCFC_Red, enmCFC_Green, enmCFC_Blue, enmCFC_Yellow, enmCFC_Purple, enmCFC_Cyan, enmCFC_Gray, enmCFC_White, enmCFC_HighWhite, enmCFC_Black };
//int allBackColors[] = { enmCBC_Red, enmCBC_Green, enmCBC_Blue, enmCBC_Yellow, enmCBC_Purple, enmCBC_Cyan, 0, enmCBC_White, enmCBC_HighWhite, enmCBC_Black };
//SetConsoleColor((ConsoleForegroundColor)allForeColors[i], (ConsoleBackGroundColor)allBackColors[j]);
//Fore: 0 Red,1 Green,2 Blue,3 Yellow,4 Purple,5 Cyan(青),6 Gray,7 White,8 HighWhite,9 Black
//Back: 0 Red,1 Green,2 Blue,3 Yellow,4 Purple,5 Cyan(青),6 0 ,7 White,8 HighWhite,9 Black
int allForeColors[] = { enmCFC_Red, enmCFC_Green, enmCFC_Blue, enmCFC_Yellow, enmCFC_Purple, enmCFC_Cyan, enmCFC_Gray, enmCFC_White, enmCFC_HighWhite, enmCFC_Black };
int allBackColors[] = { enmCBC_Red, enmCBC_Green, enmCBC_Blue, enmCBC_Yellow, enmCBC_Purple, enmCBC_Cyan, 0, enmCBC_White, enmCBC_HighWhite, enmCBC_Black };
struct MAP
{
string map[N+1][M+1];
} map1;
int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^'0');
ch=getchar();
}
return x*f;
}
void writemap(MAP map1)
{
system("cls");
for(int i=0; i<=N; i++)
{
for(int q=0; q<=M; q++)
{
if(have[i][q]<=7&&have[i][q]!=0&&map1.map[i][q]!="#")
{
SetConsoleColor((ConsoleForegroundColor)allForeColors[0], (ConsoleBackGroundColor)allBackColors[9]);
}
else
{
if(have[i][q]!=0&&map1.map[i][q]!="#")
{
SetConsoleColor((ConsoleForegroundColor)allForeColors[2], (ConsoleBackGroundColor)allBackColors[9]);
}
}
printf("%s",map1.map[i][q].c_str());
SetConsoleColor((ConsoleForegroundColor)allForeColors[7], (ConsoleBackGroundColor)allBackColors[9]);
if((have[i][q]==0&&map1.map[i][q]!="10")||map1.map[i][q]=="#")
{
putchar(' ');
}
}
puts("");
}
puts("");
}
void buildmap()
{
red=false;
blue=false;
memset(have,0,sizeof(have));
map1.map[0][0]=" ";
map1.map[1][0]="1";
map1.map[2][0]="2";
map1.map[3][0]="3";
map1.map[4][0]="4";
map1.map[5][0]="5";
map1.map[6][0]="6";
map1.map[7][0]="7";
map1.map[8][0]="8";
map1.map[9][0]="9";
map1.map[10][0]="10";
map1.map[0][1]="1";
map1.map[0][2]="2";
map1.map[0][3]="3";
map1.map[0][4]="4";
map1.map[0][5]="5";
map1.map[0][6]="6";
map1.map[0][7]="7";
map1.map[0][8]="8";
map1.map[0][9]="9";
for(int i=1; i<=N; i++)
{
for(int q=1; q<=M; q++)
{
map1.map[i][q]=".";
}
}
map1.map[1][1]="車";
have[1][1]=1;
map1.map[1][2]="馬";
have[1][2]=2;
map1.map[1][3]="相";
have[1][3]=3;
map1.map[1][4]="仕";
have[1][4]=4;
map1.map[1][5]="帅";
have[1][5]=5;
map1.map[1][6]="仕";
have[1][6]=4;
map1.map[1][7]="相";
have[1][7]=3;
map1.map[1][8]="馬";
have[1][8]=2;
map1.map[1][9]="車";
have[1][9]=1;
map1.map[3][2]="炮";
have[3][2]=6;
map1.map[3][8]="炮";
have[3][8]=6;
map1.map[4][1]="卒";
have[4][1]=7;
map1.map[4][3]="卒";
have[4][3]=7;
map1.map[4][5]="卒";
have[4][5]=7;
map1.map[4][7]="卒";
have[4][7]=7;
map1.map[4][9]="卒";
have[4][9]=7;
map1.map[7][1]="兵";
have[7][1]=14;
map1.map[7][3]="兵";
have[7][3]=14;
map1.map[7][5]="兵";
have[7][5]=14;
map1.map[7][7]="兵";
have[7][7]=14;
map1.map[7][9]="兵";
have[7][9]=14;
map1.map[8][2]="砲";
have[8][2]=13;
map1.map[8][8]="砲";
have[8][8]=13;
map1.map[N][1]="车";
have[N][1]=8;
map1.map[N][2]="马";
have[N][2]=9;
map1.map[N][3]="象";
have[N][3]=10;
map1.map[N][4]="士";
have[N][4]=11;
map1.map[N][5]="将";
have[N][5]=12;
map1.map[N][6]="士";
have[N][6]=11;
map1.map[N][7]="象";
have[N][7]=10;
map1.map[N][8]="马";
have[N][8]=9;
map1.map[N][9]="车";
have[N][9]=8;
}
bool right(int num,int stx,int sty,int edx,int edy,bool output)
{
if(num%7==1)
{
if(stx!=edx&&sty!=edy)
{
if(output) puts("您的車只可以横竖走,并且只能走直线,您输入错了,请重新输入:");
return false;
}
if(sty==edy)
{
bool b=false;
for(int i=stx+(edx>stx?1:-1); (edx>stx?i<edx:i>edx); i+=(edx>stx?1:-1))
{
if(have[i][sty])
{
if(output)
puts("O(≧口≦)O,怎么老是被挡住!只能重新选择一个要去的点啦:");
b=true;
return false;
}
}
if(b)
{
return false;
}
}
else
{
bool b=false;
for(int i=sty+(edy>sty?1:-1); (edy>sty?i<edy:i>edy); i+=(edy>sty?1:-1))
{
if(have[stx][i])
{
if(output)
puts("O(≧口≦)O,怎么老是被挡住!只能重新选择一个要去的点啦:");
b=true;
break;
}
}
if(b)
{
return false;
}
}
}
if(num%7==2)
{
bool b=false;
int fangxiang;//0 上,1 下,2 左,3 右
for(int i=0; i<8; i++)
{
if(stx+horsex[i]==edx&&sty+horsey[i]==edy)
{
fangxiang=i/2;
b=true;
break;
}
}
if(b)
{
if(fangxiang==0)
{
if(have[stx-1][sty])
{
if(output)
puts("O(≧口≦)O,这都能被蹩马腿(绊马脚),只能重新选择一个要去的点啦:");
return false;
}
}
if(fangxiang==1)
{
if(have[stx+1][sty])
{
if(output)
puts("O(≧口≦)O,这都能被蹩马腿(绊马脚),只能重新选择一个要去的点啦:");
return false;
}
}
if(fangxiang==2)
{
if(have[stx][sty-1])
{
if(output)
puts("O(≧口≦)O,这都能被蹩马腿(绊马脚),只能重新选择一个要去的点啦:");
return false;
}
}
if(fangxiang==3)
{
if(have[stx][sty+1])
{
if(output)
puts("O(≧口≦)O,这都能被蹩马腿(绊马脚),只能重新选择一个要去的点啦:");
return false;
}
}
}
else
{
if(output)
puts("您的馬只可以走日字,您输入错了,请重新输入:");
return false;
}
}
if(num%7==3)
{
if(num<=7?edx>5:edx<6)
{
if(output)
puts("相的活动范围限于“河界”以内的本方阵地,不能过河,您输入错了,请重新输入:");
return false;
}
bool b=false;
int fangxiang;//0 左上,1 右上,2 左下,3 右下
for(int i=0; i<4; i++)
{
if(stx+xiangx[i]==edx&&sty+xiangy[i]==edy)
{
fangxiang=i;
b=true;
break;
}
}
if(b)
{
if(fangxiang==0)
{
if(have[stx-1][sty-1])
{
if(output)
puts("O(≧口≦)O,这都能被塞象眼,只能重新选择一个要去的点啦:");
return false;
}
}
if(fangxiang==1)
{
if(have[stx-1][sty+1])
{
if(output)
puts("O(≧口≦)O,这都能被塞象眼,只能重新选择一个要去的点啦:");
return false;
}
}
if(fangxiang==2)
{
if(have[stx+1][sty-1])
{
if(output)
puts("O(≧口≦)O,这都能被塞象眼,只能重新选择一个要去的点啦:");
return false;
}
}
if(fangxiang==3)
{
if(have[stx+1][sty+1])
{
if(output)
puts("O(≧口≦)O,这都能被塞象眼,只能重新选择一个要去的点啦:");
return false;
}
}
}
else
{
if(output)
puts("您的相只可以走田字,您输入错了,请重新输入:");
return false;
}
}
if(num%7==4)
{
if(num<=7?(edx>3||edy<4||edy>6):(edx<8||edy<4||edy>6))
{
if(output)
puts("仕的活动范围限于九宫格内,您输入错了,请重新输入:");
return false;
}
bool b=false;
for(int i=0; i<4; i++)
{
if(stx+shix[i]==edx&&sty+shiy[i]==edy)
{
b=true;
break;
}
}
if(!b)
{
if(output)
puts("您的仕只可以走九宫格内的斜边,并且只能走一段斜线,您输入错了,请重新输入:");
return false;
}
}
if(num%7==5)
{
if((num<=7?(edx>3||edy<4||edy>6):(edx<8||edy<4||edy>6))&&have[edx][edy]!=(num<=7?12:5))
{
if(output)
puts("将的活动范围限于九宫格内,您输入错了,请重新输入:");
return false;
}
bool b=false;
for(int i=0; i<4; i++)
{
if(stx+jiangx[i]==edx&&sty+jiangy[i]==edy)
{
b=true;
break;
}
}
if(b)
{
bool b=false;
for(int i=stx+(num<=7?1:-1); (num<=7?i<=10:i>=1); i+=(num<=7?1:-1))
{
if(have[i][edy])
{
if(have[i][edy]==(num<=7?12:5))
{
b=true;
}
break;
}
}
if(b)
{
if(output)
puts("您被白脸将杀法控制了,O(≧口≦)O");
return false;
}
}
else
{
bool b=false;
for(int i=stx+(num<=7?1:-1); (num<=7?i<=10:i>=1); i+=(num<=7?1:-1))
{
if(have[i][edy])
{
if(have[i][edy]==(num<=7?12:5))
{
b=true;
}
break;
}
}
if(!b)
{
if(output)
puts("将只能走一步,您输入错了。");
return false;
}
}
}
if(num%7==6)
{
int k=0;
if(stx!=edx&&sty!=edy)
{
if(output)
puts("您的炮只可以横竖走,并且只能走直线,您输入错了,请重新输入:");
return false;
}
if(sty==edy)
{
for(int i=stx+(edx>stx?1:-1); (edx>stx?i<edx:i>edx); i+=(edx>stx?1:-1))
{
if(have[i][sty])
{
k++;
}
}
}
else
{
for(int i=sty+(edy>sty?1:-1); (edy>sty?i<edy:i>edy); i+=(edy>sty?1:-1))
{
if(have[stx][i])
{
k++;
}
}
}
if(k>1)
{
if(output)
puts("O(≧口≦)O,怎么老是被挡住!只能重新选择一个要去的点啦:");
return false;
}
if(!k&&have[edx][edy])
{
if(output)
puts("炮走法同车一样时,炮必须不吃子,您输入错了,请重新输入:");
return false;
}
if(k&&!have[edx][edy])
{
if(output)
puts("炮隔一个棋子(无论是哪一方的)走时,必须是吃子的时候,您输入错了,请重新输入:");
return false;
}
}
if(num%7==0)
{
if(num<=7?stx<=5:stx>=6)
{
if(edy!=sty||stx+(num<=7?1:-1)!=edx)
{
if(output)
puts("兵在没有过“河界”前,每着只许向前直走一步,您输入错了,请重新输入:");
return false;
}
}
else
{
if((edy!=sty||edx!=stx+(num<=7?1:-1))&&(edy!=sty-1||edx!=stx)&&(edy!=sty+1||edx!=stx))
{
if(output)
puts("兵在过“河界”后,每步可向前直走或横走一步,但不能后退,您输入错了,请重新输入:");
return false;
}
}
}
return true;
}
void hint(int num,int stx,int sty)
{
MAP map2=map1;
bool b=false;
for(int i=1; i<=10; i++)
{
for(int q=1; q<=9; q++)
{
if(!have[i][q]||(num<=7?have[i][q]>7:have[i][q]<=7))
{
if(right(num,stx,sty,i,q,false))
{
map2.map[i][q]="#";
b=true;
}
}
}
}
writemap(map2);
if(!b)
{
puts("很不幸,无路可走哦!");
}
}
bool fight(int num)
{
bool b=false;
while(1)
{
if(!b)
{
writemap(map1);
}
else
{
hint(num,stx,sty);
}
init:
puts("您想让这个棋子移动到哪里?(输入坐标(格式:行 列)(输入“-1 -1”为返回重新选择棋子进行操作,输入“-2 -2”打开或关闭提示)");
edx=read();edy=read();
if(edx==-1&&edx==-1)
{
return false;
}
if(edx==-2&&edy==-2)
{
b=!b;
continue;
}
if(edx>0&&edy>0&&edx<=10&&edy<=9&&(!have[edx][edy]||(num<=7?have[edx][edy]>7:have[edx][edy]<=7)))
{
if(!right(num,stx,sty,edx,edy,true))
{
goto init;
}
puts("移动中……");
Sleep(500);
if(!have[edx][edy])
{
swap(map1.map[stx][sty],map1.map[edx][edy]);
swap(have[stx][sty],have[edx][edy]);
}
else
{
if(have[edx][edy]==12)
{
blue=true;
}
if(have[edx][edy]==5)
{
red=true;
}
map1.map[edx][edy]=map1.map[stx][sty];
map1.map[stx][sty]=".";
have[edx][edy]=have[stx][sty];
have[stx][sty]=0;
puts("顺便吃掉了一个敌人,好嗨皮!");
Sleep(1000);
}
writemap(map1);
break;
}
else
{
puts("您输入的坐标错误或坐标对应的位置有你方的棋,请重新输入:");
goto init;
}
}
return true;
}
void play()
{
while(!red&&!blue)
{
SetConsoleColor((ConsoleForegroundColor)allForeColors[0], (ConsoleBackGroundColor)allBackColors[9]);
printf("红");
SetConsoleColor((ConsoleForegroundColor)allForeColors[7], (ConsoleBackGroundColor)allBackColors[9]);
puts("方回合到了,");
while(1)
{
puts("您需要将哪个棋子进行操作?(输入坐标(格式:行 列)");
stx=read();sty=read();
if(stx>0&&sty>0&&stx<=10&&sty<=9&&have[stx][sty]<=7&&have[stx][sty]>=1)
{
if(fight(have[stx][sty]))
{
break;
}
else
{
puts("请重新输入:");
continue;
}
}
else
{
puts("您输入的坐标错误或者坐标对应的位置没有你方的棋,请重新输入:");
}
}
if(blue)
{
puts("恭喜红方获胜!!!");
Sleep(5000);
return;
}
SetConsoleColor((ConsoleForegroundColor)allForeColors[2], (ConsoleBackGroundColor)allBackColors[9]);
printf("蓝");
SetConsoleColor((ConsoleForegroundColor)allForeColors[7], (ConsoleBackGroundColor)allBackColors[9]);
puts("方回合到了,");
while(1)
{
puts("您需要将哪个棋子进行操作?(输入坐标(格式:行 列)");
stx=read();sty=read();
if(stx>0&&sty>0&&stx<=10&&sty<=9&&have[stx][sty]>7&&have[stx][sty]>=1)
{
if(fight(have[stx][sty]))
{
break;
}
else
{
puts("请重新输入:");
continue;
}
}
else
{
puts("您输入的坐标错误或者坐标对应的位置没有你方的棋,请重新输入:");
}
}
if(red)
{
puts("恭喜蓝方获胜!!!");
Sleep(5000);
return;
}
}
}
void see()
{
puts("中国象棋一共有七种兵种,分别是车、马、炮、兵、士、相、帅。车、马、炮主要是负责进攻的棋子,而士、象是专职防守。");
puts("");
puts("车:可以纵着走也可以横着走,所有一个车能控制的点有17个,纵的有9个,横的有8个。所有车是象棋里面最厉害的棋子。它的吃子方式和走子方式是相同的,比如说在纵线上有敌对棋子,这个时候可以吃掉。");
puts("");
puts("马:马走“日”字,马在中间时能控制的格子有8个,成语说“马”八面威风说的就是这个意思。马在边上的时候能控制的格子就少了很多,所有我们尽量让马放在中间。马的走棋还有个规则就是“绊马脚”。");
puts("");
puts("炮:炮的走法与车相同,但是炮的吃子方式有点特别,它必须格着一个棋子才能吃子,也就是说它要有一个炮架。");
puts("");
puts("兵:兵有5个,位置在河界旁。兵在没过河之前只能往前走,过了河之后它就可以往左和右走。但是兵是不能往后退的,当兵走到底线的时候只能往左右走。兵的价值最好的位置是刚过河不久。如果冲到底线它的价值就降低了。");
puts("");
puts("士:士只能在“九宫”的5个点走,走法按斜上方走或斜下方走。");
puts("");
puts("相:相走“田”,相不能过河。相的走法有个'相眼'的走发(塞相眼)。");
puts("");
puts("王:中国象棋的王红方叫“帅”,黑方叫“将”。王只能在“九宫”中走动,不能出去。王的走法是可以走相邻的格子。双方王不能不隔任何棋子照面。");
puts("");
printf("按下回车即可退出。");
getchar();
}
void slowsay(string s)
{
for(int i=0; s[i]; i++)
{
cout<<s[i];
Sleep(15);
}
}
void diary()
{
puts("第一版:萌新游戏。");
puts("第二版:增加了“白脸将”杀法。");
puts("第三版:增加了规则。");
puts("第四版:增加了提示。");
puts("第五版:增加了颜色、更新日志,简化了操作。 ——2018年9月15日");
puts("BUG在每一次更新都会有修改,而且会根据BUG和需要持续更新,多谢大家支持!");
puts("注:目前“白脸将”杀法还是有BUG,正在修复。");
puts("");
printf("按下回车即可退出。");
getchar();
}
int main()
{
memset(have,0,sizeof(have));
SetConsoleColor((ConsoleForegroundColor)allForeColors[7], (ConsoleBackGroundColor)allBackColors[9]);
slowsay("欢迎来到中国象棋小游戏\n");
Sleep(1700);
while(1)
{
slowsay("输入1可查看规则,输入2可开始游戏,输入3可查看往期更新内容,输入4退出\n");
int num1;
while(1)
{
num1=read();
if(num1==1)
{
see();
break;
}
else
{
if(num1==2)
{
while(1)
{
bool b=false;
printf("象棋高手们,你们准备好了吗?按下回车开始游戏哦!(注意:选手各自要先分出红方蓝方(上半部分为红方(玩家1),下半部分为蓝方(玩家2)))");
getchar();
puts("进入游戏中……稍等片刻");
Sleep(1000);
buildmap();
writemap(map1);
play();
system("cls");
puts("再来一局吗,高手们?(输入1为退出,输入2为再来一局,输入3为返回主界面)");
int num2;
while(1)
{
num2=read();
if(num2==1)
{
return 0;
}
else
{
if(num2==3)
{
b=true;
break;
}
else
{
if(num2!=2)
{
puts("输入错误,请重新输入:");
}
}
}
break;
}
if(b)
{
break;
}
}
}
else
{
if(num1==3)
{
diary();
}
else
{
if(num1==4)
{
return 0;
}
else
{
puts("输入错误,请重新输入:");
continue;
}
}
}
}
break;
}
system("cls");
}
return 0;
}
}
```
第一版:萌新游戏。
第二版:增加了[“白脸将”](https://baike.baidu.com/item/%E7%99%BD%E8%84%B8%E5%B0%86/4445566?fr=aladdin)杀法。
第三版:增加了规则。
第四版:增加了提示。
第五版:棋子有了[颜色(转)](https://www.cnblogs.com/tangxin-blog/p/7257413.html),更容易区分,简化了操作 ——2018年9月9日
BUG在每一次更新都会有修改,而且会根据BUG和需要持续更新,多谢大家支持!