五子棋(C语言) [实现了简单人机,人人,以及提示和复盘的功能]

#include <stdio.h>
#include<string.h>
#include<windows.h>

#define N 15
#define same_u_i same(row + dx[u] * i, col + dy[u] * i, p[row][col])//u方向i距离的点是否同色
#define OutOrNotEmpty (!inboard(row + dx[u] * i, col + dy[u] * i) || p[row + dx[u] * i][col + dy[u] * i] != 0) //出了棋盘或者非空格点

int p[N + 2][N + 2]; //0空1黑2白  1●2○ -1▲-2△
int s = 0, ais = 1, s0;//s是轮到谁下,s=1,2,s=1是ai下,s=2是玩家,s=s0是黑方下,否则是白方下
int k,x = 0; //决定人人对抗还是人机对抗
int is_end = 0;
int dx[8] = { 1, 1, 0, -1, -1, -1, 0, 1 }; //flat技术
int dy[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };//(dx,dy)是8个方向向量
int manu[2][300], manukey = 0;//棋谱
int a2;
int l = 0;
int a1,b1;
int pa[2][300];
int keyi, keyj;

int out(int i, int j)//打印棋盘
{
    if (p[i][j] == 1)return printf("-●-");
    if (p[i][j] == 2)return printf("-○-");
    if (p[i][j] == -1)return printf("-▲-");
    if (p[i][j] == -2)return printf("-△-");
    if (i == N)
    {
        if (j == 1)return printf(" ┏-");
        if (j == N)return printf("-┓ ");
        return printf("-┯-");
    }
    if (i == 1)
    {
        if (j == 1)return printf(" ┗-");
        if (j == N)return printf("-┛ ");
        return printf("-┷-");
    }
    if (j == 1)return printf(" ┠-");
    if (j == N)return printf("-┨ ");
    return printf("-┼-");
}

void DrawBoard()//打印整个游戏界面
{
    system("cls");
    int row = 0, col = 0, keyr = 0, keyc = 0;
    char alpha = 'A';
    printf("\n\n\n     ");
    printf("  ");
    for (col = 1; col <= N; col++)printf("%c  ", alpha++);
    for (row = N; row >= 1; row--)
    {
        printf("\n   %2d ", row);
        for (col = 1; col <= N; col++)
        {
            out(row, col);
            if (p[row][col] < 0)keyr = row, keyc = col;
        }
        printf(" %d", row);
    }
    alpha = 'A';
    printf("\n     ");
    printf("  ");
    for (col = 1; col <= N; col++)printf("%c  ", alpha++);
    printf("\n\n");
    if(k == 0)
    {
        if (s0 == ais)printf("  AI执黑,玩家执白\n");
        else printf("  AI执白,玩家执黑\n");
        alpha = 'A';
        if (keyr)printf("  最后落子位置:%c%d\n", alpha + keyc - 1, keyr);
    }
    else if(k == 1)
    {
        printf("  玩家一执黑,玩家二执白\n");
        alpha = 'A';
        if (keyr)printf("  最后落子位置:%c%d\n", alpha + keyc - 1, keyr);
    }
}

void init()//游戏开局初始化
{
    system("color f0");
    printf("输入A或者B进行选择\nA:人机对抗\nB:双人对抗\n");
    char pt;
    scanf(" %c",&pt);
    if(pt != 'A' && pt != 'B')
    {
        printf("输入错误,请重新输入!\n");
        return init();
    }
    else if(pt == 'A')
    {
        k = 0;
        printf("输入1或者2进行选择\n1:AI执黑先行\n2:玩家执黑先行\n");
        scanf("%d", &s);
        while (s != 1 && s != 2)
        {
            printf("输入错误,请重新输入!\n");
            printf("输入1或者2进行选择\n1:AI执黑先行\n2:玩家执黑先行\n");
            scanf("%d",&s);
        }
        s0 = s;
        int i, j;
        for (i = 0; i <= N + 1; i++)for (j = 0; j <= N + 1; j++)p[i][j] = 0;//以空格包围棋盘
        for (j = 0; j < 300; j++)manu[0][j] = manu[1][j] = 0;
    }
    else if(pt == 'B')
    {
        k = 1;
        x = 1;
    }
}

int inboard(int row, int col)//判断(row,col)是否在棋盘内
{
    if (row <1 || row > N)return 0;
    return col >= 1 && col <= N;
}

int same(int row, int col, int key)//判断2个棋子是否同色
{
    if (!inboard(row, col))return 0;
    return (p[row][col] == key || p[row][col] + key == 0);
}

