栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言五子棋代码

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言五子棋代码

五子棋
  • 效果
  • 实现功能
  • 流程图
  • 开发工具
  • 函数说明
    • 链表操作函数
    • 功能函数
    • 控制函数
  • 源代码

效果

话不多说,先看成果图:

实现功能
  • 游戏界面加载
  • 棋子自定义
  • 鼠标操控落子位置
  • 悔棋
  • 复盘
  • 棋子追踪(标记最新落下的棋子)
流程图

主体功能的流程图如下:

开发工具

Visual Studio 2019、EasyX.
Visual Studio 2019的安装方法在此获取,EasyX图形库在官网获取。
也可以在 Q群 :178668046 - 群文件 - 开发工具 获取。
注:这里Visual Studio 2019并不是必需的,使用适配EasyX图形库的任一编译器即可。

函数说明 链表操作函数

为了实现对弈时的悔棋、复盘操作,本文建立了一个双向链表,来存储对局信息。由于悔棋操作需要每次取走棋盘上最新落下的棋子,所以利用栈来存储对局信息最为合适。而复盘操作需要按照棋手落子顺序,将对局过程再次展现出来,利用队列来存储对局信息最为合适,所以我将悔棋操作用到的栈升级为一个双向链表(为了方便描述与理解,以下依旧称此双向链表为栈)。
棋手落子时将落子位置push进栈,悔棋时pop出栈;复盘时将栈底元素看作队头元素,栈顶元素看作队尾元素,从队头元素开始依此出队。这样可以同时实现栈和队列的功能,同时满足悔棋和复盘的需求。

函数名函数作用
push()元素入栈
pop()元素出栈
lClear()清空栈
fuPan()进行复盘
功能函数
函数名函数作用
m_withdraw()悔棋
m_emphasize()标记最新落下的棋子
m_remove(int x, int y)为棋子取消标记
panDuan()判断对局是否结束
控制函数
函数名函数作用
init_system()系统初始化
init_game()对局界面初始化
init_qipan()棋盘数组初始化
m_startgame()对局控制函数
showWhoWin()展示哪一方获胜
m_replay()再来一局
close_system()关闭系统
源代码
  • 代码需要保存为.cpp格式才可以正常运行。
  • 代码运行需要棋子图片,可以进 群:178668046 直接获取,或者自己设置喜欢的棋子图片也可。设置方法:1. 在代码的同级目录新建名为 image 的文件夹,并将自己准备的图片放到 image文件夹中;2. 在函数init_system()中,将要导入图片的名称及格式替换为自己准备的图片的名称及格式。
#include 
#include 
#include 
#include 
#include 

#define N 15
#define LIGHTBROWN RGB(255,211,155)    // 棋盘颜色

int m_bine = 34, m_wh = 40;            // 定义棋子大小、每格像素数
int m_x0 = 100, m_y0 = 40;             // 初始棋子位置
int m_x9 = 660, m_y9 = 600;            // 最终棋子位置
int a = 740, b = 350, c = 810, d = 390;// 悔棋按钮的位置
int flag;

struct Point {
    int a, b;
    struct Point* prior;
    struct Point* next;
};

int qipan[N][N];
int ffupan[N][N];
int x, y, x0, y0;                  // (x0,y0)是棋盘上的坐标,(x,y)是数组下标 

struct Point* top, * base;         // 全局变量 分别指向栈顶和栈底 

IMAGE dog, cat, dog1, cat1;
HWND hwnd;

void push();                       // 进栈 //实际是一个队列加栈,双向链表 ,不是栈 
void pop();                        // 出栈 
void lClear();                    // 清空
void fuPan();                      // 复盘,由栈底向栈顶搜索

int panDuan();                     // 判断是否有连成五子
int showWhoWin();                  // 输出谁赢了

