C语言实现中国象棋

 更新时间:2022年05月10日 14:37:17   作者:冰凌呀  
这篇文章主要为大家详细介绍了C语言实现中国象棋,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C语言实现中国象棋的具体代码,供大家参考,具体内容如下

运行截图

实现思路

老套路,二维数组存储棋盘,宏定义各种棋子,每次棋子的移动实质为二维数组的赋值。
重点是判断棋子是否可移动到目标位置,移动有两种可能,一是单纯移动,二是吃子移动。主要飞将的特殊规则。废话不多说,贴源码(主要下面是两个源文件哦)

源码

main.c

#include<stdio.h>
#include<string.h>
#include<windows.h>
//自定义源文件(棋谱结构) 
#include"manual.c"
//棋盘行列 
#define ROWS 10
#define COLS 9
//空地 
#define white 0
//红方棋子 
#define isred (map[i][j]>0&&map[i][j]<10)
#define ju 1
#define ma 2
#define xiang 3
#define shi 4
#define shuai 5
#define pao 6
#define bing 7
//黑方棋子
#define isblack (map[i][j]>10)
#define Ju 11
#define Ma 12
#define Xiang 13
#define Shi 14
#define Jiang 15
#define Pao 16
#define Zu 17 
//控制输出颜色 
#define NONECOLOR SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7)
#define REDCOLOR SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED)
#define GREENCOLOR SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN)
//当前玩家
#define red 1
#define black 0 

//地图 
int map[ROWS][COLS]={white};
//棋步 
char step[20];

//初始化地图 
void InitializeMap()
{
    int i,j;
    for(i=0;i<ROWS;i++)
    {
        for(j=0;j<COLS;j++)
        {
            map[i][j]=white;
        }
    }
    
/*
      0 1 2 3 4 5 6 7 8
    0车马象士将士象马车
    1
    2  砲          砲
    3卒  卒  卒  卒  卒
    4
    5
    6兵  兵  兵  兵  兵
    7  炮          炮
    8  
    9車馬相仕帥仕相馬車 
*/
    //黑方子力配置 
    map[0][0]=Ju;
    map[0][1]=Ma;
    map[0][2]=Xiang;
    map[0][3]=Shi;
    map[0][4]=Jiang;
    map[0][5]=Shi;
    map[0][6]=Xiang;
    map[0][7]=Ma;
    map[0][8]=Ju;
    map[2][1]=Pao;
    map[2][7]=Pao;
    map[3][0]=Zu;
    map[3][2]=Zu;
    map[3][4]=Zu;
    map[3][6]=Zu;
    map[3][8]=Zu;
    //红方子力配置
    map[6][0]=bing;
    map[6][2]=bing;
    map[6][4]=bing;
    map[6][6]=bing;
    map[6][8]=bing; 
    map[7][1]=pao;
    map[7][7]=pao;
    map[9][0]=ju;
    map[9][1]=ma;
    map[9][2]=xiang;
    map[9][3]=shi;
    map[9][4]=shuai;
    map[9][5]=shi;
    map[9][6]=xiang;
    map[9][7]=ma;
    map[9][8]=ju;
}

//打印地图
void displayMap()
{
    int i,j,k;
    printf(" ");
    for(k=0;k<COLS;k++)
    {
        printf(" %d",k);
    }
    printf("\n");
    for(i=0;i<ROWS;i++)
    {
        printf("%d ",i);
        for(j=0;j<COLS;j++)
        {
            if(map[i][j]==white)
            {
                NONECOLOR;
                printf("  ");
            }
            else
            {
                if(isred)
                {
                    REDCOLOR;
                }
                else if(isblack)
                {
                    GREENCOLOR;
                }
                switch(map[i][j])
                {
                    case ju:
                        printf("車");
                        break;
                    case Ju:
                        printf("车");
                        break;
                    case ma:
                        printf("馬");
                        break;
                    case Ma:
                        printf("马");
                        break;
                    case xiang:
                        printf("相");
                        break;
                    case Xiang:
                        printf("象");
                        break;
                    case shi:
                        printf("仕");
                        break;
                    case Shi:
                        printf("士");
                        break;
                    case shuai:
                        printf("帥");
                        break;
                    case Jiang:
                        printf("將");
                        break;
                    case pao:
                        printf("炮");
                        break;
                    case Pao:
                        printf("砲");
                        break;
                    case bing:
                        printf("兵");
                        break;
                    case Zu:
                        printf("卒");
                        break;
                }    
            }
        }    
        NONECOLOR;
        printf("\n");
    }    
    /*
    char border[][3]={"九","八","七","六","五","四","三","二","一"};
    printf("  ");
    for(k=0;k<9;k++)
    {
        printf("%s",border[k]);
    }
    */
    printf("\n\n"); 
} 