int num(int row, int col, int u)//坐标(row,col),方向向量u,返回该方向有多少连续同色棋子
{
    int i = row + dx[u], j = col + dy[u], sum = 0, ref = p[row][col];
    if (ref == 0)return 0;
    while (same(i, j, ref))sum++, i += dx[u], j += dy[u];
    return sum;
}

int live4(int row, int col)//活4的数量
{
    int sum = 0, i, u;
    for (u = 0; u < 4; u++)//4个方向,判断每个方向是否成活4
    {
        int sumk = 1;
        for (i = 1; same_u_i; i++)sumk++;
        if (OutOrNotEmpty)continue;
        for (i = -1; same_u_i; i--)sumk++;
        if (OutOrNotEmpty)continue;
        if (sumk == 4)sum++;
    }
    return sum;
}

int cheng5(int row, int col)//成5点的数量
{
    int sum = 0, i, u;
    for (u = 0; u < 8; u++)//8个成五点的方向
    {
        int  sumk = 0;
        int flag = 1;
        for (i = 1; same_u_i || flag; i++)
        {
            if (!same_u_i)//该方向的第一个不同色的点,超出边界或者对方棋子或空格
            {
                if (p[row + dx[u] * i][col + dy[u] * i])sumk -= 10;//该方向的第一个不同色的点是对方棋子,没有成五点
                flag = 0;
            }
            sumk++;
        }
        if (!inboard(row + dx[u] * --i, col + dy[u] * i))continue;//该方向的第一个不同色的点是超出边界,没有成五点
        for (i = -1; same_u_i; i--)sumk++;
        if (sumk == 4)sum++;
    }
    return sum;
}

int chong4(int row, int col)//冲4的数量
{
    return cheng5(row, col) - live4(row, col) * 2;
}

int live3(int row, int col)//活3的数量
{
    int key = p[row][col], sum = 0, i, u, flag = 2;
    for (u = 0; u < 4; u++)//三连的活三
    {
        int sumk = 1;
        for (i = 1; same_u_i; i++)sumk++;
        if (OutOrNotEmpty)continue;
        i++;
        if (OutOrNotEmpty)flag--;
        for (i = -1; same_u_i; i--)sumk++;
        if (OutOrNotEmpty)continue;
        i--;
        if (OutOrNotEmpty)flag--;
        if (sumk == 3 && flag > 0)sum++;
    }
    for (u = 0; u < 8; u++)//8个方向,每个方向最多1个非三连的活三
    {
        int  sumk = 0;
        int flag = 1;
        for (i = 1; same_u_i || flag; i++)//成活四点的方向
        {
            if (!same_u_i)
            {
                if (p[row + dx[u] * i][col + dy[u] * i])sumk -= 10;
                flag = 0;
            }
            sumk++;
        }
        if (OutOrNotEmpty)continue;
        if (p[row + dx[u] * --i][col + dy[u] * i] == 0)continue;
        for (i = -1; same_u_i; i--)sumk++;
        if (OutOrNotEmpty)continue;
        if (sumk == 3)sum++;
    }
    return sum;
}

int overline(int row, int col)//长连禁手
{
    for (int u = 0; u < 4; u++) {
        if (num(row, col, u) + num(row, col, u + 4) > 4)return 1;
    }
    return 0;
}

int ban(int row, int col)//判断落子后是否成禁手
{
    if (same(row, col, 2))return 0;//白方无禁手
    return live3(row, col) > 1 || overline(row, col) || live4(row, col) + chong4(row, col) > 1;
}

int end_(int row, int col)//(row,col)处落子之后是否游戏结束
{
    for (int u = 0; u < 4; u++) {
        if (num(row, col, u) + num(row, col, u + 4) >= 4)return is_end = 1;
    }
    return is_end = ban(row, col);
}

void go(int row, int col)//落下一子
{
    if (s == s0)p[row][col] = -1; //标出最新下的棋
    else p[row][col] = -2;
    for (int i = 0; i <= N; i++)for (int j = 0; j <= N; j++) //取消上一个最新棋的标识
    {
        if (i == row && j == col)continue;
        if (p[i][j] < 0)p[i][j] *= -1;
    }
    DrawBoard();
    if (ban(row, col))
    {
        printf("禁手\n");
        if (s0 == 1)printf("玩家胜");
        else printf("AI胜");
        Sleep(10000);
    }
    if (end_(row, col))
    {
        if(k == 0)
        {
            if (s == ais)printf("AI胜");
            else printf("玩家胜");
        }
        else if(k == 1)
        {
            if (x == 1)printf("玩家二胜");
            else printf("玩家一胜");
        }
        Sleep(1000);
    }
    manu[0][manukey] = row, manu[1][manukey++] = col;
}

