考虑一个象棋残局,其中红方有n
(
2≤
n
≤7
)个棋子,黑方只有一个将。红方除了有一个 帅(G
)之外还有
3
种可能的棋子:车(
R
),马(
H
),炮(
C
),并且需要考虑
“
蹩马 腿”
(如图
4-4
所示)与将和帅不能照面(将、帅如果同在一条直线上,中间又不隔着任何棋 子的情况下,走子的一方获胜)的规则。
输入所有棋子的位置,保证局面合法并且红方已经将军。你的任务是判断红方是否已经把黑方将死。关于中国象棋的相关规则请参见原题。
大一新生,欢迎各位大佬评论提出宝贵意见,觉得对你有用的话点个赞吧!
也可以评论一下想看的题目,我可以去试试 ^v^
头文件(函数的声明)
#include<stdio.h>
#include<string.h>
#include<windows.h>
void menu();//简单打印一个游戏菜单
void show(char[10][9][3]);//用于展示棋盘
void makeboard(char[10][9][3], const char[]);//棋盘的初始化
void puthead(char [10][9][3], char[10][9][3], const char[]);//放置双方将帅
void putchess(char[10][9][3], char[10][9][3], const char[]);//防止普通棋子
int judge(char[10][9][3]);//判断该情况是否被将死
int find(int*, int*, char[10][9][3], const char[]);//寻找某个棋子
主函数部分(源文件)
#include"deffunction.h"
int main()
{
int no, key = 0, hang = 0, lie = 0;
char showboard[10][9][3];
//由于象棋是汉字,汉字应该用字符串来表示,占两个字节,所以用三维数组,理解起来就是二维数组的
//每个元素为字符串
char trueboard[10][9][3];
char beif[3];
do
{
loop://未被将死时返回此处
menu();
no = scanf("%d", &key);
if (key == 1)
{
no = 0;
hang = 0, lie = 0;
system("cls");
makeboard(showboard, " ");//showboard为展示棋盘,初始化为‘ ’
makeboard(trueboard, "0");//trueboard为用于判断的棋盘,初始化为‘0’
show(showboard);//打印棋盘
puthead(trueboard, showboard, "r");//先放置红方的帅
system("cls");
show(showboard);//清屏之后再打印棋盘为了美观
putchess(trueboard, showboard, "r");//再放置普通棋子
system("cls");
show(showboard);
puthead(trueboard, showboard, "b");//放置黑方将
system("cls");
show(showboard);
show(showboard);//打印棋盘
find(&hang, &lie, trueboard, "Q");//寻找到将的位置
//寻找到之后判断将的位置,决定将是否能移动,移动之后判定是否被将死
if (hang + 1 < 10)
{
strcpy(beif, trueboard[hang + 1][lie]);//先记录下将要移动到的位置的棋子
strcpy(trueboard[hang + 1][lie], "Q");//再将将移动过去
strcpy(trueboard[hang][lie], "0");//把原来将的位置设为‘0’
no = judge(trueboard);//判定是否将军
if (no)
{
system("cls");
show(showboard);//打印黑方没有将死的走法
printf("黑方未被将死\n\n");
system("pause");
system("cls");
goto loop;
}
strcpy(trueboard[hang + 1][lie], beif);把记录下的棋子放回原处
strcpy(trueboard[hang][lie], "Q");//把将放回原处
}
if (hang - 1 >6)
{
strcpy(beif, trueboard[hang - 1][lie]);
strcpy(trueboard[hang - 1][lie], "Q");
strcpy(trueboard[hang][lie], "0");
no = judge(trueboard);
if (no)
{
system("cls");
show(showboard);
printf("黑方未被将死\n\n");
system("pause");
system("cls");
goto loop;
}
strcpy(trueboard[hang - 1][lie], beif);
strcpy(trueboard[hang][lie], "Q");
}
if (lie + 1 < 6)
{
strcpy(beif, trueboard[hang][lie + 1]);
strcpy(trueboard[hang][lie + 1], "Q");
strcpy(trueboard[hang][lie], "0");
no = judge(trueboard);
if (no)
{
system("cls");
show(showboard);
printf("黑方未被将死\n\n");
system("pause");
system("cls");
goto loop;
}
strcpy(trueboard[hang][lie + 1], beif);
strcpy(trueboard[hang][lie], "Q");
}
if (lie - 1 > 2)
{
strcpy(beif, trueboard[hang][lie - 1]);
strcpy(trueboard[hang][lie - 1], "Q");
strcpy(trueboard[hang][lie], "0");
no = judge(trueboard);
if (no)
{
system("cls");
show(showboard);
printf("黑方未被将死\n\n");
system("pause");
system("cls");
goto loop;
}
strcpy(trueboard[hang][lie - 1], beif);
strcpy(trueboard[hang][lie], "Q");
}
printf("黑方已经被将死\n\n");//若没有返回loop处,则表示黑方被将死
system("pause");
system("cls");
}
} while (key);
return 0;
}
函数定义(源文件)
#include"deffunction.h"
void menu()
{
printf("####################################\n");
printf("########## 1.开始游戏 ##########\n");
printf("########## 0.退出游戏 ##########\n");
printf("####################################\n");
printf("请选择--> ");
}
void show(char board[10][9][3])
{
int hang = 0,lie = 0, i = 0;
printf(" ");
for (i = 0; i < 9; i++)
printf(" %-4d", i + 1);
printf("\n");
for (hang = 0; hang < 10; hang++)
{
printf("%2d ", hang + 1);
for (lie = 0; lie < 8; lie++)
printf("%2s---", board[hang][lie]);
printf("%2s\n", board[hang][lie]);
if (hang == 4)
{
printf(" ");
printf("|| 楚河 汉界 ||\n");
continue;
}
if (hang < 9)
{
if (hang == 0)
printf(" || || || || \\ || / || || || ||\n");
else if (hang == 1)
printf(" || || || || / || \\ || || || ||\n");
else if (hang == 7)
printf(" || || || || \\ || / || || || ||\n");
else if (hang == 8)
printf(" || || || || / || \\ || || || ||\n");
else
printf(" || || || || || || || || ||\n");
}
}
printf("\n");
}
void makeboard(char board[10][9][3], const char c[])
{
int lie, hang;
for (hang = 0; hang < 10; hang++)
for (lie = 0; lie < 9; lie++)
{
strcpy(board[hang][lie], c);
//初始化为字符串c
}
}
void puthead(char trueboard[10][9][3], char showboard[10][9][3], const char c[])
{
int hang, lie, no;
loop:
if (c == "r")
{
printf("请选择红方“帅”的位置 --> ");//个人设定红方在上,黑方在下
no = scanf("%d%d", &hang, &lie);
if (hang < 0 || hang > 3 || lie < 4 || lie > 6)
{
printf("输入无效,请重新输入");
goto loop;
}
strcpy(showboard[hang - 1][lie - 1] , "帅");
strcpy(trueboard[hang - 1][lie - 1] , "s" );
}
else
{
printf("请选择黑方“将”的位置 --> ");
no = scanf("%d%d", &hang, &lie);
if (hang > 10 || hang < 8 || lie < 4 || lie > 6)
{
printf("输入无效,请重新输入");
goto loop;
}
strcpy(showboard[hang - 1][lie - 1], "将");
strcpy(trueboard[hang - 1][lie - 1], "Q" );
}
}
void putchess(char trueboard[10][9][3], char showboard[10][9][3], const char c[])
{
char ml[3] = "0";
int a1 = 0, a2 = 0, a3 = 0, k = 0, hang, lie, no;
//a1,a2,a3用于记录不同种类棋子放置的数量,当三个都为2时自动结束放置
//no无实际意义,用于减少vs的警告
//k用于判定操作
do
{
if (a1 == 2 && a2 == 2 && a3 == 2)
{
printf("放置结束\n");
Sleep(800);
break;
}
system("cls");
show(showboard);//打印棋盘
show(trueboard);
printf("输入“0”结束放置\n");
printf("请选择红方将要放置的棋子: 1.马 2.车 3.炮 --->");
no = scanf("%d", &k);
switch (k)
{
case 1:
loop1:
if (a1 == 2)//最多放置两个同类型的棋子
{
printf("您没马了\n");
Sleep(800);
break;
}
printf("请选择红方“马”的位置 -->");
no = scanf("%d%d", &hang, &lie);
if (hang < 0 || hang > 10 || lie < 0 || lie > 9 || strcmp(trueboard[hang - 1][lie - 1], "0") != 0)
{
printf("输入无效,请重新输入\n");
goto loop1;
}
strcpy(showboard[hang - 1][lie - 1], "马");
strcpy(trueboard[hang - 1][lie - 1], "m" );
a1++;
break;
case 2:
loop2:
if (a2 == 2)
{
printf("规则只允许场上存在红方两个“车”\n");
Sleep(800);
break;
}
printf("请选择红方“车”的位置 -->");
no = scanf("%d%d", &hang, &lie);
if (hang < 0 || hang > 10 || lie < 0 || lie > 9 || strcmp(trueboard[hang - 1][lie - 1], "0") != 0)
{
printf("输入无效,请重新输入\n");
goto loop2;
}
strcpy(showboard[hang - 1][lie - 1], "车");
strcpy(trueboard[hang - 1][lie - 1], "c" );
a2++;
break;
case 3:
loop3:
if (a3 == 2)
{
printf("规则只允许场上存在红方两个“炮”\n");
Sleep(800);
break;
}
printf("请选择红方“炮”的位置 -->");
no = scanf("%d%d", &hang, &lie);
if (hang < 0 || hang > 10 || lie < 0 || lie > 9 || strcmp(trueboard[hang - 1][lie - 1], "0") != 0)
{
printf("输入无效,请重新输入\n");
goto loop3;
}
strcpy(showboard[hang - 1][lie - 1], "炮");
strcpy(trueboard[hang - 1][lie - 1], "p" );
a3++;
break;
default:
break;
}
} while (k);
}
int judge(char board[10][9][3])
{
int hang = 0, lie = 0, hang1 = 0, lie1 = 0, hang3 = 0, lie3 = 0, n = 0, mid = 0;
//hang来记录“将”的位置,hang1来记录红方某个棋子的位置,hang3为变量,n用于记录find的返回值,mid用于统计两个棋子中间棋子的数量
find(&hang, &lie, board, "Q");
//找到“将”的位置
n = find(&hang1, &lie1, board, "s");
//找到"帅"的位置
if (n)
for (hang3 = 0; hang3 < 10; hang3++)//
if (strcmp(board[hang3][lie1], "Q") == 0)
return 1;//如果帅将对面,则黑方未被将死
hang1 = 0; lie1 = 0;//hang1初始化从头开始找起
n = find(&hang1, &lie1, board, "c");//找到第一个车
if (n)
{
if (hang1 == hang && lie1 > lie)//只有在hang1与hang相同,或者lie1与lie相同的时候车才可能将军
{
mid = 1;//mid设为1表示处于同一行,如果没有变成2,表示可以将军(和mid == 0区分开来)
for (lie3 = lie + 1; lie3 < lie1; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid = 2;//如果车和将中间有棋子则吃不了,mid设为2
}
else if (hang1 == hang && lie1 < lie)
{
mid = 1;
for (lie3 = lie1 + 1; lie3 < lie; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid = 2;
}
else if (lie1 == lie && hang1 < hang)
{
mid = 1;
for (hang3 = hang1 + 1; hang3 < hang; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid = 2;
}
else if (lie1 == lie && hang1 > hang)
{
mid = 1;
for (hang3 = hang + 1; hang3 < hang1; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid = 2;
}
if (mid == 1)//mid为1表示处于同一行或同一列,且中间没有棋子阻挡
return 0;
}
mid = 0;//将mid设为0,避免下次一寻找车的时候mid初始化不正确,出现未在同一行或同一列但mid == 1的情况
lie1++;//从第一个车的下一格开始寻找车
n = find(&hang1, &lie1, board, "c");
if (n)
{
if (hang1 == hang && lie1 > lie)
{
for (lie3 = lie + 1; lie3 < lie1; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid = 2;
}
else if (hang1 == hang && lie1 < lie)
{
mid = 1;
for (lie3 = lie1 + 1; lie3 < lie; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid = 2;
}
else if (lie1 == lie && hang1 < hang)
{
mid = 1;
for (hang3 = hang1 + 1; hang3 < hang; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid = 2;
}
else if (lie1 == lie && hang1 > hang)
{
mid = 1;
for (hang3 = hang + 1; hang3 < hang1; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid = 2;
}
if (mid == 1)
return 0;
}
mid = 0;//初始化为0,下次计算炮与将中间棋子数
hang1 = 0; lie1 = 0;
//回到(0,0),从头开始寻找下一种棋子
n = find(&hang1, &lie1, board, "p");
if (n)
{
if (hang1 == hang && lie1 > lie)//只有在hang1与hang相同,或者lie1与lie相同的时候跑才可能吃
{
for (lie3 = lie + 1; lie3 < lie1; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid++;//统计炮和将中间棋子的数量
}
else if (hang1 == hang && lie1 < lie)
{
for (lie3 = lie1 + 1; lie3 < lie; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid++;
}
else if (lie1 == lie && hang1 < hang)
{
for (hang3 = hang1 + 1; hang3 < hang; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid++;
}
else if (lie1 == lie && hang1 > hang)
{
for (hang3 = hang + 1; hang3 < hang1; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid++;
}
if (mid == 1)//炮和将中间棋子的数量为1的时候才能将军
return 0;
}
mid = 0;//初始化为0,使下次计算时从0开始计算棋子数
lie1++;
n = find(&hang1, &lie1, board, "p");
if (n)
{
if (hang1 == hang && lie1 > lie)
{
for (lie3 = lie + 1; lie3 < lie1; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid++;
}
else if (hang1 == hang && lie1 < lie)
{
for (lie3 = lie1 + 1; lie3 < lie; lie3++)
if (strcmp(board[hang1][lie3], "0") != 0 && strcmp(board[hang1][lie3], "1") != 0)
mid++;
}
else if (lie1 == lie && hang1 < hang)
{
for (hang3 = hang1 + 1; hang3 < hang; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid++;
}
else if (lie1 == lie && hang1 > hang)
{
for (hang3 = hang + 1; hang3 < hang1; hang3++)
if (strcmp(board[hang3][lie1], "0") != 0 && strcmp(board[hang3][lie1], "1") != 0)
mid++;
}
if (mid == 1)
return 0;
}
hang1 = 0; lie1 = 0;
//回到(0,0),从头开始寻找下一种棋子
n = find(&hang1, &lie1, board, "m");
if (n)
{
if (hang1 + 2 <= 10)//判定是否在边缘出现无法跳出棋盘的情况
if (board[hang1 + 1][lie1] == "0" || board[hang1 + 1][lie1] == "1")//判定是否“被别马脚”了
{
if (lie1 + 1 <= 9)
if (board[hang1 + 2][lie1 + 1] == "Q")
return 0;
if (lie1 - 1 >= 0)
if (board[hang1 + 2][lie1 - 1] == "Q")
return 0;
}
if (hang1 - 2 >= 0)
if (board[hang1 - 1][lie1] == "0" || board[hang1 - 1][lie1] == "1")
{
if (lie1 + 1 <= 9)
if (board[hang1 - 2][lie1 + 1] == "Q")
return 0;
if (lie1 - 1 >= 0)
if (board[hang1 - 2][lie1 - 1] == "Q")
return 0;
}
if (lie1 + 2 <= 10)
if (board[hang1][lie1 + 1] == "0" || board[hang1][lie1 + 1] == "1")
{
if (hang1 + 1 <= 10)
if (board[hang1 + 1][lie1 + 2] == "Q")
return 0;
if (hang1 - 1 >= 0)
if (board[hang1 - 1][lie1 + 2] == "Q")
return 0;
}
if (lie1 - 2 >= 0)
if (board[hang1][lie1 - 1] == "0" || board[hang1][lie1 - 1] == "1")
{
if (hang1 + 1 <= 10)
if (board[hang1 + 1][lie1 - 2] == "Q")
return 0;
if (hang1 - 1 >= 0)
if (board[hang1 - 1][lie1 - 2] == "Q")
return 0;
}
}
lie1++;
n = find(&hang1, &lie1, board, "m");
if (n)
{
if (hang1 + 2 <= 10)
if (board[hang1 + 1][lie1] == "0" || board[hang1 + 1][lie1] == "1")
{
if (lie1 + 1 <= 9)
if (board[hang1 + 2][lie1 + 1] == "Q")
return 0;
if (lie1 - 1 >= 0)
if (board[hang1 + 2][lie1 - 1] == "Q")
return 0;
}
if (hang1 - 2 >= 0)
if (board[hang1 - 1][lie1] == "0" || board[hang1 - 1][lie1] == "1")
{
if (lie1 + 1 <= 9)
if (board[hang1 - 2][lie1 + 1] == "Q")
return 0;
if (lie1 - 1 >= 0)
if (board[hang1 - 2][lie1 - 1] == "Q")
return 0;
}
if (lie1 + 2 <= 10)
if (board[hang1][lie1 + 1] == "0" || board[hang1][lie1 + 1] == "1")
{
if (hang1 + 1 <= 10)
if (board[hang1 + 1][lie1 + 2] == "Q")
return 0;
if (hang1 - 1 >= 0)
if (board[hang1 - 1][lie1 + 2] == "Q")
return 0;
}
if (lie1 - 2 >= 0)
if (board[hang1][lie1 - 1] == "0" || board[hang1][lie1 - 1] == "1")
{
if (hang1 + 1 <= 10)
if (board[hang1 + 1][lie1 - 2] == "Q")
return 0;
if (hang1 - 1 >= 0)
if (board[hang1 - 1][lie1 - 2] == "Q")
return 0;
}
}
hang1 = 0; lie1 = 0;
//回到(0,0)
return 1;//如果中途没有return 0说明最终没有棋子可以将军,即返回1表示未被将死
}
int find(int* hang, int* lie, char board[10][9][3], const char key[])
{
for (; *hang < 10; (*hang)++)//不需要初始化,为了第二次开始寻找某个棋子的时候从该格下一个开始寻找
{
for (; *lie < 9; (*lie)++)
{
if ((*hang) < 10 && (*lie) < 9)
if (strcmp(board[*hang][*lie], key) == 0)//寻找到了则返回1
return 1;
}
if (*lie == 9)
*lie = 0;
}
(*hang) = 0, (*lie) = 0;//未寻找到则返回0,并重置到(0,0)
return 0;
}