#include<string>
#include<conio.h>
#include<stdio.h>
#include <graphics.h> // 引用 EasyX 图形库
#define MAXSIZE 100//用于马所遍历的点最大值
using namespace std;
int X,Y,mx,my,x,y,hx,hy,zcx,zcy,zxx,zyy;
wchar_t ix[10];
wchar_t iy[10];
int flag=0;
int count=1;
char zx[1];
char zy[1];
char s[] = "马的遍历";
char t[]="马:";
char T[]="遍历结束";
int getmouse(int c);
int nn,mm;
int dir[8][2]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}}; //八个方向
int nexti[8],nextj[8];
int board[10][10];
int exists[8]; //记录当前点的下一个点的出路数
int getpoint(int hx,int hy);
typedef struct
{
int x,y;
}biaoji;//马的坐标 用于自动遍历
typedef struct
{
biaoji di[8];
}biao;//存储马八个方向
void initial(biao &L ){
for(int i=0;i<8;i++){
L.di[i].x=0;
L.di[i].y=0;
}
}//初始化八个坐标坐标的方向为0
int tag(biao &L,int mx, int my){
flag++;
board[mx][my] =flag;
int j,i;
i=0;
for(j=0;j<8;j++){
if(board[mx+dir[j][0]][my+dir[j][1]]==0&&0<mx+dir[j][0]&&mx+dir[j][0]<x+1&&0<my+dir[j][1]&&my+dir[j][1]<y+1){
i++;
L.di[j].x=mx+dir[j][0];
L.di[j].y=my+dir[j][1];
}
}
if(i==0){ getpoint(0,0);return 1;}//无位置走则带入0 0结束
return 0;
}//标记八个反向的坐标(走过则不予标记board[x][y]数组中存走的第几次数,x,y表示其中马的坐标)
int judge(biao &L,int x,int y){
for(int j=0;j<8;j++){
if(L.di[j].x==x&&L.di[j].y==y)
return 1;
}
return 0;
}
void paint(){
char qx[1];
char qy[1];
X=(x)*100+40;
Y=(y-1)*100+40;
initgraph(X,Y+50);
setbkcolor(YELLOW);
cleardevice();
settextstyle(25, 0, "黑体");
setlinestyle(PS_SOLID,2); //设置线的样式
setlinecolor(BLACK);//设置线的颜色
settextcolor(BLACK);//设置字体的颜色
outtextxy((X-140)/2,0,s);//设置字体的位置
outtextxy(X-110,10,"遍历顺序");
for(int i=0;i<=((Y-40)/100);i++){
line(20,100*i+70,X-120,100*i+70);
sprintf(qx,"%d",i+1);
outtextxy(2,100*i+65,qx);
}//滑动y轴划线
for(int j=0;j<=((X-140)/100);j++){
line(100*j+20,70,100*j+20,Y+30);
sprintf(qy,"%d",j+1);
outtextxy(100*j+15,40,qy);
}//滑动x轴划线
}//画棋盘
int getpoint(int hx,int hy){
if(hx==0&&hy==0) {
outtextxy(X-110,Y,"未遍历完全");
_getch();
return 1;
} settextstyle(15, 0, "黑体");
if(flag||count) clearcircle(20+(zcx-1)*100,70+(zcy-1)*100,10);
if(flag+1) outtextxy(0,0,"返回");
count++;
setfillcolor(BLACK);
fillcircle(20+(hx-1)*100,70+(hy-1)*100,10);
sprintf(zx,"%d",hx);
sprintf(zy,"%d",hy);
settextcolor(BLACK);//设置字体的颜色
if(15*(count)+50<Y){
outtextxy(X-110,15*(count)+50,t);//设置字体的位置
outtextxy(X-90,15*(count)+50,zy[0]);//设置字体的位置
outtextxy(X-75,15*(count)+50,zx[0]);//设置字体的位置
}
if(15*(count)+50>=Y){
outtextxy(X-60,15*(count)+115-Y,t);//设置字体的位置
outtextxy(X-40,15*(count)+115-Y,zy[0]);//设置字体的位置
outtextxy(X-25,15*(count)+115-Y,zx[0]);//设置字体的位置
}
settextstyle(22, 0, "黑体");
if(count==x*y){
outtextxy(X-110,Y,"已完全遍历");
_getch();
}
else{
outtextxy(X-110,Y,"正在遍历中");
}
Sleep(1000);
zcx=hx;
zcy=hy;
return 0;
} //获取棋盘点的位置
int input1(){
int v=0;
initgraph(480, 480);
setbkcolor(YELLOW);
cleardevice();
//设置字体颜色 还有测试显示字体
settextcolor(BLACK);
settextstyle(25, 0, "黑体");
outtextxy(200, 50, "自动遍历");
outtextxy(100,100, "棋盘大小");
outtextxy(100, 180, "起始坐标");
outtextxy(0, 0, "-------------------------------------");
outtextxy(0, 300, "-------------------------------------") ;
string str1,str2,str3,str4; //头文件 string
//str1用来放c的总内容 str2每次存放“显示内容:”+str1,方便输出
char c; //定义字符c接收键盘输入
while(v!=5){
c=_getch();
if (c== '\b')
{ v--;
if(v<2)
str1 = str1.substr(0, str1.size()-1);
else
str3 = str3.substr(0, str3.size() - 1);
}//如果c是退格符,str1删掉一个
else{
if(c!=' ')//是否是空格
v++;
if(v<=2){
str1 += (int)c;
if(v==1)
hx=(int)c;
else if(v==2)
hy=(int)c;
}//判断在第几行输入
else{
str3+=(int)c;
if(v==3)
my=(int)c;
else if(v==4)
mx=(int)c;}
}
str2 = "棋盘大小:" + str1;
str4 = "起始坐标:" + str3;
cleardevice();
outtextxy(0, 0, "------------------------------------");
outtextxy(0, 300, "------------------------------------");
outtextxy(200, 50, "自动遍历");
outtextxy(100, 100, str2.c_str());
outtextxy(100, 180, str4.c_str());
if(v==4){
outtextxy(0, 400, "------------按任意键进入----------");
v++;
_getch();
}
}closegraph();
return 0;
}
int input2(){
int v=0;
initgraph(480, 480);
setbkcolor(YELLOW);
cleardevice();
//设置字体颜色 还有测试显示字体
settextcolor(BLACK);
settextstyle(25, 0, "黑体");
outtextxy(200, 50, "手动遍历");
outtextxy(100,100, "棋盘大小");
outtextxy(0, 0, "-------------------------------------");
outtextxy(0, 300, "-------------------------------------") ;
string str1,str2; //头文件 string
//str1用来放c的总内容 str2每次存放“显示内容:”+str1,方便输出
char c; //定义字符c接收键盘输入
while(v!=3){
c=_getch();
if (c== '\b')
{ v--;
str1 = str1.substr(0, str1.size()-1);
}//如果c是退格符,str1删掉一个
else{
if(c!=' ')//是否是空格
v++;
str1 += (int)c;
if(v==1)
hx=(int)c;
else
hy=(int)c;
}//判断在第几行输入
str2 = "棋盘大小:" + str1;
cleardevice();
outtextxy(0, 0, "------------------------------------");
outtextxy(0, 300, "------------------------------------");
outtextxy(200, 50, "手动遍历");
outtextxy(100, 100, str2.c_str());
if(v==2){
outtextxy(0, 400, "------------按任意键进入----------");
v++;
_getch();
}
}closegraph();
return 0;
}
int slove(int x,int y)
{
getpoint(y,x);
memset(board,0,sizeof(board));
memset(exists,0,sizeof(exists));
memset(nexti,0,sizeof(nexti));
memset(nextj,0,sizeof(nextj));//初始化数组
int cnt,t,minx,tmp;
board[x][y] = 1;
for(int i=2;i<=nn*mm;++i){
for(int k=0;k<8;++k){
exists[k] = 0; //初始化出路的个数为0
}
t = 0;
for(int j=0;j<8;++j){
int nx = x + dir[j][0];
int ny = y + dir[j][1];
if(nx<1||nx>nn||ny<1||ny>mm) continue;
if(board[nx][ny] == 0){ //如果这个方向可走,则记录方向
nexti[t] = nx;
nextj[t] = ny;
t++;
}
}
cnt = t; //cnt记录的是从当前点向8个方向走,可以落子的点的个数
if(cnt == 0) { getpoint(0,0) ;return 0 ;} //从这一步无路可走
else if(cnt == 1){ //只有一个可以走的方向,则这个方向就是最少出路的方向
minx=0;
}
else{
for(k=0;k<cnt;++k){
for(int j=0;j<8;++j){
int nx = nexti[k]+dir[j][0];
int ny = nextj[k]+dir[j][1];
if(nx<1||nx>nn||ny<1||ny>mm) continue;
if(board[nx][ny]==0){
exists[k]++; //记录下个位置的出路数据
}
}
}
tmp = exists[0];
minx = 0;
for(k=1;k<cnt;++k){
if(exists[k] < tmp){
tmp = exists[k];
minx = k;
}
}
}
x = nexti[minx];
y = nextj[minx];
getpoint(y,x);
board[x][y] = i;
}
return 1;
}
int getmouse(int c){
MOUSEMSG m;
switch(c){
case 1:
while(1){
m = GetMouseMsg();
if(m.x>=190&&m.x<=240&&m.y>=300&&m.y<=340){
setlinecolor(BLUE);
rectangle(190,300,240,340);
if (m.uMsg == WM_LBUTTONDOWN) { //如果按下鼠标左键实现相应功能.
closegraph();
return 1;
}
}
else if(m.x>=260&&m.x<=310&&m.y>=300&&m.y<=340){
setlinecolor(BLUE);
rectangle(260,300,310,340);
if (m.uMsg == WM_LBUTTONDOWN) { //如果按下鼠标左键实现相应功能.
exit(0);
}
}
else
{
setlinecolor(YELLOW);
rectangle(190,300,240,340);
rectangle(260,300,310,340);
}
}break;
case 2: biao L;
initial(L);
memset(board,0,sizeof(board));
while(1){
a: m = GetMouseMsg();
if(m.x<40&&m.y<20&&m.uMsg == WM_LBUTTONDOWN){
return 1;
}
if (m.uMsg == WM_LBUTTONDOWN&&m.x<=X-120){//如果按下鼠标左键实现相应功能.
if(flag!=0){
if(!judge(L,m.x/100+1,m.y/100+1)||zxx==m.x/100+1&&zyy==m.y/100+1)goto a;
}
getpoint(m.x/100+1,m.y/100+1);
zxx=m.x/100+1;
zyy=m.y/100+1;
initial(L);
if(tag(L,m.x/100+1,m.y/100+1)) return 0;
}
}break;
case 3:
while(1){
m = GetMouseMsg();
if(m.x>=110&&m.x<=360&&m.y>=150&&m.y<=220){
setlinecolor(BLUE);
rectangle(110,150,360,220);
if (m.uMsg == WM_LBUTTONDOWN) { //如果按下鼠标左键实现相应功能.
closegraph();
return 2;
}
}
else if(m.x>=110&&m.x<=360&&m.y>=300&&m.y<=370){
setlinecolor(BLUE);
rectangle(110,300,360,370);
if (m.uMsg == WM_LBUTTONDOWN) { //如果按下鼠标左键实现相应功能.
closegraph();
return 1;
}
}
else
{
setlinecolor(YELLOW);
rectangle(110,150,360,220);
rectangle(110,300,360,370);
}
}break;
}
return 1;
}
void gameover(){
initgraph(480, 480);
setbkcolor(YELLOW);
cleardevice();
settextcolor(BLACK);
settextstyle(60, 0, "黑体");
outtextxy(130, 100, "游戏结束");
settextstyle(40, 0, "黑体");
outtextxy(160, 200, "是否继续?");
outtextxy(190, 300, "是");
outtextxy(260, 300, "否");
getmouse(1);
}
int show(){
initgraph(480,480);
setbkcolor(YELLOW);
cleardevice();
settextcolor(BLACK);
settextstyle(60, 0, "黑体");
outtextxy(110,0,"马的遍历");
settextstyle(40, 0, "黑体");
outtextxy(130,150,"手动遍历");
outtextxy(130,300,"自动遍历");
return getmouse(3);
}
int main(){
A: count=0;flag=0;
switch(show()){
case 1:input1(); x=hx-48;
y=hy-48;
mm=x;
nn=y;
mx=mx-48;
my=my-48;
paint();
slove(mx,my);
gameover();
goto A;break;
case 2:input2();
x=hx-48;
y=hy-48;
paint();
if(getmouse(2)) goto A;
else{gameover();
goto A;}
}
return 1;
}
//需要下载easyx库