int ok(int row, int col)//能否落子
{
    return inboard(row, col) && (p[row][col] == 0);
}

int point(int row, int col)//非负分值
{
    if (ban(row, col))return 0;//禁手0分
    if (end_(row, col))
    {
        is_end = 0;
        return 10000;
    }
    int ret = live4(row, col) * 1000 + (chong4(row, col) + live3(row, col)) * 100, u;
    for (u = 0; u < 8; u++) {
        if (p[row + dx[u]][col + dy[u]])ret++;//无效点0分
    }
    return ret;
}

int AI3(int p2)
{
    int keyp = -100000, tempp;
    for (int i = 1; i <= N; i++)for (int j = 1; j <= N; j++)
    {
        if (!ok(i, j))continue;
        p[i][j] = s0;
        tempp = point(i, j);
        if (tempp == 0)
        {
            p[i][j] = 0;
            continue;
        }
        if (tempp == 10000)
        {
            p[i][j] = 0;
            return 10000;
        }
        p[i][j] = 0;
        if (tempp - p2 * 2 > keyp)keyp = tempp - p2 * 2;//第三层取极大
    }
    return keyp;
}

int AI2()
{
    int keyp = 100000, tempp;
    for (int i = 1; i <= N; i++)for (int j = 1; j <= N; j++)
    {
        if (!ok(i, j))continue;
        p[i][j] = 3 - s0;
        tempp = point(i, j);
        if (tempp == 0)
        {
            p[i][j] = 0;
            continue;
        }
        if (tempp == 10000)
        {
            p[i][j] = 0;
            return -10000;
        }
        tempp = AI3(tempp);
        p[i][j] = 0;
        if (tempp < keyp)keyp = tempp;//第二层取极小
    }
    return keyp;
}

void AI()
{
    DrawBoard();
    printf("  轮到AI下,请稍候: ");
    if (p[8][8] == 0)return go(8, 8);
    int i, j;
    int keyp = -100000, tempp;
    for (i = 1; i <= N; i++)
    {
        for (j = 1; j <= N; j++)
        {
            if (!ok(i, j))continue;
            p[i][j] = s0;
            tempp = point(i, j);
            if (tempp == 0)
            {
                p[i][j] = 0;
                continue;
            }//高效剪枝,避开了禁手点和无效点
            if (tempp == 10000)return go(i, j);
            tempp = AI2();
            p[i][j] = 0;
            if (tempp > keyp)keyp = tempp, keyi = i, keyj = j;//第一层取极大
        }
    }
    return go(keyi, keyj);
}

void out_manual()
{
    char alpha = 'A';
    int i;
    if(k == 0)
    {
        printf("\n  黑方落子位置: ");
        for (i = 0; i < manukey; i += 2)printf("  %c%d", alpha + manu[1][i] - 1, manu[0][i]);
        printf("\n  白方落子位置: ");
        for (i = 1; i < manukey; i += 2)printf("  %c%d", alpha + manu[1][i] - 1, manu[0][i]);
    }
    else if(k == 1)
    {
        printf("\n  玩家一落子位置: ");
        for (i = 0; i < manukey; i += 2)printf("  %c%d", alpha + manu[1][i] - 1, manu[0][i]);
        printf("\n  玩家二落子位置: ");
        for (i = 1; i < manukey; i += 2)printf("  %c%d", alpha + manu[1][i] - 1, manu[0][i]);
    }
    Sleep(5000);
}

void player1()
{
    DrawBoard();
    if(k == 0)
    {
        printf("  轮到玩家下棋,请输入坐标[例如H8](输入=0查看棋谱): ");
        if(live3(keyi, keyj) > 0)
            printf("AI已成活3,请注意!\n");
        if(chong4(keyi, keyj) > 0)
            printf("AI已成冲4,请注意!\n");
    }
    else if(k == 1 )
    {
        if(x == 1)
        {
            printf("  轮到玩家一下棋,请输入坐标[例如H8](输入=0查看棋谱): ");
            x = 3-x;
        }
        else if(x == 2)
        {
            printf("  轮到玩家二下棋,请输入坐标[例如H8](输入=0查看棋谱): ");
            x = 3-x;
        }
    }
    char c = '\n';
    int row = 0, col = 0;
    while (c < '0')scanf("%c%d", &c, &row);
    if (c == '=')
    {
        out_manual();
        return player1();
    }
    if (c < 'a')col = c - 'A' + 1;
    else col = c - 'a' + 1;
    if (!ok(row, col))
    {
        printf("此处不能下");
        x = 3-x;
        Sleep(1000);
        return player1();
    }
    if(live3(row, col) > 0)
        printf("对手已成活3,请注意!\n");
    if(chong4(row, col) > 0)
        printf("对手已成冲4,请注意!\n");
    go(row, col);
}

