C语言实现五子棋小游戏:控制台绘图与AI随机落子

Cora
Cora
发布时间:2026-10-15 | 6人浏览过
原创

利用C语言和Windows控制台API开发五子棋游戏,涉及字符界面渲染、坐标映射、状态管理与基础胜负判定。本方案基于14x14网格,实现用户手动输入坐标与电脑随机落子的交替进行。

项目准备与环境依赖

要在终端(Console)中实现类似图形的效果,必须依赖于操作系统的特定API。本项目专为 Windows 环境设计,主要依赖以下头文件与库:

  • <stdio.h>:处理标准输入输出(如打印棋盘、接收用户指令)。
  • <windows.h>:GetStdHandle 和 SetConsoleCursorPosition 是实现“不刷新整个屏幕而移动光标”的关键。
  • <time.h>:用于初始化随机数种子(若需更智能的AI)。注:当前示例代码侧重于基础逻辑,未包含随机种子初始化,建议在实际编译前添加 srand(time(NULL))。

核心机制解析

第1步:控制台光标定位技术

控制台默认是流式打印,无法直接修改已输出的字符。为了实现“点击位置出现棋子”,我们需要通过 gotoxy 函数将光标移动到指定行列,然后重新打印字符覆盖。

入口/动作:

  1. 获取标准输出句柄:HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE)。
  2. 定义坐标结构体:COORD pos = {x, y},其中 x 为列,y 为行。
  3. 执行定位:SetConsoleCursorPosition(hOut, pos)。

第2步:棋盘网格构建

游戏盘面是一个 14x14 的矩阵。为了方便计算边界溢出,我们在宏定义时预留了空间或使用严格的边界检查。

#define ROW 14
#define COL 14
int arr[ROW][COL] = {0}; // 0:空, 1:黑棋(用户), 2:白棋(电脑)

绘制时使用 Unicode 字符(┌, ┬, ├, ┼, └, ┴)来美化边缘,中间用 “空格+符号+空格” 的模式保持对齐。

第3步:坐标转换与交互

用户习惯从 (1,1) 开始输入,而数组索引从 0 开始。同时,由于字符宽度通常为2个英文字符位,显示时需要调整X轴偏移量。

转换公式:

  • 实际数组行索引:row = input_x - 1
  • 实际数组列索引:col = input_y - 1
  • 光标横向位置:col * 2 (对应打印时的两个字符间距)

完整代码实现与编译指南

以下是经过整理、注释规范化的源代码。您可以将其保存为 gobang.c。

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

#define ROW 14
#define COL 14

// 光标定位函数
void gotoxy(int x, int y)
{
    HANDLE hOut;
    COORD pos = {x, y};
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOut, pos);
}

// 绘制静态棋盘
void paintGameUI()
{
    int i, j;
    printf("┌ ");
    for(i=0; i<COL; i++) printf("┬ ");
    printf("┐\n");

    for(j=0; j<ROW; j++)
    {
        printf("├ ");
        for(i=0; i<COL; i++) printf("┼ ");
        printf("┤\n");
    }

    printf("└ ");
    for(i=0; i<COL; i++) printf("┴ ");
    printf("┘\n");
}

// 判断输赢的核心辅助函数
int checkWin(int arr[][COL], int row, int col, int player)
{
    int i, j;
    // 横向判断
    for(i=0; i<ROW; i++) {
        for(j=0; j<=COL-5; j++) {
            if(arr[i][j]==player && arr[i][j+1]==player && 
               arr[i][j+2]==player && arr[i][j+3]==player && 
               arr[i][j+4]==player) return 1;
        }
    }
    // 纵向判断
    for(i=0; i<=ROW-5; i++) {
        for(j=0; j<COL; j++) {
            if(arr[i][j]==player && arr[i+1][j]==player && 
               arr[i+2][j]==player && arr[i+3][j]==player && 
               arr[i+4][j]==player) return 1;
        }
    }
    return 0;
}

void playgame()
{
    srand(time(NULL)); // 初始化随机数种子
    int arr[ROW][COL]={0}; 
    int userX, userY;   
    int compRow, compCol;
    
    // 清屏优化(可选,这里仅重绘一次棋盘框架)
    system("cls"); 
    paintGameUI();     
    
    while(1) 
    {
        // === 玩家回合 ===
        while(1)   
        {
            gotoxy(0, ROW + 2); // 在棋盘下方显示提示
            printf("                  "); // 清空旧提示
            gotoxy(0, ROW + 2); 
            printf("请输入下棋位置 (行 列): ");
            
            if(scanf("%d %d", &userX, &userY) != 2 || 
               userX < 1 || userX > ROW || userY < 1 || userY > COL) {
                printf("无效输入,请重试!\n");
                continue;
            }

            int r = userX - 1;
            int c = userY - 1;
            
            if(arr[r][c] == 0)   
            {   
                gotoxy(c*2, r); 
                printf("●"); // 用户黑棋
                arr[r][c] = 1;
                
                if(checkWin(arr, r, c, 1)) {
                    gotoxy(0, ROW + 4);
                    printf("恭喜!用户赢了!\n");
                    return;   
                }
                break;   
            } 
            else  
            {
                gotoxy(0, ROW + 3);
                printf("该位置已有棋子,请重新输入");
            }   
        }

        // === 电脑回合 ===
        // 简单AI:随机寻找空位
        while(1) 
        {
            compRow = rand() % ROW;
            compCol = rand() % COL;
            
            if(arr[compRow][compCol] == 0)   
            {   
                gotoxy(compCol*2, compRow);
                printf("○"); // 电脑白棋
                arr[compRow][compCol] = 2;
                
                if(checkWin(arr, compRow, compCol, 2)) {
                    gotoxy(0, ROW + 4);
                    printf("电脑赢了!\n");
                    return; 
                }
                break;   
            }   
        }   
    }   
}

int main()
{
    printf("欢迎体验C语言控制台五子棋\n");
    playgame();   
    return 0;
}

功能局限与改进方向

当前版本实现了基础的对战逻辑,但在以下几个方面存在明显的提升空间:

  1. 判定完整性:上述 checkWin 代码仅包含“横向”和“纵向”两种获胜情况。完整的五子棋还需要判定左上到右下以及右上到左下两条对角线方向的胜利条件。
  2. AI智力:目前的电脑策略是完全随机的 rand(),不具备防守或进攻意识。若要增强体验,可引入简单的评分算法,优先占据有相邻棋子的位置。
  3. 视觉刷新:频繁使用 printf 可能导致闪烁,可以使用 Windows API 的全屏缓冲技术(Virtual Screen Buffer)来实现平滑的重绘。

以上就是C语言控制台五子棋小游戏的详细内容,更多关于C语言游戏开发的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表