欧卡2中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

需要三步,才能开始

只需两步,慢速开始

玩欧卡就用莱仕达V10方向盘欧卡2入门方向盘选莱仕达V9莱仕达折叠便携游戏方向盘支架欢迎地图Mod入驻
查看: 5420|回复: 0
收起左侧

qq围棋棋谱文件wgs转换为sgf通用棋谱

[复制链接]
知行 发表于 2012-7-15 10:15 | 显示全部楼层 |阅读模式
@断桥残雪 、、、自己来看吧

实现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;
}

联系我们|手机版|欧卡2中国 ( 湘ICP备11020288号-1 )

GMT+8, 2024-4-24 13:58 , Processed in 0.031184 second(s), 7 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表