|
#include <graphics.h>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
#define Row 3
#define Col 3
int board[Row][Col]; //棋盘
key_msg keyMsg; //键盘
int zx,zy;//0的位置
int m1[3][3]={
1,2,5,
3,4,8,
6,7,0,
} ;
int m2[3][3]={0};
PIMAGE pimgs[9]; //棋盘图片
void loadImage()//图片载入
{
char path[100]; //加载图片路径
for(int i=0;i<9;i++)
{
pimgs[i]=newimage(); //向计算机申请一个图片空间
sprintf(path,"image/%d.png",i);//拼接图片相对路径
getimage(pimgs[i],path);//将系统中的图片数据存入pimgs
}
}
void draw()//图形绘制
{
setcolor(RED);
for(int i=0;i<Row;i++)
for(int j=0;j<Col;j++)
{
if(board[i][j]>0) putimage(j*100,i*100,pimgs[board[i][j]]);
}
setcolor(BLACK);
line(100,0,100,300);
line(200,0,200,300);
line(0,100,300,100);
line(0,200,300,200);
}
bool gameover()
{
for(int i=0;i<Row;i++)
for(int j=0;j<Col;j++)
{
if (board[i][j] != i*3+j)
{
return false;
}
}
//游戏结束
return true;
}
void find_zero(int b[][3])//找到0,使用函数,可以提前结束寻找
{
for(int i=0;i<Row;i++)
for(int j=0;j<Col;j++)
{
if(b[i][j]==0)
{
zx=i;
zy=j;
return;
}
}
}
int update_n(int m,int x)//根据现有棋盘特征值,动作 更新棋盘特征值
{
int n=0;
for(int i=2;i>=0;i--)//还原棋盘
for(int j=2;j>=0;j--)
{
m2[i][j]=m%10;
m=m/10;//形式参数,不会改变m的引用值
}
find_zero(m2);
switch(x)
{
case 1:
if(zx<2) swap(m2[zx][zy],m2[zx+1][zy]);
else return -1;//无法移动 返回-1
break;
case 3:
if(zy<2) swap(m2[zx][zy],m2[zx][zy+1]);
else return -1;
break;
case 2:
if(zx>0) swap(m2[zx][zy],m2[zx-1][zy]);
else return -1;
break;
case 4:
if(zy>0) swap(m2[zx][zy],m2[zx][zy-1]);
else return -1;
break;
default:break;
}
for(int i=0;i<=2;i++)//更新棋盘特征值
for(int j=0;j<=2;j++)
n=n*10+m2[i][j];
return n;
}
void bfs_8s()
{
set<int> check;//标记用 集合
int a[65536]={0};//特征值记录
int b[65536]={0};//记录动作 1上 2下 3左 4右
int c[65536]={0};//父节点记录
int h=0,t=1;
// b[1]=0;
// s[1]=1;
int n=0;//特征值
for(int i=0;i<=2;i++)
for(int j=0;j<=2;j++)
n=n*10+m2[i][j];
check.insert(n);//标记值n纳入集合
a[1]=n;//动作后的特征值
b[1]=0;//记录动作
c[1]=0;//父节点记录
cout<<n<<endl;
while(1)
{
h++;
for(int i=1;i<=4;i++)//四个方向
{
int k=update_n(a[h],i);//特征值为n的组合,翻转位置j的棋子
//cout<<k<<endl;
if(k!=-1&&(!check.count(k)))//可以向i方向移动+特征值未出现过
{
t++;
check.insert(k);
a[t]=k;
b[t]=i;
c[t]=h;
// cout<<k<<" "<<i<<" "<<h<<" "<<endl;
// getch();
if(k==12345678)//全黑
{
h=t;
int t2=t;
// cout<<k<<" "<<i<<" "<<j<<" "<<h<<" "<<endl;
// getch();
while(1)
{
if(c[t2]==0) break;
cout<<b[t2]<<"<-";
//getch();
t2=c[t2];
}
break;
}
}
}
if(h>=t) break;
}
}
void update()
{
find_zero(board);
switch(keyMsg.key)
{
case 'W':
if(zx<2) swap(board[zx][zy],board[zx+1][zy]);
break;
case 'A':
if(zy<2) swap(board[zx][zy],board[zx][zy+1]);
break;
case 'S':
if(zx>0) swap(board[zx][zy],board[zx-1][zy]);
break;
case 'D':
if(zy>0) swap(board[zx][zy],board[zx][zy-1]);
break;
case 'Q':
memcpy(board, m1, sizeof(m1));
break;
case 'E':
memcpy(m2, board, sizeof(board));
bfs_8s();
break;
default:break;
}
}
void start()//初始化
{
//关闭窗口不强制退出程序,以便进行游戏保存工作
// setinitmode(INIT_RENDERMANUAL | INIT_NOFORCEEXIT, 100, 50);
initgraph(Col*100,Row*100);//图形初始化
setcaption("翻转游戏"); //设置程序标题
setbkcolor(WHITE);
setlinewidth(5);// 设置当前线宽
setcolor(RED);
setfont(85,0,"微软雅黑");//(字体高度,字体宽度(为0即为自适应),字形)设置字体为25,幼圆字体
setbkmode(TRANSPARENT); //设置文字背景色为透明(默认为有背景色)
loadImage();
memcpy(board, m1, sizeof(m1));
}
int main()
{
start();
while(1)
{
while(kbmsg())
{
keyMsg = getkey();
if ((keyMsg.msg == key_msg_down)&&((keyMsg.key=='A')||(keyMsg.key=='S')||
(keyMsg.key=='W')||(keyMsg.key=='D')||(keyMsg.key=='Q'))||(keyMsg.key=='E'))
{
update();
}
}
draw();
delay_fps(60);
if(gameover()) {xyprintf(50,50,"获胜"); getch();}
cleardevice();
}
getch();
return 0;
} |
|