void init_system();                // 初始化系统
void init_game();                  // 初始化游戏界面
void init_qipan();                 // 棋盘数组初始化
void m_replay();                   // 重玩
void m_startgame();                // 游戏开始
void m_withdraw();                 // 悔棋
void m_emphasize();                // 标记(强调)最新落子
void m_remove(int x, int y);       // 取消标记
void close_system();               // 关闭系统


void push()
{
    struct Point* p;
    p = (struct Point*)malloc(sizeof(struct Point));
    if (!p) exit(0);
    p->a = x;
    p->b = y;
    p->prior = NULL;
    p->next = top;
    if (top == NULL)
        base = p;
    else top->prior = p;
    top = p;
}
void pop()
{
    struct Point* p;
    p = top;

    qipan[top->a][top->b] = 0;
    top = top->next;
    if (top == NULL)
    {
        base = NULL;
        x = 0, y = 0;
    }
    else
    {
        top->prior = NULL;
        x = top->a; y = top->b;
        x0 = x + 1; y0 = y + 1;
    }
    free(p);
}
void lClear()
{
    struct Point* p;
    p = top;
    while (top != NULL)
    {
        p = top;
        top = top->next;
        free(p);
    }
    base = NULL;
}

void fuPan()
{
    struct Point* p, * q;
    p = base;
    int i, j;
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            ffupan[i][j] = qipan[i][j];
    init_qipan();
    init_game();

    fillrectangle(a, b - 100, c + 100, d - 100);
    // setcolor(BLACK);
    setbkmode(TRANSPARENT);
    settextstyle(30, 0, L"楷体");
    outtextxy(a + 5, b - 95, L"按空格继续");
    setcolor(WHITE);

    int color = 1;

    while (p != NULL)
    {
        qipan[p->a][p->b] = ffupan[p->a][p->b];
        system("cls");

        x = p->a;
        y = p->b;
        int xx = m_x0 + x * m_wh;
        int yy = m_y0 + y * m_wh;
        if (color == 1)
        {
            putimage(xx - m_bine / 2, yy - m_bine / 2, &dog);
            color = 2;
        }
        else
        {
            putimage(xx - m_bine / 2, yy - m_bine / 2, &cat);
            color = 1;
        }
        m_emphasize();

        system("pause");
        m_remove(x, y);
        
        p=p->prior;
    }
}


int main()
{
    init_system();

    m_startgame();

    close_system();
}

void init_system()  // 初始化系统
{
    init_game();
    init_qipan();
    loadimage(&dog, L"image/dog0.jpg", m_bine, m_bine);
    loadimage(&cat, L"image/cat0.jpg", m_bine, m_bine);
    loadimage(&dog1, L"image/dog1.jpg", 64, 64);
    loadimage(&cat1, L"image/cat1.jpg", 64, 64);
}

void init_game()    // 初始化游戏界面
{
    int i;
    initgraph(960, 640);
    hwnd = GetHWnd();
    SetWindowText(hwnd, L"五子棋");

    setlinecolor(LIGHTBROWN);
    setfillcolor(LIGHTBROWN);
    fillrectangle(m_x0 - m_wh, m_y0 - m_wh, m_x9 + m_wh, m_y9 + m_wh);

    fillrectangle(a, b, c, d);
    setcolor(BLACK);
    setbkmode(TRANSPARENT);
    settextstyle(30, 0, L"楷体");
    outtextxy(a + 5, b + 5, L"悔棋");
    setcolor(WHITE);

    setlinecolor(BLACK);
    setfillcolor(BLACK);
    for (i = 0; i < N; i++)
        line(m_x0, m_y0 + i * m_wh, m_x9, m_y0 + i * m_wh);

    for (i = 0; i < N; i++)
        line(m_x0 + i * m_wh, m_y0, m_x0 + i * m_wh, m_y9);

    fillcircle(m_x0 + 7 * m_wh, m_y0 + 7 * m_wh, 3);
    fillcircle(m_x0 + 3 * m_wh, m_y0 + 3 * m_wh, 3);
    fillcircle(m_x0 + 3 * m_wh, m_y0 + 11 * m_wh, 3);
    fillcircle(m_x0 + 11 * m_wh, m_y0 + 3 * m_wh, 3);
    fillcircle(m_x0 + 11 * m_wh, m_y0 + 11 * m_wh, 3);
    setcolor(WHITE);
    // setlinecolor(WHITE);
    // setfillcolor(BLACK);
}