//将(x1,y1)的棋子移动到(x2,y2) 
void movePiece(int x1,int y1,int x2,int y2)
{
    map[x2][y2]=map[x1][y1];
    map[x1][y1]=white;
}

//获取玩家需要移动的棋子位置和移动到的目标位置
int getInput(int *x1,int *y1,int *x2,int *y2)
{
    printf("\n输入棋子坐标和目的坐标(全为-1时表示查看当前棋谱):\n");
    scanf("%d %d %d %d",x1,y1,x2,y2);
    if((*x1)<0||(*x1)>ROWS||(*y1)<0||(*y1)>COLS||(*x2)<0||(*x2)>ROWS||(*y2<0)||(*y2)>COLS)
    {
        return 0;
    }
    else if((*x1)==(*x2)&&(*y1)==(*y2))
    {
        return 0;
    }
    return 1;
} 

//判断是否已经结束游戏(-1:黑胜 0:还没结束 1:红胜) 
int isOver()
{
    int i,j;
    //没有將时红胜,没有帥时黑胜
    int haveShuai=0,haveJiang=0;
    for(i=0;i<ROWS;i++)
    {
        for(j=0;j<COLS;j++)
        {
            if(map[i][j]==shuai)
            {
                haveShuai=1;        
            }    
            else if(map[i][j]==Jiang)
            {
                haveJiang=1;
            }
        }    
    }    
    if(haveShuai==0)
    {
        return -1;
    }
    else if(haveJiang==0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
} 

//输出赢家 
void displayWinner(int winner)
{
    if(winner==1)
    {
        printf("红胜!\n");
    }
    else if(winner==-1)
    {
        printf("黑胜!\n");
    }
}

//打印当前回合的玩家
void displayPlayer(int player)
{
    printf("=======");
    if(player==red)
    {
        printf("红方回合"); 
    }
    else if(player==black)
    {
        printf("黑方回合");     
    }
    printf("=======");    
} 

//交替到对方回合 
void exchangePlayer(int *player)
{
    if((*player)==red)
    {
        *player=black;
    }
    else if((*player)==black)
    {
        *player=red;
    }
}

//坐标(x1,y1)上的棋子是否能移动到(x2,y2)上 
int canMove(int x1,int y1,int x2,int y2,int player)
{
    //当(x2,y2)为己方棋子时,不可以
    if(map[x2][y2]>0&&map[x2][y2]<10&&player==red||map[x2][y2]>10&&player==black)
    {
        return 0;    
    } 
    int piece=map[x1][y1];
    int i,j;
    int start,end;
    int eye_x=-1,eye_y=-1;
    int count=0;
    switch(piece)
    {
        //車、车 
        case ju:
        case Ju:
            if(x1==x2)
            {
                start=y1;
                end=y2;
                i=x1;
                if(y1>y2)
                {
                    start=y2;
                    end=y1;
                }
                for(j=start+1;j<end;j++)
                {
                    if(map[i][j]!=white)
                    {
                        return 0;
                    }
                }
            }
            else if(y1==y2)
            {
                start=x1;
                end=x2;
                j=y1;
                if(x1>x2)
                {
                    start=x2;
                    end=x1;
                }
                for(i=start+1;i<end;i++)
                {
                    if(map[i][j]!=white)
                    {
                        return 0;
                    }
                }
            }
            else
            {
                return 0;
            }
            break;
        case ma:
        case Ma:
            if(abs(x1-x2)==1&&y1-y2==2)
            {
                eye_x=x1;
                eye_y=y1-1;
            }
            else if(abs(x1-x2)==1&&y1-y2==-2)
            {
                eye_x=x1;
                eye_y=y1+1;
            }
            else if(abs(y1-y2)==1&&x1-x2==2)
            {
                eye_x=x1-1;
                eye_y=y1;
            }
            else if(abs(y1-y2)==1&&x1-x2==-2)
            {
                eye_x=x1+1;
                eye_y=y1;
            }
            if(eye_x==-1&&eye_y==-1)
            {
                return 0;
            }
            else if(map[eye_x][eye_y]!=white)
            {
                return 0;
            }
            break;
        case xiang:
        case Xiang:
            //相(象)过河 
            if((player==red&&x2<5)||(player==black&&x2>4)) 
            {
                return 0;
            }
            else if(abs(x1-x2)==2&&abs(y1-y2)==2)
            {
                eye_x=(x1+x2)/2;
                eye_y=(y1+y2)/2;
                if(map[eye_x][eye_y]!=white)
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
            break;
        case shi:
        case Shi:
            //出九宫
            if(player==red&&(x2<7||y2<3||y2>5)||player==black&&(x2>2||y2<3||y2>5))
            {
                return 0;    
            } 
            //不是走的斜一格 
            else if(abs(x1-x2)!=1||abs(y1-y2)!=1)
            {
                return 0;
            }
            break;
        case shuai:
        case Jiang:
            //飞将
            if((player==red&&x2<3||player==black&&x2>6)&&y1==y2)
            {
                start=x1;
                end=x2;
                j=y1;
                if(x1>x2)
                {
                    start=x2;
                    end=x1;    
                }    
                for(i=start+1;i<end;i++)
                {
                    if(map[i][j]!=white)
                    {
                        return 0;
                    }
                }
            } 
            else if(y2<3||y2>5||player==red&&x2<7||player==black&&x2>2||abs(x1-x2)+abs(y1-y2)!=1)
            {
                return 0;
            }
            break;
        case pao:
        case Pao:
            if(x1==x2)
            {
                start=y1;
                end=y2;
                i=x1;
                if(y1>y2)
                {
                    start=y2;
                    end=y1;
                }
                for(j=start+1;j<end;j++)
                {
                    if(map[i][j]!=white)
                    {
                        count++;
                    }
                }
                if(count>1)
                {
                    return 0;
                }
                else if(count==1)
                {
                    if(map[x2][y2]>10&&player==red||map[x2][y2]>0&&map[x2][y2]<10&&player==black)
                    {
                        return 1;
                    }
                    else
                    {
                        return 0;
                    }
                }
            }
            else if(y1==y2)
            {
                start=x1;
                end=x2;
                j=y1;
                if(x1>x2)
                {
                    start=x2;
                    end=x1;
                }
                for(i=start+1;i<end;i++)
                {
                    if(map[i][j]!=white)
                    {
                        count++;
                    }
                }
                if(count>1)
                {
                    return 0;
                }
                else if(count==1)
                {
                    if(map[x2][y2]>10&&player==red||map[x2][y2]>0&&map[x2][y2]<10&&player==black)
                    {
                        return 1;
                    }
                    else
                    {
                        return 0;
                    }
                }
            }
            else
            {
                return 0;
            }
            break;
        case bing:
        case Zu:
            //不是横或纵走一格 
            if((abs(x1-x2)+abs(y1-y2))!=1)
            {
                return 0;
            }
            //没过河时便左右移动 
            if(player==red&&x1>=5&&(abs(y1-y2)==1)||player==black&&(x1<=4)&&(abs(y1-y2)==1))
            {
                return 0;
            }
            //往后退 
            else if(player==red&&(x1-x2==-1)||player==black&&(x2-x1==-1))
            {
                return 0;
            }
            break;
    }
    return 1;
} 

//获得棋子名字 
char *getPieceName(int piece)
{
    switch(piece)
    {
        case Ju:
            return "车";
        case ju:
            return "車";
        case Ma:
            return "马";
        case ma:
            return "馬";
        case Xiang:
            return "象";
        case xiang:
            return "相";
        case Shi:
            return "士";
        case shi:
            return "仕";
        case Jiang:
            return "將";
        case shuai:
            return "帥";
        case Pao:
            return "砲";
        case pao:
            return "炮";
        case Zu:
            return "卒";
        case bing:
            return "兵";
    }
    return "";
}

//获得棋步 
void getStep(int x1,int y1,int x2,int y2,int player)
{
    //清空之前棋步 
    step[0]='\0';
    char border_red[][3]={"九","八","七","六","五","四","三","二","一"};
    char border_black[][3]={"1","2","3","4","5","6","7","8","9"};
    int i,j;
    int piece=map[x1][y1];
    int last=0,next=0;
    j=y1;
    for(i=0;i<x1;i++)
    {
        if(map[i][j]==piece)
        {
            last=1;
            break;
        }
    }
    for(i=x1+1;i<ROWS;i++)
    {
        if(map[i][j]==piece)
        {
            next=1;
            break;
        }
    }
    if(last==1&&next==1)
    {
        strcat(step,"中");
    }    
    else if(last==1)
    {
        if(player==red)
        {
            strcat(step,"后");
        }
        else
        {
            strcat(step,"前");
        }
    }
    else if(next==1)
    {
        if(player==red)
        {
            strcat(step,"前");
        }
        else
        {
            strcat(step,"后");
        }
    }
    strcat(step,getPieceName(map[x1][y1]));
    if(last==0&&next==0)
    {
        if(player==red)
        {
            strcat(step,border_red[y1]);
        }
        else
        {
            strcat(step,border_black[y1]);    
        }
    }
    if(x1==x2)
    {
        strcat(step,"平");
        if(player==red)
        {
            strcat(step,border_red[y2]);
        }
        else
        {
            strcat(step,border_black[y2]);    
        }
        return;
    }
    int distance=x2-x1;
    switch(map[x1][y1])
    {
        case Ju:
        case Jiang:
        case Pao:
        case Zu:
            if(distance>0)
            {
                strcat(step,"进");
            }
            else
            {
                strcat(step,"退");
            }
            strcat(step,border_black[abs(distance)-1]);
            break;
        case Ma:
        case Xiang:
        case Shi:
            if(distance>0)
            {
                strcat(step,"进");
            }
            else
            {
                strcat(step,"退");
            }
            strcat(step,border_black[y2]);
            break;
        case ju:
        case shuai:
        case pao:
        case bing:
            if(distance>0)
            {
                strcat(step,"退");
            }
            else
            {
                strcat(step,"进");
            }
            strcat(step,border_red[9-abs(distance)]);
            break;
        case ma:
        case xiang:
        case shi:
            if(distance>0)
            {
                strcat(step,"退");
            }
            else
            {
                strcat(step,"进");
            }
            strcat(step,border_red[y2]);
            break;
    }
}

int main()
{
    InitializeMap();
    //棋谱 
    manual m;
    //初始化棋谱 
    initializeManual(&m);
    //游戏是否已经结束 
    int isEnd=0;
    //坐标
    int x1,y1,x2,y2; 
    //输入是否合法
    int inputRight; 
    //移动是否成功
    int moveSuccess; 
    //当前玩家
    int player=red; 
    while(!isEnd)
    {
        system("cls");                            //清屏
        displayMap();                            //打印现在棋局
        displayPlayer(player);                    //当前玩家回合 
        inputRight=getInput(&x1,&y1,&x2,&y2);    //接收玩家输入
        if(x1==-1&&x2==-1&&y1==-1&&y2==-1)        //请求打印棋谱 
        {
            displayManual(m);                    //打印棋谱 
        }
        if(inputRight)                            //输入成功 
        {
                                                //是否选择己方棋子 
            if(map[x1][y1]>0&&map[x1][y1]<10&&player==red||map[x1][y1]>10&&player==black)
            {
                                                //是否可以移动 
                moveSuccess=canMove(x1,y1,x2,y2,player);
                if(moveSuccess)                    //可以移动 
                {                                //按照输入移动棋子 
                    getStep(x1,y1,x2,y2,player);
                    insertStep(step,&m);        //添加棋步到棋谱中 
                    printf("当前棋步为-->>%s\n",step);//打印当前棋步 
                    system("pause");
                    movePiece(x1,y1,x2,y2);    
                    exchangePlayer(&player);    //移动成功,轮到对方回合                            
                    isEnd=isOver();                //判断棋局是否已经结束        
                }
            }    
        } 
    }
    system("cls");
    displayMap();                                //打印现在棋局
    displayWinner(isEnd);
    saveManual(m,"manual.txt");
    return 0;
}

manual.c

#ifndef manual_c
#define manual_c
#define MAXCOUNT 200
//棋谱结构 
typedef struct manual
{
    int count;
    char step[MAXCOUNT][20];    
}manual;

//初始化棋谱 
void initializeManual(manual *m)
{
    m->count=0;
}

//打印棋谱 
void displayManual(manual m)
{
    printf("\n");
    if(m.count==0)
    {
        printf("当前棋谱为空!\n");    
    } 
    int i;
    for(i=0;i<m.count;i++)
    {
        if(i%2==0)
        {
            printf("%d-->>",i/2+1);
        }
        printf("%s  ",m.step[i]);
        if(i%2==1)
        {
            printf("\n");
        }
    }
    printf("\n");
    system("pause"); 
}

//添加棋步
void insertStep(char step[],manual *m)
{
    if(m->count>=MAXCOUNT)
    {
        return;
    }
    int i=m->count;
    strcpy(m->step[i],step);
    i++;
    m->count=i;    
} 

//删除棋步
void deleteStep(manual *m)
{
    int i=m->count;
    i--;
    m->count=i;    
} 

//保存棋谱 
void saveManual(manual m,char filepath[])
{
    int i;
    FILE *fp=fopen(filepath,"w");
    for(i=0;i<m.count;i++)
    {
        fprintf(fp,"%s\n",m.step[i]);
    }
    fclose(fp);
    printf("\n棋谱保存成功!\n");
}

//读取棋谱
void readManual(manual *m,char filepath[])
{
    int i=0;
    FILE *fp=fopen(filepath,"r");
    if(fp==NULL)
    {
        printf("棋谱文件丢失!\n");
        return;
    }
    while(1)
    {
        if(fscanf(fp,"%s",m->step[i])==EOF)
        {
            break;
        }
        i++;
    }
    m->count=i;
    fclose(fp);    
} 
#endif

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • c语言中的二级指针做函数参数说明

    c语言中的二级指针做函数参数说明

    这篇文章主要介绍了c语言中的二级指针做函数参数说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • C++ Boost Random随机函数详解

    C++ Boost Random随机函数详解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言中的时间函数clock()和time()你都了解吗

    C语言中的时间函数clock()和time()你都了解吗

    这篇文章主要为大家详细介绍了C语言中的时间函数clock()和time(),文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • Qt教程之QSqlQueryModel的使用详解

    Qt教程之QSqlQueryModel的使用详解

    QSqlQueryModel是QSqlTableModel的父类,它封装了执行SELECT语句从数据库查询数据的功能,本文将为大家介绍一下QSqlQueryModel的使用,需要的可以参考一下
    2022-11-11
  • C语言实现简单推箱子小游戏

    C语言实现简单推箱子小游戏

    这篇文章主要为大家详细介绍了C语言实现推箱子小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • c++类型转换及RTTI运行阶段类型识别

    c++类型转换及RTTI运行阶段类型识别

    这篇文章主要为大家介绍了c++类型转换及RTTI运行阶段类型识别详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2023-05-05
  • 深入解析C语言中的内存分配相关问题

    深入解析C语言中的内存分配相关问题

    这篇文章主要深入地介绍了C语言中的内存分配,C语言编程中的内存泄漏问题一直以来都是C编程中的一大棘手问题,本文从malloc和指针等方面对C内存进行了深层次讲解,强烈推荐!需要的朋友可以参考下
    2015-08-08
  • C++实现小型复数计算器

    C++实现小型复数计算器

    这篇文章主要为大家详细介绍了C++实现小型复数计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • 在C++ 中慎用setjmp和longjmp解析

    在C++ 中慎用setjmp和longjmp解析

    setjmp和longjmp是C语言中用于实现非局部跳转的函数,setjmp和longjmp 是 C 语言中一个很强大的函数,这篇文章主要介绍了在C++ 中慎用setjmp和longjmp的相关知识,需要的朋友可以参考下
    2023-06-06
  • C++面试八股文之如何避免死锁详解

    C++面试八股文之如何避免死锁详解

    在C++中,锁(Lock)是一种同步工具,用于保护共享资源,防止多个线程同时访问,那么如何避免死锁的情况出现呢,下面就为大家简单讲讲
    2023-07-07

最新评论