void fupan(int i)//清空棋盘
{
    if(a2 == 1)
    {
        int  m,n;
        char c = '\n',alpha = 'A';
        c = alpha + manu[1][i] - 1;
        if (c < 'a')a1 = c - 'A' + 1;
        else a1 = c - 'a' + 1;
        b1 = manu[0][i];
        pa[1][l] = a1;
        pa[0][l] = b1;
        l++;
        if (i%2 == 0)p[b1][a1] = 1; //标出最新下的棋
        else p[b1][a1] = 2;
    }
    else if(a2 == 2)
    {
        p[pa[0][l-1]][pa[1][l-1]] = 0;
        l--;
    }
    DrawBoard();
}

void bzd()
{
    int o,i=0;
    printf("\n   是否复盘(是:1,否:2):");
    scanf("%d",&o);
    if(o==1)
    {
        for(i = 0;i < manukey+1;i++)
        {
            printf("是否进行下一步\n输入1或2进行选择\n1:进行下一步\n2:返回上一步\n\n输入:");
            scanf("%d",&a2);
            if(a2 == 1)
            {
                fupan(i);
            }
            else if(a2 == 2)
            {
                fupan(i);
                i--;
                i--;
            }
            else
            {
                printf("输入错误,请重新输入\n");
                i--;
            }
        }
    }
}

void main()
{
    int o,i=0,a2;
    int m,n;
    char alpha = 'A';
    init();
    while (!is_end)
    {
        if(k == 0)
        {
            if (s == ais)AI();
            else player1();
        }
        else if(k == 1)
        {
            player1();
        }
        s = 3 - s;//换下棋方
    }
    if(is_end == 1)
    {
        for (m = 0; m <= N + 1; m++)for (n = 0; n <= N + 1; n++)p[m][n] = 0;//以空格包围棋盘
        bzd();
    }
    Sleep(10000);
    return;
}
 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一个很好的五子棋c语言源程序代码,最重要的是能运行正确!!! #include #include #include #include #include #define CROSSRU 0xbf /*右上角点*/ #define CROSSLU 0xda /*左上角点*/ #define CROSSLD 0xc0 /*左下角点*/ #define CROSSRD 0xd9 /*右下角点*/ #define CROSSL 0xc3 /*左边*/ #define CROSSR 0xb4 /*右边*/ #define CROSSU 0xc2 /*上边*/ #define CROSSD 0xc1 /*下边*/ #define CROSS 0xc5 /*十字交叉点*/ /*定义棋盘左上角点在屏幕上的位置*/ #define MAPXOFT 5 #define MAPYOFT 2 /*定义1号玩家的操作键键码*/ #define PLAY1UP 0x1157/*上移--'W'*/ #define PLAY1DOWN 0x1f53/*下移--'S'*/ #define PLAY1LEFT 0x1e41/*左移--'A'*/ #define PLAY1RIGHT 0x2044/*右移--'D'*/ #define PLAY1DO 0x3920/*落子--空格键*/ /*定义2号玩家的操作键键码*/ #define PLAY2UP 0x4800/*上移--方向键up*/ #define PLAY2DOWN 0x5000/*下移--方向键down*/ #define PLAY2LEFT 0x4b00/*左移--方向键left*/ #define PLAY2RIGHT 0x4d00/*右移--方向键right*/ #define PLAY2DO 0x1c0d/*落子--回车键Enter*/ /*若想在游戏中途退出, 可按 Esc 键*/ #define ESCAPE 0x011b /*定义棋盘上交叉点的状态, 即该点有无棋子 */ /*若有棋子, 还应能指出是哪个玩家的棋子 */ #define CHESSNULL 0 /*没有棋子*/ #define CHESS1 'O'/*一号玩家的棋子*/ #define CHESS2 'X'/*二号玩家的棋子*/ /*定义按键类别*/ #define KEYEXIT 0/*退出键*/ #define KEYFALLCHESS 1/*落子键*/ #define KEYMOVECURSOR 2/*光标移动键*/ #define KEYINVALID 3/*无效键*/ 下载可看到完整的...