void init_qipan()
{
    int i, j;
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            qipan[i][j] = 0;
}

void close_system()  // 关闭系统
{
    settextstyle(20, 0, L"楷体");
    outtextxy(810, 600, L"按任意键结束。。");
    system("pause");
    closegraph();
}

void m_replay()// 重新游戏
{
    lClear();
    memset(qipan, 0, sizeof(qipan));// 初始化数组
    // color = 1;
    init_game();
}

void m_emphasize()
{
    int a1, b1;
    a1 = m_x0 + x * m_wh;
    b1 = m_y0 + y * m_wh;
    setlinecolor(RED);
    line(a1 - m_wh / 2, b1 - m_wh / 2, a1 - m_wh / 2 + 5, b1 - m_wh / 2);
    line(a1 - m_wh / 2, b1 - m_wh / 2, a1 - m_wh / 2, b1 - m_wh / 2 + 5);
    line(a1 + m_wh / 2 - 5, b1 - m_wh / 2, a1 + m_wh / 2, b1 - m_wh / 2);
    line(a1 + m_wh / 2, b1 - m_wh / 2, a1 + m_wh / 2, b1 - m_wh / 2 + 5);
    line(a1 - m_wh / 2, b1 + m_wh / 2, a1 - m_wh / 2 + 5, b1 + m_wh / 2);
    line(a1 - m_wh / 2, b1 + m_wh / 2 - 5, a1 - m_wh / 2, b1 + m_wh / 2);
    line(a1 + m_wh / 2 - 5, b1 + m_wh / 2, a1 + m_wh / 2, b1 + m_wh / 2);
    line(a1 + m_wh / 2, b1 + m_wh / 2 - 5, a1 + m_wh / 2, b1 + m_wh / 2);
    setcolor(WHITE);
}
void m_remove(int x, int y)
{
    int a1, b1;
    a1 = m_x0 + x * m_wh;
    b1 = m_y0 + y * m_wh;
    setlinecolor(LIGHTBROWN);
    line(a1 - m_wh / 2, b1 - m_wh / 2, a1 - m_wh / 2 + 5, b1 - m_wh / 2);
    line(a1 - m_wh / 2, b1 - m_wh / 2, a1 - m_wh / 2, b1 - m_wh / 2 + 5);
    line(a1 + m_wh / 2 - 5, b1 - m_wh / 2, a1 + m_wh / 2, b1 - m_wh / 2);
    line(a1 + m_wh / 2, b1 - m_wh / 2, a1 + m_wh / 2, b1 - m_wh / 2 + 5);
    line(a1 - m_wh / 2, b1 + m_wh / 2, a1 - m_wh / 2 + 5, b1 + m_wh / 2);
    line(a1 - m_wh / 2, b1 + m_wh / 2 - 5, a1 - m_wh / 2, b1 + m_wh / 2);
    line(a1 + m_wh / 2 - 5, b1 + m_wh / 2, a1 + m_wh / 2, b1 + m_wh / 2);
    line(a1 + m_wh / 2, b1 + m_wh / 2 - 5, a1 + m_wh / 2, b1 + m_wh / 2);
    setcolor(WHITE);
}

