@断桥残雪 、、、自己来看吧
实现qq围棋棋谱文件wgs转化为通用棋谱sgf文件,首先简要分析wgs文件内容:
/* qq棋谱文件(.wgs)分析(用UltraEdit打开,(xxh,x)表示位置):
(00h,a)~(10h,f)表示执黑棋手姓名,共22字节;
(30h,a)~(40h,f)表示执白棋手姓名,共22字节;
棋手姓名前面六个字节,保存的是qq号信息,从低位到高位,直接转换为十进制;
比如黑棋qq号保存在(00h,4)~(00h,9)字节内,信息为
E9 03 E4 41 00 00
则表示的qq号是 00 00 41 E4 03 E9 所表示的十进制数,即 1105462249
棋盘大小 在wgs文件中,棋盘路数信息保存在 60h行,5列,第101字节处
手数保存在 (70h,8)~(70h,9);
对局从(70h,a)开始;
*/
代码实现:#include<iostream>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int main()
{
ifstream inFile;
ofstream gofile;
ofstream sgffile;
int lu; //棋盘大小 在wgs文件中,棋盘路数信息保存在 60h行,5列,第101字节处
int filesize; //棋谱文件大小
char* filepath; //棋谱文件路径
filepath=new char[100];
char* newfilepath; //sgf文件路径
newfilepath=new char[100];
cout<<"请输入棋谱文件路径:";
cin.get(filepath,100);
cout<<"棋谱路径:"<<filepath<<endl;
/*
得到要输出的sgf文件的路径,首先获得filepath的长度,然后截断原扩展名,在连接新扩展名,截断扩展名时
应把 .wgs 截去,然后接上 .sgf,不能截 wgs 接 sgf,那样输入相对路径时不能得到正确结果,具体原因未明。
#include <string.h>
void *memcpy( void *to, const void *from, size_t count );
功能:函数从from中复制count 个字符到to中,并返回to指针。 如果to 和 from 重叠,则函数行为不确定。
*/
memcpy(newfilepath,filepath,strlen(filepath)-4); //截断 .wgs
strcat(newfilepath,".sgf"); //新扩展名 .sgf
cout<<"新文件路径:"<<newfilepath<<endl;
inFile.open(filepath);
inFile.seekg(10,ios::beg); //黑棋棋手姓名保存在距文件开始10字节处
char* pb; //黑棋棋手姓名
char* pw; //白棋棋手姓名
pb=new char[22];
pw=new char[22];
inFile.get(pb,22); //棋手姓名信息占用22字节
cout<<"黑棋:"<<pb<<endl;
inFile.seekg(58,ios::beg); //白棋棋手姓名保存在距文件开始58字节处
inFile.get(pw,22); //棋手姓名信息占用22字节
cout<<"白棋:"<<pw<<endl;
inFile.close();
inFile.open(filepath,ios::in|ios::binary); //打开棋谱
if(!inFile)
{
cerr<<"File Open Error!"<<endl;
system("pause");
exit(0);
}
else
{
inFile.seekg(0,ios::end);
filesize=inFile.tellg();
cout<<"文件字节数:"<<filesize<<endl;
}
unsigned char b[filesize]; //棋谱二进制文件缓冲区
//如:00 00 41 E4 03 E9,bqq[0]=00,bqq[1]=0,..,计算个位置后计算 bqq[]的和即为qq号
int bqq[6]; //黑棋qq号
int wqq[6]; //白棋qq号
long long blackqq; //黑棋qq号,long long 类型以便保存10位数及以上的qq号
long long whiteqq; //白棋qq号
inFile.seekg(4,ios::beg); //定位到第4字节处读取黑棋qq号
for(int i=0;i<6;i++)
{
inFile.read((char*)&b[i],sizeof(char));
}
int k=0;
for(int i=5;i>=0;i--)
{
bqq[k]=(int)b[i];
cout<<"bqq["<<k<<"]="<<bqq[k]<<endl;
k++;
}
cout<<endl;
/*
计算qq号 ,若某qq号16进制形式数组为:qq[6]={00 00 41 E4 03 E9},则qq号计算过程:
(4*16^7+1*16^6) + (14*16^5+4*16^4)+ ... =(4*16+1)*16^6 + (14*16+4)*16^4 + ......
而41表示的十进制数为 4*16+1 ,E4表示的数为 14*16+4,则可见规律为 :
qq号= qq[0]*16^10 + qq[1]*16^8 + qq[2]*16^6 + qq[3]*16^4 + +qq[4]*16^2 + qq[5]*16^0;
*/
blackqq=bqq[0]*1099511627776+bqq[1]*4294967296+bqq[2]*16777216+bqq[3]*65536+bqq[4]*256+bqq[5];
cout<<"blackqq="<<blackqq<<endl;
inFile.seekg(52,ios::beg); //定位到第52字节处读取白棋qq号
for(int i=0;i<6;i++)
{
inFile.read((char*)&b[i],sizeof(char));
}
k=0;
for(int i=5;i>=0;i--)
{
wqq[k]=(int)b[i];
cout<<"wqq["<<k<<"]="<<wqq[k]<<endl;
k++;
}
cout<<endl;
/*
计算qq号 ,若某qq号16进制形式数组为:qq[6]={00 00 41 E4 03 E9},则qq号计算过程:
(4*16^7+1*16^6) + (14*16^5+4*16^4)+ ... =(4*16+1)*16^6 + (14*16+4)*16^4 + ......
而41表示的十进制数为 4*16+1 ,E4表示的数为 14*16+4,则可见规律为 :
qq号= qq[0]*16^10 + qq[1]*16^8 + qq[2]*16^6 + qq[3]*16^4 + +qq[4]*16^2 + qq[5]*16^0;
*/
whiteqq=wqq[0]*1099511627776+wqq[1]*4294967296+wqq[2]*16777216+wqq[3]*65536+wqq[4]*256+wqq[5];
cout<<"whiteqq="<<whiteqq<<endl;
inFile.seekg(101,ios::beg); //定位到据文件开始101字节处读取棋盘大小信息
inFile.read((char*)&b[101],sizeof(char));
lu=(unsigned int)b[101]; //棋盘路数
inFile.seekg(122,ios::beg); //指针定位到据文件首部122字节处
int shoushu=filesize-122; //2倍手数
int t[shoushu]; //保存手数信息
gofile.open("qqgo.txt");
for(int i=122;i<filesize;i++)
{
inFile.read((char*)&b[i],sizeof(char));
gofile<<hex<<(unsigned int)b[i]<<" ";
t[i-122]=(unsigned int)b[i];
cout<<t[i-122]<<" ";
}
sgffile.open(newfilepath,ios::out); //先写入打开,确保重新写入时先清空文件内容
sgffile.close(); //需要先关闭才能再次以追加方式打开
sgffile.open(newfilepath,ios::app); //ios:app 添加输入
sgffile<<"(;CA[gb2312]SZ["<<lu<<"]"<<"PB["<<pb<<blackqq<<"]PW["<<pw<<whiteqq<<"]AP[WGS2SGF1.0]MULTIGOGM[1]\n";
/*
97~122对应字母a~z, 列:32对应i,0对应a,4对应b,8对应c,....;97+t[i]/4可以实现0->97,4->98,8->99...的映射,
行:0->a,1->b,2->c... t[j]+97实现映射;
*/
int tmp=0; //sgf文件换行
for(int j=0;j<shoushu;j++)
{
if((j/2)%2==0) //判断黑白,奇数手为黑,偶数手为白
{
if(t[j]==1&&t[j+1]==0) //脱先,在wgs对应16进制 01 00,在sgf中对应B[]或者W[]
{
sgffile<<";B[];";
j++;
}
else
{
sgffile<<";B["<<((char)(97+t[j]/4))<<((char)(97+t[j+1]))<<"];";
j++; //读取了两个字节,需加1
}
}
else
{
if(t[j]==1&&t[j+1]==0) //脱先,在wgs对应16进制 01 00,在sgf中对应B[]或者W[]
{
sgffile<<"W[]";
j++;
}
else
{
sgffile<<"W["<<((unsigned char)(97+t[j]/4))<<((unsigned char)(97+t[j+1]))<<"]";
j++;
}
}
tmp++;
if(tmp%14==0) //14手换一行
sgffile<<endl;
}
sgffile<<")";
delete [] filepath;
delete [] pb;
delete [] pw;
inFile.close();
gofile.close();
sgffile.close();
system("pause");
return 0;
}
|