使用EGE图形库来实现五子棋人机人人对战可以让游戏更加直观和交互性。下面是一个使用C语言和EGE库编写的示例代码实现五子棋人机人人对战功能。 ```c #include <stdio.h> #include <graphics.h> #define ROWS 15 #define COLS 15 #define SIZE 40 #define MARGIN 20 int chessboard[ROWS][COLS]; int currentPlayer = 1; // 当前玩家,1表示黑棋,2表示白棋 int gameMode = 0; // 游戏模式,0表示人机对战,1表示人人对战 int gameOver = 0; // 游戏是否结束 void drawChessboard() { setfillcolor(RGB(255, 206, 158)); // 设置棋盘背景颜色 solidrectangle(MARGIN, MARGIN, MARGIN + COLS * SIZE, MARGIN + ROWS * SIZE); setlinecolor(BLACK); // 设置棋盘线条颜色 // 绘制棋盘线条 for (int i = 0; i <= ROWS; i++) { line(MARGIN, MARGIN + i * SIZE, MARGIN + COLS * SIZE, MARGIN + i * SIZE); } for (int j = 0; j <= COLS; j++) { line(MARGIN + j * SIZE, MARGIN, MARGIN + j * SIZE, MARGIN + ROWS * SIZE); } // 绘制棋子 for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (chessboard[i][j] == 1) { setfillcolor(BLACK); solidcircle(MARGIN + j * SIZE, MARGIN + i * SIZE, SIZE / 2 - 2); } else if (chessboard[i][j] == 2) { setfillcolor(WHITE); solidcircle(MARGIN + j * SIZE, MARGIN + i * SIZE, SIZE / 2 - 2); } } } } void initChessboard() { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { chessboard[i][j] = 0; } } } void placePiece(int row, int col) { chessboard[row][col] = currentPlayer; } int checkWin(int row, int col) { int directions[4][2] = { {1, 0}, {0, 1}, {1, 1}, {-1, 1} }; for (int i = 0; i < 4; i++) { int count = 1; int dx = directions[i][0]; int dy = directions[i][1]; // 向正反两个方向搜索 for (int j = 1; j < 5; j++) { int newRow = row + j * dx; int newCol = col + j * dy; if (newRow >= 0 && newRow < ROWS && newCol >= 0 && newCol < COLS && chessboard[newRow][newCol] == currentPlayer) { count++; } else { break; } } for (int j = 1; j < 5; j++) { int newRow = row - j * dx; int newCol = col - j * dy; if (newRow >= 0 && newRow < ROWS && newCol >= 0 && newCol < COLS && chessboard[newRow][newCol] == currentPlayer) { count++; } else { break; } } if (count >= 5) { return currentPlayer; } } return 0; } void aiMove() { // 随机选择一个空位落子 while (1) { int row = rand() % ROWS; int col = rand() % COLS; if (chessboard[row][col] == 0) { placePiece(row, col); break; } } } void gameLoop() { initgraph(COLS * SIZE + 2 * MARGIN, ROWS * SIZE + 2 * MARGIN); while (!gameOver) { drawChessboard(); if (gameMode == 0 && currentPlayer == 2) { aiMove(); } else { MOUSEMSG m; m = GetMouseMsg(); if (m.uMsg == WM_LBUTTONDOWN) { int x = m.x - MARGIN; int y = m.y - MARGIN; if (x >= 0 && x < COLS * SIZE && y >= 0 && y < ROWS * SIZE) { int row = y / SIZE; int col = x / SIZE; if (chessboard[row][col] == 0) { placePiece(row, col); int winner = checkWin(row, col); if (winner > 0) { gameOver = 1; char msg[20]; sprintf(msg, "Player %d wins!", winner); MessageBox(GetHWnd(), msg, "Game Over", MB_OK); } else { currentPlayer = (currentPlayer == 1) ? 2 : 1; } } } } } } closegraph(); } int main() { gameLoop(); return 0; } ``` 这段代码使用了EGE图形库来绘制棋盘和棋子,并且支持人机对战和人人对战两种游戏模式。在人机对战模式下,计算机会随机选择一个空位落子;在人人对战模式下,玩家轮流下棋。当有玩家获胜时,会弹出提示框显示胜利信息。 你需要在Windows环境下安装EGE库,并使用支持EGE库的C语言编译器来编译和运行这段代码。如果你想更深入了解EGE库的使用,可以查阅相关文档和教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值