int panDuan()
{
    int who, count = 1;
    int i = 1, j = 1;

    who = qipan[x][y];
    if (who == 0) return 0;// 针对上来就悔棋的情况 

    // 水平的左边
    while (who == qipan[x][y - i] && y - i >= 0)
    {
        i++;
        count++;
        if (count == 5) return who;
    }
    // 水平的右边
    i = 1;
    while (who == qipan[x][y + i] && y + i < N)
    {
        i++;
        count++;
        if (count == 5) return who;
    }

    // 垂直上方
    i = 1;
    count = 1;
    while (who == qipan[x - i][y] && x - i >= 0)
    {
        i++;
        count++;
        if (count == 5) return who;
    }
    // 垂直下方
    i = 1;
    while (who == qipan[x + i][y] && x + i < N)
    {
        i++;
        count++;
        if (count == 5) return who;
    }

    // 解决左上的斜线  上方
    i = 1;
    j = 1;
    count = 1;
    while (who == qipan[x - i][y - j] && x - i >= 0 && y - j >= 0)
    {
        i++;
        j++;
        count++;
        if (count == 5) return who;
    }
    // 解决左上的斜线  下方
    i = 1;
    j = 1;
    while (who == qipan[x + i][y + j] && x + i < N && y + j < N)
    {
        i++;
        j++;
        count++;
        if (count == 5) return who;
    }

    // 解决右上的斜线  上方
    i = 1;
    j = 1;
    count = 1;
    while (who == qipan[x - i][y + j] && x - i >= 0 && y + j < N)
    {
        i++;
        j++;
        count++;
        if (count == 5) return who;
    }
    // 解决右上的斜线  下方
    i = 1;
    j = 1;
    while (who == qipan[x + i][y - j] && x + i < N && y - j >= 0)
    {
        i++;
        j++;
        count++;
        if (count == 5) return who;
    }

    return 0;// 无人胜利 
}

int showWhoWin()
{
    int whowin;  // 谁赢了 1-dog 2-cat 0-NULL 
    whowin = panDuan();
    if (whowin == 0) return 0;
    else
    {
        int id;
        if (whowin == 1) {
            id = MessageBox(hwnd, TEXT("恭喜汪汪队立大功!n是否复盘?"), TEXT("游戏结束"), MB_YESNO);
        }
        else
            id = MessageBox(hwnd, TEXT("恭喜喵喵队立大功!n是否复盘?"), TEXT("游戏结束"), MB_YESNO);
        if (id == IDYES)
            return 1;
        else return 2;
    }
}

void m_startgame()
{
    MOUSEMSG m_mouse;

    int color = 1;

    top = NULL;
    base = NULL;
    // init_game里面

    while (1)
    {
        if (color == 1)
            putimage(a, 200, &dog1);
        else
            putimage(a, 200, &cat1);
        m_mouse = GetMouseMsg();

        if (m_mouse.uMsg == WM_LBUTTONDOWN)
        {
            if (m_mouse.x > a && m_mouse.x < c && m_mouse.y > b && m_mouse.y < d) // 判断是否悔棋
            {
                if (top == NULL)
                    MessageBox(hwnd, TEXT("已无法继续悔棋!"), TEXT("提示"), MB_OK);

                else {
                    m_withdraw();
                    if (color == 1) color = 2;
                    else color = 1;
                }
            }


            else if (m_mouse.x > m_x0 - m_wh / 2 && m_mouse.x < m_x9 + m_wh / 2 &&
                m_mouse.y > m_y0 - m_wh / 2 && m_mouse.y < m_y9 + m_wh / 2)  // 判断是否在棋盘内
            {
                int x1, y1;  // 为m_remove()服务
                x1 = x; y1 = y;

                for (x = 0; x < N; x++)
                {
                    for (y = 0; y < N; y++)
                    {
                        if (m_mouse.x >= m_x0 - m_wh / 2 + x * m_wh &&
                            m_mouse.x <= m_x0 + m_wh / 2 + x * m_wh &&
                            m_mouse.y >= m_y0 - m_wh / 2 + y * m_wh &&
                            m_mouse.y <= m_y0 + m_wh / 2 + y * m_wh)      // 纠正棋子位置,使其落在两线交叉点
                        {
                            x0 = x + 1;
                            y0 = y + 1;
                            m_mouse.x = m_x0 + x * m_wh;
                            m_mouse.y = m_y0 + y * m_wh;
                            break;
                        }
                    }
                    //break;可优化 
                }
                x = x0 - 1;
                y = y0 - 1;
                if (qipan[x][y] != 0)  // 如果此处有棋子则不能下棋
                    continue;
                qipan[x][y] = color;
                push();

                if (color == 1)
                {
                    putimage(m_mouse.x - m_bine / 2, m_mouse.y - m_bine / 2, &dog);
                    color = 2;
                }
                else
                {
                    putimage(m_mouse.x - m_bine / 2, m_mouse.y - m_bine / 2, &cat);
                    color = 1;
                }

                m_remove(x1, y1);
                m_emphasize();
            }

            else continue;                      // 鼠标无效点击

            flag = showWhoWin();
            if (flag != 0)                      // 不为0即游戏结束
            {
                if (flag == 1)
                    fuPan();

                int id;
                id = MessageBox(hwnd, TEXT("是否重新开始游戏?"), TEXT("游戏结束"), MB_YESNO);

                if (id == IDYES)
                    m_replay();
                else break;
                color = 1;
            }
        }
    }

}

