八数码游戏练习
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <cstdio>
#include <set>
#include<time.h>
#include <map>
#include<conio.h>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N = 4e5;
int d[4][2] = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};
ll kt(int *s);
struct Node
{
int a[10];
int id9;
int num;
int stp;
};
int stp[N];
bool check(int nx, int ny)
{
if (nx < 0 || ny < 0 || nx >= 3 || ny >= 3)
return true;
return false;
}
ll fact(int n)
{
if (n == 0)
return 1;
return n * fact(n - 1);
}
ll kt(int *s)
{
ll res = 0;
for (int i = 0; i < 9; i++)
{
int aj = 0;
for (int j = i + 1; j < 9; j++)
aj += s[i] > s[j];
res += aj * fact(8 - i);
}
return res;
}
bool vis[N];
void bfs(Node s)
{
memset(stp, -1, sizeof stp);
queue<Node> q;
q.push(s);
s.num = kt(s.a);
vis[s.num] = 1;
stp[s.num]=0;
while (q.size())
{
s = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int nx = s.id9 / 3 + d[i][0], ny = s.id9 % 3 + d[i][1];
if (check(nx, ny))
continue;
Node v = s;
v.id9 = nx * 3 + ny;
swap(v.a[v.id9], v.a[s.id9]);
v.num = kt(v.a);
v.stp = s.stp + 1;
if (vis[v.num])
continue;
stp[v.num] = v.stp;
vis[v.num] = 1;
q.push(v);
}
}
}
Node build()
{
srand((int)time(0));
struct Node t;
bool st[10];
memset(st, 0, sizeof st);
map<int, int> mp;
int cnt = 0;
vector<int> v;
while (1)
{
int x = rand() % 10;
if(x == 0) continue;
if (mp[x] == 0)
v.push_back(x), mp[x] = 1, cnt++;
if (cnt == 9)
break;
}
int i = 0;
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
if (*it == 9)
t.id9 = i;
t.a[i++] = *it;
}
t.num = kt(t.a);
t.stp = 0;
return t;
}
Node s;
void show(Node g)
{
if(stp[g.num] == 0){
cout<<endl<<endl
<<" /$$ /$$ /$$$$$$ /$$ /$$ /$$ /$$ /$$$$$$ /$$ /$$ /$$ /$$\n"
<<"| $$ /$$//$$__ $$| $$ | $$ | $$ /$ | $$|_ $$_/| $$$ | $$ | $$| $$\n"
<<" \ $$ /$$/| $$ \ $$| $$ | $$ | $$ /$$$| $$ | $$ | $$$$| $$ | $$| $$\n"
<<" \ $$$$/ | $$ | $$| $$ | $$ | $$/$$ $$ $$ | $$ | $$ $$ $$ | $$| $$\n"
<<" \ $$/ | $$ | $$| $$ | $$ | $$$$_ $$$$ | $$ | $$ $$$$ |__/|__/\n"
<<" | $$ | $$ | $$| $$ | $$ | $$$/ \ $$$ | $$ | $$\ $$$ \n"
<<" | $$ | $$$$$$/| $$$$$$/ | $$/ \ $$ /$$$$$$| $$ \ $$ /$$ /$$\n"
<<" |__/ \______/ \______/ |__/ \__/|______/|__/ \__/ |__/|__/\n";
cout<<endl<<endl;
getchar();
exit(0);
}
cout<<"\n***DIS = "<<stp[g.num]<<"***\n";
char disp[100][410];
int B = 5;
for(int i=0;i<3;i++)
for(int j=B;j<B+3;j++){
disp[i][j] = s.a[i*3+(j-B)] + '0';
if(s.a[i*3+(j-B)] == 9)
disp[i][j] = ' ';
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
disp[i][j] = g.a[i*3+j] + '0';
if(disp[i][j] == '9')
disp[i][j] = ' ';
}
}
for(int i=0;i<3;i++,puts(""))
for(int j=0;j<B+3;j++)
cout<<disp[i][j]<<' ';
}
Node get_start()
{
int id = 0 ;
while(stp[id]==-1)id++;
int a[9];
for(int i=0;i<9;i++)a[i] = i+1;
for(int i=0;i<id;i++)
next_permutation(a,a+9);
Node res;
for(int i=0;i<9;i++)
{
res.a[i] = a[i];
if(a[i]==9) res.id9 = i;
}
res.num = kt(res.a);
res.stp = stp[res.num];
return res;
}
int operate(Node &st)
{
char c = getch();
if(c == 'o') return 1;
map<char,int>mp;
{
mp['w'] = 0;
mp['d'] = 1;
mp['a'] = 2;
mp['s'] = 3;
}
int nx = st.id9/3 + d[mp[c]][0];
int ny = st.id9%3 + d[mp[c]][1];
if(check(nx,ny))
{
cout<<"Invalid operation\n";
return 0;
}
swap(st.a[st.id9],st.a[nx*3+ny]);
st.id9 = nx * 3 + ny;
st.num = kt(st.a);
st.stp = stp[st.num];
return 0;
}
void play()
{
Node st = get_start();
while(1)
{
show(st);
if(operate(st))break;
}
}
void start()
{
cout<<"----------------------------\n"
<<"| 操作说明:w,a,s,d控制 |\n"
<<"| 按'o' 结束游戏 |\n"
<<"| 按 Enter 开始游戏 |\n"
<<"----------------------------\n";
getchar();
}
int main()
{
s = build();
bfs(s);
start();
play();
return 0;
}