用c语言写一个简单的五子棋

    很高兴用了一下午终于把五子棋弄明白了!简单说一下我对五子棋的理解。

在五子棋中最重要的算法就是判断输赢,他的思路很简单,就是以一个棋子为中心,将他的水平,竖直,主对角线和斜对角线的四个方向依次判断是否存在五个连续且相同的棋子。

int judge(int x, int y)
{
    int i, j;
    int count;
    int winflag = 1;    //第一个点不用再次读取
    int cur;   //记录当前所下的棋
    cur = map[x][y] == 白棋 ? 白棋 : 黑棋;
    //printf("cur = %d", cur);
    //水平方向判断
    count = 0;
    for (i = x, j = y - 1; j > 0 && count++ < 5; j--) //读取num次,或者遇到边界 
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x, j = y + 1; j < N && count++ < 5; j++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;
    //垂直方向判断
    count = 0;
    for (i = x - 1, j = y; i > 0 && count++ < 5; i--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x + 1, j = y; i < N && count++ < 5; i++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;
    //主对角线判断
    count = 0;
    for (i = x - 1, j = y - 1; i > 0 && j > 0 && count++ < 5; j--, i--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x + 1, j = y + 1; i < N && j < N && count++ < 5; j++, i++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;
    //斜对角线判断
    count = 0;
    for (i = x + 1, j = y - 1; x < N && j > 0 && count++ < 5; j--, i++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x - 1, j = y + 1; i > 0 && j < N && count++ < 5; j++, i--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;

    return NO;
}

这是我第一次写的判断函数,比较简单明了,思路清晰,但是缺点是比较冗长,每个方向上的一些重复的步骤很多,然后我又查阅到一个大神通过二维数组写的一个简洁明了的代码,值得我们深思。

int judge(int x, int y)
{
    int i, j, k;
    const int step[4][2]={{1,0},{0,1},{1,1},{1,-1}};
    for(i=0;i<4;++i)
    {
        const int d[2]={-1,1};
        int count=1;
        for(j=0;j<2;++j)
            for( k=1;k<=4;++k){
                int row=x+k*d[j]*step[i][0];
                int col=y+k*d[j]*step[i][1];
                if( row>=1 && row<=N &&
                    col>=1 && col<=N &&
                    map[x][y] == map[row][col])
                    count+=1;
                else
                    break;
            }
        if(count>=5)
            return 1;
    }
    return 0;
}

这里通过step二维数组巧妙的将四个方向记录在数组中,又通过一维数组d将每个方向分成两部分,真的让我感到很精妙,将第一写的代码以一定规律巧妙的将重复部分融合在一起,形成了简短精炼的代码,这是值得我们学习的。

附上五子棋源码,如有错误请及时指出,让我们共同进步:

#include <stdio.h>
#include <stdlib.h>
#define N 15
#define OK 1
#define NO 0

int map[N][N] = {};
int whoturn = 0;

void initgame();
void playchess();
void printfchessmap();
int judge(int x, int y);

int main()
{
    initgame();

    while(1)
    {
        playchess();
        whoturn++;
    }

    return 0;
}

void initgame()
{
    char choice;
    printf("是否进入游戏(Y/N)");
    choice = getchar();
    if (choice != 'y' && choice != 'Y')     //注意这里的&&,不要写成||
        exit(0);
    //getchar();
    printf("\n");
    system("cls");
    printfchessmap();
}

void printfchessmap()
{
    int i, j;

    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            if (i == 0)
                printf("%3d", j);
            else if (j == 0)
                printf("%3d", i);
            else if (1 == map[i][j])
                printf("%3c", 'O');
            else if (2 == map[i][j])
                printf("%3c", 'X');
            else
                printf("%3c", '*');
        }
        printf("\n");
    }
}

void playchess()
{
    int x, y;

    if (0 == whoturn % 2)
    {
        printf("现在轮到玩家1,请落子:");
        scanf("%d %d", &x, &y);
        while(0 != map[x][y])
        {
            printf("这个位置已经有棋子了,请重新输入:");
            scanf("%d %d", &x, &y);
        }
        map[x][y] = 1;
    }
    else if (1 == whoturn % 2)
    {
        printf("现在轮到玩家2,请落子:");
        scanf("%d %d", &x, &y);
        while(0 != map[x][y])
        {
            printf("这个位置已经有棋子了,请重新输入:");
            scanf("%d %d", &x, &y);
        }
        map[x][y] = 2;
    }
    system("cls");
    printfchessmap();
    if (judge(x, y)){
        printf("玩家%d获胜\n",1 + whoturn % 2);
        exit(0);
    }
}

int judge(int x, int y)
{
    int i, j;
    int count;
    int winflag = 1;    //第一个点不用再次读取
    int cur;   //记录当前所下的棋
    cur = map[x][y] == 1 ? 1 : 2;
    printf("cur = %d", cur);
    //水平方向判断
    count = 0;
    for (i = x, j = y - 1; j > 0 && count++ < 5; j--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x, j = y + 1; j < N && count++ < 5; j++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;
    //垂直方向判断
    count = 0;
    for (i = x - 1, j = y; i > 0 && count++ < 5; i--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x + 1, j = y; i < N && count++ < 5; i++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;
    //主对角线判断
    count = 0;
    for (i = x - 1, j = y - 1; i > 0 && j > 0 && count++ < 5; j--, i--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x + 1, j = y + 1; i < N && j < N && count++ < 5; j++, i++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;
    //斜对角线判断
    count = 0;
    for (i = x + 1, j = y - 1; x < N && j > 0 && count++ < 5; j--, i++)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    count = 0;
    for (i = x - 1, j = y + 1; i > 0 && j < N && count++ < 5; j++, i--)
    {
        if (map[i][j] == cur)
        {
            winflag++;
        }
        else
            break;
    }
    if (winflag >= 5)
        return OK;
    else
        winflag = 1;

    return NO;
}




猜你喜欢

转载自blog.csdn.net/qq_41282102/article/details/80465311