void m_withdraw()
{
    // 去除棋子的追踪特效
    m_remove(x, y);

    int a, b;
    a = m_x0 + x * m_wh;
    b = m_y0 + y * m_wh;

    setcolor(LIGHTBROWN);
    setfillcolor(LIGHTBROWN);
    fillcircle(a, b, m_wh / 2);
    //floodfill(a, b, LIGHTBROWN);

    // 为悔棋棋子的位置加上黑线
    setcolor(BLACK);
    setfillcolor(BLACK);
    if (x0 == 1 && y0 == 1)
    {
        line(m_x0, m_y0, m_x0 + m_wh / 2, m_y0);
        line(m_x0, m_y0, m_x0, m_y0 + m_wh / 2);
    }
    else if (x0 == 15 && y0 == 1)
    {
        line(m_x9 - m_wh / 2, m_y0, m_x9, m_y0);
        line(m_x9, m_y0, m_x9, m_y0 + m_wh / 2);
    }
    else if (x0 == 1 && y0 == 15)
    {
        line(m_x0, m_y9, m_x0 + m_wh / 2, m_y9);
        line(m_x0, m_y9 - m_wh / 2, m_x0, m_y9);
    }
    else if (x0 == 15 && y0 == 15)
    {
        line(m_x9, m_y9 - m_wh / 2, m_x9, m_y9);
        line(m_x9 - m_wh / 2, m_y9, m_x9, m_y9);
    }

    else if (x0 == 1)
    {
        line(a, b, a + m_wh / 2, b);
        line(a, b - m_wh / 2, a, b + m_wh / 2);
    }
    else if (x0 == 15)
    {
        line(a - m_wh / 2, b, a, b);
        line(a, b - m_wh / 2, a, b + m_wh / 2);
    }
    else if (y0 == 1)
    {
        line(a - m_wh / 2, b, a + m_wh / 2, b);
        line(a, b, a, b + m_wh / 2);
    }
    else if (y0 == 15)
    {
        line(a - m_wh / 2, b, a + m_wh / 2, b);
        line(a, b - m_wh / 2, a, b);
    }

    else
    {
        line(a - m_wh / 2, b, a + m_wh / 2, b);
        line(a, b - m_wh / 2, a, b + m_wh / 2);
        if (x0 == 4 && y0 == 4)
            fillcircle(a, b, 3);
        else if (x0 == 4 && y0 == 12)
            fillcircle(a, b, 3);
        else if (x0 == 12 && y0 == 4)
            fillcircle(a, b, 3);
        else if (x0 == 12 && y0 == 12)
            fillcircle(a, b, 3);
        else if (x0 == 8 && y0 == 8)
            fillcircle(a, b, 3);
    }

    pop();
    if (top != NULL)
        // 为最新棋子加上特效
        m_emphasize();
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/937888.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号