水墨五子棋(暂时未完成)

完成进度:

C++课程设计

老师布置了C++的课程设计,说是随便写点啥,同学们都写了各种基于黑框框(控制台)的什么学生成绩管理系统,感觉没什么创意,我想写一个图形界面的,本程序采用了EasyX图形库和一些Winodows API,然后用它来完成我的五子棋,具体实现过程就不说了,底下会放出源码的。在这里更一下进度吧。。

编译环境:

Visual Studio 2017(在编译选项里选择多字符集支持,默认是Unicode的字符集)

EasyX图形库

原来准备写三个功能:

1.双人对战(已完成)

2.单人AI(有BUG)

3.联机对战(没写)

背景音乐:

主界面:万代.传承

游戏界面:绿野仙踪

游戏截图

主界面:

《水墨五子棋(暂时未完成)》

鼠标移到对应选项会变色:

《水墨五子棋(暂时未完成)》

双人模式界面:

《水墨五子棋(暂时未完成)》

双人模式胜利界面:

《水墨五子棋(暂时未完成)》

AI模式胜利界面:

《水墨五子棋(暂时未完成)》


附上主要的代码,完整的代码去文末GitHub里面找:

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <time.h>
#include "chess.h"
#include "Pos.h"
#define mem(a,b) memset(a,b,sizeof(a))
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
using namespace std;
#define window_x 1013
#define window_y 800
#define inf 0x3f3f3f3f
#define chess_r 49
#define debug() puts("what the fuck!!!")
int MODE = 1;//模式,1代表双人,2代表单人,3代表联机
Pos map[20][20];//存储每一个棋子的坐标
int vis[20][20];//标记一个位置当前有没有落子
int color[20][20];//1代表黑棋,0代表白棋
IMAGE MAPIMAGE[30][30];//图片对象
IMAGE NowChessImage;//存储请谁落子的图
void monse()
{
    POINT point;
    char s[10];
    while (true)
    {
        GetCursorPos(&point);
        // 输出鼠标坐标
        sprintf(s, _T("%d    "), point.x);
        outtextxy(0, 0, s);

        sprintf(s, _T("%d    "), point.y);
        outtextxy(0, 20, s);

        // 适当延时
        Sleep(10);

    }
}
void chess::welcome()
{
    mciSendString("open welcome.mp3", NULL, 0, 0);
    mciSendString("play welcome.mp3 repeat", NULL, 0, 0);


    initgraph(1024, 632);//创建一个1024*632的画布
    loadimage(NULL, "welcome.jpg");//放置背景
     /*mciSendString("open welcome.mp3", NULL, 0, 0);
     mciSendString("play welcome.mp3", NULL, 0, 0);*/
     //monse();
    setbkmode(TRANSPARENT);//透明字体
    HWND hwnd = GetHWnd();//获取当前窗口句柄
    SetWindowText(hwnd, "蒟蒻的五子棋 --- By:贺鹏程");//设置窗口标题
    settextcolor(RGB(77, 77, 77));
    LOGFONT f;//字体类对象
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 70;
    strcpy_s(f.lfFaceName, "微软雅黑");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    RECT r1 = { 500, 300, 800, 400 };
    RECT r2 = { 500, 405, 800, 505 };
    RECT r3 = { 500, 510, 800, 610 };
    /*setlinecolor(BLACK);
    rectangle(500, 300, 800, 400);*/
    drawtext("【双人模式】", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
    drawtext("【单人A   I】", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
    drawtext("【联机对战】", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
                                                                    //--------------------------------------------------------------------------------------------
    bool flag = true;
    MOUSEMSG m;//定义一个鼠标对象
    while (flag)
    {
        //这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
        BeginBatchDraw();
        m = GetMouseMsg();//获取鼠标消息
        switch (m.uMsg)
        {
        case WM_LBUTTONDOWN://鼠标左键按下
            EndBatchDraw();
            if (m.x >= 500 && m.x <= 800 && m.y >= 300 && m.y <= 400)//判断在开始游戏的矩形区域内
            {

                flag = false;
                MODE = 1;
                closegraph();
            }
            else if (m.x >= 500 && m.x <= 800 && m.y >= 405 && m.y <= 505)//单人ai模式
            {

                flag = false;
                MODE = 2;
                closegraph();

            }
        case WM_MOUSEMOVE://监测鼠标移动
            EndBatchDraw();
            if (m.x >= 500 && m.x <= 800 && m.y >= 300 && m.y <= 400)//判断鼠标在开始游戏的矩形区域内
            {
                settextcolor(RGB(254, 67, 101));
                drawtext("【双人模式】", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            else if (m.x >= 500 && m.x <= 800 && m.y >= 405 && m.y <= 505)
            {
                settextcolor(RGB(254, 67, 101));
                drawtext("【单人A   I】", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            else if (m.x >= 500 && m.x <= 800 && m.y >= 510 && m.y <= 610)
            {
                settextcolor(RGB(254, 67, 101));
                drawtext("【联机对战】", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            else
            {
                settextcolor(RGB(77, 77, 77));
                drawtext("【双人模式】", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                drawtext("【单人A   I】", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                drawtext("【联机对战】", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            //break;
        }
    }

}
double chess::dis(int x1, int y1, int x2, int y2)//算出两点间的距离
{
    return sqrt((double)((x1 - x2)*(x1 - x2)) + (double)((y1 - y2)*(y1 - y2)));
}
bool chess::JudgeChess(int x, int y)
{
    //思路:以当前点为中心点,向四个方向展开搜索
    if (color[x][y] == 0)//判断白棋连珠
    {
        int num = 0;//记录棋子数量
  //横向x不变
        for (int i = y; i <= 15; i++)//向右
        {
            if (color[x][i] == 0)
            {
                num++;
            }
            else
                break;
        }
        for (int i = y - 1; i >= 0; i--)//向左
        {
            if (color[x][i] == 0)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;//横向连珠,返回结果
        num = 0;//归零
                //竖向y不变
        for (int i = x; i <= 15; i++)//向下
        {
            if (color[i][y] == 0)
            {
                num++;
            }
            else
                break;
        }
        for (int i = x - 1; i >= 0; i--)//向上
        {
            if (color[i][y] == 0)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;//竖向连珠,返回结果
        num = 0;//归零
                //由右下斜向左上'\'
        for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
        {
            if (color[i][j] == 0)
            {
                num++;
            }
            else
                break;
        }
        for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
        {
            if (color[i][j] == 0)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;// '\'连珠,返回结果
        num = 0;//归零
                //由左下斜向右上'/'
        for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
        {
            if (color[i][j] == 0)
            {
                num++;
            }
            else
                break;
        }
        for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
        {
            if (color[i][j] == 0)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;// '/'连珠,返回结果
        num = 0;//归零
        return false;//白棋不能连珠
    }
    else if (color[x][y] == 1)//黑棋连珠
    {
        int num = 0;//记录棋子数量
                    //横向x不变
        for (int i = y; i <= 15; i++)//向右
        {
            if (color[x][i] == 1)
            {
                num++;
            }
            else
                break;
        }
        for (int i = y - 1; i >= 0; i--)//向左
        {
            if (color[x][i] == 1)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;//横向连珠,返回结果
        num = 0;//归零
                //竖向y不变
        for (int i = x; i <= 15; i++)//向下
        {
            if (color[i][y] == 1)
            {
                num++;
            }
            else
                break;
        }
        for (int i = x - 1; i >= 0; i--)//向上
        {
            if (color[i][y] == 1)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;//竖向连珠,返回结果
        num = 0;//归零
                //由右下斜向左上'\'
        for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
        {
            if (color[i][j] == 1)
            {
                num++;
            }
            else
                break;
        }
        for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
        {
            if (color[i][j] == 1)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;// '\'连珠,返回结果
        num = 0;//归零
                //由左下斜向右上'/'
        for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
        {
            if (color[i][j] == 1)
            {
                num++;
            }
            else
                break;
        }
        for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
        {
            if (color[i][j] == 1)
            {
                num++;
            }
            else
                break;
        }
        if (num >= 5)
            return true;// '/'连珠,返回结果
        num = 0;//归零
        return false;//黑棋不能连珠
    }
}
void chess::PlayGame1()
{
    /*---------------------------------处理背景音乐------------------------------------------------*/
    mciSendString("close welcome.mp3", NULL, 0, 0);
    mciSendString("open palying.mp3", NULL, 0, 0);
    mciSendString("play palying.mp3 repeat", NULL, 0, 0);
    /*---------------------------------画棋盘------------------------------------------------*/
    initgraph(window_x, window_y);
    loadimage(NULL, "4.jpg");
    HWND hwnd = GetHWnd();//获取当前窗口句柄
    SetWindowText(hwnd, "蒟蒻的五子棋 --- By:贺鹏程");//设置窗口标题
    setlinestyle(PS_SOLID, 2);
    setlinecolor(BLACK);
    for (int x = 30; x <= 765; x += 49)
    {
        line(30, x, 765, x);
    }
    for (int y = 30; y <= 765; y += 49)
    {
        line(y, 30, y, 765);
    }
    /*---------------------------------存储棋盘坐标------------------------------------------------*/

    //存储坐标
    for (int i = 0; i <= 15; i++)
    {
        for (int j = 0; j <= 15; j++)
        {
            map[i][j].x = 30 + 49 * j;
        }
    }
    for (int i = 0; i <= 15; i++)
    {
        for (int j = 0; j <= 15; j++)
        {
            map[j][i].y = 30 + 49 * j;
        }
    }

    //画黑点
    setlinecolor(BLACK);
    setfillcolor(BLACK);
    fillrectangle(map[3][3].x - 3, map[3][3].y - 3, map[3][3].x + 3, map[3][3].y + 3);
    fillrectangle(map[3][11].x - 3, map[3][11].y - 3, map[3][11].x + 3, map[3][11].y + 3);
    fillrectangle(map[7][7].x - 3, map[7][7].y - 3, map[7][7].x + 3, map[7][7].y + 3);
    fillrectangle(map[11][3].x - 3, map[11][3].y - 3, map[11][3].x + 3, map[11][3].y + 3);
    fillrectangle(map[11][11].x - 3, map[11][11].y - 3, map[11][11].x + 3, map[11][11].y + 3);
    //存储每一个位置的圆的图片
    /*for (int i = 0; i <= 15; i++)
    {
    for (int j = 0; j <= 15; j++)
    {
    getimage(&MAPIMAGE[i][j],)
    }
    }*/

    /*---------------------------------游戏开始------------------------------------------------*/
    mem(vis, 0);//清零标记数组
    mem(color, -1);//把颜色全部设置无
    bool flag = true;
    int opp = 0;//偶数是黑棋,奇数是白棋
    MOUSEMSG m;//定义一个鼠标对象


               /*setlinestyle(PS_SOLID, 1);
               setlinecolor(BLACK);*/
    getimage(&NowChessImage, 780, 40, 1000, 100);//获取原来的图像并存储
                                                 //rectangle(780,40, 1000, 100);
    settextcolor(RGB(77, 77, 77));
    RECT r1 = { 780,40, 1000, 100 };
    LOGFONT f;//字体类对象
    setbkmode(TRANSPARENT);//透明字体
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 50;
    strcpy_s(f.lfFaceName, "微软雅黑");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    while (flag)
    {
        //这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
        BeginBatchDraw();
        m = GetMouseMsg();//获取鼠标消息
        switch (m.uMsg)
        {
        case WM_LBUTTONDOWN://鼠标左键按下
            EndBatchDraw();
            Pos temp;
            temp.x = inf, temp.y = inf;
            double R = 10000000.0;
            for (int i = 0; i <= 15; i++)
            {
                for (int j = 0; j <= 15; j++)
                {
                    if (dis(map[i][j].x, map[i][j].y, m.x, m.y)<R)
                    {
                        R = dis(map[i][j].x, map[i][j].y, m.x, m.y);
                        temp.x = i;
                        temp.y = j;
                    }
                }
            }
            setlinecolor(BLACK);
            if (!vis[temp.x][temp.y])//只有没有被标记过才可以走
            {
                vis[temp.x][temp.y] = 1;
                if (opp & 1)//是奇数就画白棋
                {

                    setfillcolor(WHITE);
                    fillcircle(map[temp.x][temp.y].x, map[temp.x][temp.y].y, chess_r / 3);
                    PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);//播放声音
                    putimage(780, 40, &NowChessImage);
                    drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

                    color[temp.x][temp.y] = 0;
                    if (JudgeChess(temp.x, temp.y) == true)//白棋可以连珠
                    {
                        flag = false;
                        GameOver1(0);
                    }

                }
                else//偶数就画黑棋
                {

                    setfillcolor(BLACK);
                    fillcircle(map[temp.x][temp.y].x, map[temp.x][temp.y].y, chess_r / 3);
                    PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);

                    putimage(780, 40, &NowChessImage);
                    drawtext("请白方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                    color[temp.x][temp.y] = 1;//标记颜色
                    if (JudgeChess(temp.x, temp.y) == true)//黑棋可以连珠
                    {
                        flag = false;
                        GameOver1(1);
                    }
                }
                opp++;//改变状态
            }
            //case WM_MOUSEMOVE://监测鼠标移动
            //  EndBatchDraw();
        }
    }
}
void chess::GameOver1(int n)
{
    settextcolor(RGB(254, 67, 101));
    LOGFONT f;//字体类对象
    setbkmode(TRANSPARENT);//透明字体
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 120;
    strcpy_s(f.lfFaceName, "黑体");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    RECT r1 = { 0, 0, 800, 800 };
    RECT r2 = { 790, 710, 980, 760 };
    RECT r3 = { 780,40, 1000, 100 };
    setlinecolor(BLACK);
    if (n == 0)
    {
        drawtext("白 棋 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行

    }
    else if (n == 1)
    {
        drawtext("黑 棋 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
    }
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 50;
    strcpy_s(f.lfFaceName, "微软雅黑");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    putimage(780, 40, &NowChessImage);
    drawtext("游戏结束", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);


    //设置矩形
    setlinestyle(PS_SOLID, 1);
    setlinecolor(BLACK);
    rectangle(790, 710, 980, 760);//画重新开始的矩形边框
    setbkmode(TRANSPARENT);//透明字体
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 50;
    strcpy_s(f.lfFaceName, "微软雅黑");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    settextcolor(RGB(77, 77, 77));
    drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    bool flag = true;
    MOUSEMSG m;//定义一个鼠标对象
    while (flag)
    {
        //这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
        BeginBatchDraw();
        m = GetMouseMsg();//获取鼠标消息
        switch (m.uMsg)
        {
        case WM_LBUTTONDOWN://鼠标左键按下
            EndBatchDraw();
            if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断在开始游戏的矩形区域内
            {
                flag = false;
                //***********************************************
                PlayGame1();//重新开始游戏
            }
            //break;
        case WM_MOUSEMOVE://监测鼠标移动
            EndBatchDraw();
            if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断鼠标在开始游戏的矩形区域内
            {
                settextcolor(RGB(254, 67, 101));
                drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            else
            {
                settextcolor(RGB(77, 77, 77));
                drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            //break;
        }
    }


}
void chess::PlayGame2()
{
    /*---------------------------------处理背景音乐------------------------------------------------*/
    mciSendString("close welcome.mp3", NULL, 0, 0);
    mciSendString("open palying.mp3", NULL, 0, 0);
    mciSendString("play palying.mp3 repeat", NULL, 0, 0);
    /*---------------------------------画棋盘------------------------------------------------*/
    initgraph(window_x, window_y);
    loadimage(NULL, "4.jpg");
    HWND hwnd = GetHWnd();//获取当前窗口句柄
    SetWindowText(hwnd, "蒟蒻的五子棋 --- By:贺鹏程");//设置窗口标题
    setlinestyle(PS_SOLID, 2);
    setlinecolor(BLACK);
    for (int x = 30; x <= 765; x += 49)
    {
        line(30, x, 765, x);
    }
    for (int y = 30; y <= 765; y += 49)
    {
        line(y, 30, y, 765);
    }
    /*---------------------------------存储棋盘坐标------------------------------------------------*/

    //存储坐标
    for (int i = 0; i <= 15; i++)
    {
        for (int j = 0; j <= 15; j++)
        {
            map[i][j].x = 30 + 49 * j;
        }
    }
    for (int i = 0; i <= 15; i++)
    {
        for (int j = 0; j <= 15; j++)
        {
            map[j][i].y = 30 + 49 * j;
        }
    }

    //画黑点
    setlinecolor(BLACK);
    setfillcolor(BLACK);
    fillrectangle(map[3][3].x - 3, map[3][3].y - 3, map[3][3].x + 3, map[3][3].y + 3);
    fillrectangle(map[3][11].x - 3, map[3][11].y - 3, map[3][11].x + 3, map[3][11].y + 3);
    fillrectangle(map[7][7].x - 3, map[7][7].y - 3, map[7][7].x + 3, map[7][7].y + 3);
    fillrectangle(map[11][3].x - 3, map[11][3].y - 3, map[11][3].x + 3, map[11][3].y + 3);
    fillrectangle(map[11][11].x - 3, map[11][11].y - 3, map[11][11].x + 3, map[11][11].y + 3);
    //存储每一个位置的圆的图片

    /*---------------------------------游戏开始------------------------------------------------*/
    mem(vis, 0);//清零标记数组
    mem(color, -1);//把颜色全部设置无
    bool flag = true;
    int opp = 0;//偶数是黑棋,奇数是白棋
    MOUSEMSG m;//定义一个鼠标对象

    getimage(&NowChessImage, 780, 40, 1000, 100);//获取原来的图像并存储

    settextcolor(RGB(77, 77, 77));
    RECT r1 = { 780,40, 1000, 100 };
    LOGFONT f;//字体类对象
    setbkmode(TRANSPARENT);//透明字体
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 50;
    strcpy_s(f.lfFaceName, "微软雅黑");
    settextstyle(&f);
    drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    while (flag)
    {
        //这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
        BeginBatchDraw();
        m = GetMouseMsg();//获取鼠标消息
        switch (m.uMsg)
        {
        case WM_LBUTTONDOWN://鼠标左键按下
            EndBatchDraw();
            Pos temp;
            temp.x = inf, temp.y = inf;
            double R = 10000000.0;
            for (int i = 0; i <= 15; i++)
            {
                for (int j = 0; j <= 15; j++)
                {
                    if (dis(map[i][j].x, map[i][j].y, m.x, m.y)<R)
                    {
                        R = dis(map[i][j].x, map[i][j].y, m.x, m.y);
                        temp.x = i;
                        temp.y = j;
                    }
                }
            }
            setlinecolor(BLACK);
            int black_go = 0;
            if (!vis[temp.x][temp.y])//只有没有被标记过才可以走
            {
                vis[temp.x][temp.y] = 1;
                black_go = 1;

                //////////////////////画黑棋//////////////////////////
                setfillcolor(BLACK);
                fillcircle(map[temp.x][temp.y].x, map[temp.x][temp.y].y, chess_r / 3);
                PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);

                putimage(780, 40, &NowChessImage);
                drawtext("请白方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                color[temp.x][temp.y] = 1;//标记颜色
                if (JudgeChess(temp.x, temp.y) == true)//黑棋可以连珠
                {
                    flag = false;
                    GameOver2(1);
                    break;
                }
            }
                ///////////////////////////////画白棋//////////////////////////////////
            Pos PointWhite = GetAddress();
            if (!vis[PointWhite.x][PointWhite.y] && black_go == 1)
            {
                vis[PointWhite.x][PointWhite.y] = 1;
                setfillcolor(WHITE);
                //MessageBox(NULL, to_string(PointWhite.y).c_str(), "Title(标题)", MB_OK);
                fillcircle(map[PointWhite.x][PointWhite.y].x, map[PointWhite.x][PointWhite.y].y, chess_r / 3);
                PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);//播放声音
                putimage(780, 40, &NowChessImage);
                drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                color[PointWhite.x][PointWhite.y] = 0;
                if (JudgeChess(PointWhite.x, PointWhite.y) == true)//白棋可以连珠
                {
                    flag = false;
                    GameOver2(0);
                    break;
                }
            }
        }
    }
}
void chess::GameOver2(int n)
{
    settextcolor(RGB(254, 67, 101));
    LOGFONT f;//字体类对象
    setbkmode(TRANSPARENT);//透明字体
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 120;
    strcpy_s(f.lfFaceName, "黑体");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    RECT r1 = { 0, 0, 800, 800 };
    RECT r2 = { 790, 710, 980, 760 };
    RECT r3 = { 780,40, 1000, 100 };
    setlinecolor(BLACK);
    if (n == 0)
    {
        drawtext("电 脑 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行

    }
    else if (n == 1)
    {
        drawtext("玩 家 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
    }
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 50;
    strcpy_s(f.lfFaceName, "微软雅黑");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    putimage(780, 40, &NowChessImage);
    drawtext("游戏结束", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);


    //设置矩形
    setlinestyle(PS_SOLID, 1);
    setlinecolor(BLACK);
    rectangle(790, 710, 980, 760);//画重新开始的矩形边框
    setbkmode(TRANSPARENT);//透明字体
    gettextstyle(&f);//获取当前字体设置
    f.lfHeight = 50;
    strcpy_s(f.lfFaceName, "微软雅黑");
    f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
    settextstyle(&f);
    settextcolor(RGB(77, 77, 77));
    drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    bool flag = true;
    MOUSEMSG m;//定义一个鼠标对象
    while (flag)
    {
        //这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
        BeginBatchDraw();
        m = GetMouseMsg();//获取鼠标消息
        switch (m.uMsg)
        {
        case WM_LBUTTONDOWN://鼠标左键按下
            EndBatchDraw();
            if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断在开始游戏的矩形区域内
            {
                flag = false;
                //***********************************************
                PlayGame2();//重新开始游戏

            }
            //break;
        case WM_MOUSEMOVE://监测鼠标移动
            EndBatchDraw();
            if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断鼠标在开始游戏的矩形区域内
            {
                settextcolor(RGB(254, 67, 101));
                drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            else
            {
                settextcolor(RGB(77, 77, 77));
                drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
            //break;
        }
    }
}
Pos chess::GetAddress()//传进来当前落子的坐标
{
    Pos now;
    int choose_score = 1;//判分,如果需要防守此值为0,要进攻为1
//白棋防守,判断黑棋最多能连成几个棋子,然后进行封堵
    int flag = 1;//判断是否跳出循环
    for (int x = 0; x <= 15 && flag; x++)
    {
        for (int y = 0; y <= 15 && flag; y++)
        {
            if (color[x][y] == 1 && flag)//如果当前棋子的颜色为黑色
            {
                int num = 0;//记录连续黑色棋子数量
                            //横向x不变
                for (int i = y; i <= 15; i++)//向右
                {
                    if (color[x][i] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                for (int i = y - 1; i >= 0; i--)//向左
                {
                    if (color[x][i] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                if (num >= 3)//如果横向已经连成三个
                {
                    choose_score = 0;
                    int flog = 1;//区分是否已找到
                    for (int i = y; i <= 15 && flog; i++)//向右
                    {
                        if (color[x][i] == -1)
                        {
                            flog = 0;
                            now.x = x;
                            now.y = i;
                        }
                    }
                    for (int i = y - 1; i >= 0 && flog; i--)//向左
                    {
                        if (color[x][i] == -1)
                        {
                            flog = 0;
                            now.x = x;
                            now.y = i;
                        }

                    }
                    flag = 0;
                    break;
                }
                num = 0;
                //竖向y不变
                for (int i = x; i <= 15; i++)//向下
                {
                    if (color[i][y] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                for (int i = x - 1; i >= 0; i--)//向上
                {
                    if (color[i][y] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                if (num >= 3)//如果竖向已经连成三个
                {
                    choose_score = 0;
                    int flog = 1;
                    for (int i = x; i <= 15 && flog; i++)//向下
                    {
                        if (color[i][y] == -1)
                        {
                            flog = 0;
                            now.x = i;
                            now.y = y;
                        }
                    }
                    for (int i = x - 1; i >= 0 && flog; i--)//向上
                    {
                        if (color[i][y] == 1)
                        {
                            flog = 0;
                            now.x = i;
                            now.y = y;
                        }
                    }
                    flag = 0;
                    break;
                }
                num = 0;
                //由右下斜向左上'\'
                for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
                {
                    if (color[i][j] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
                {
                    if (color[i][j] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                if (num >= 3)//如果'\'已经连成三个
                {
                    choose_score = 0;
                    int flog = 1;
                    for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i--, j--)//由当前点向左上
                    {
                        if (color[i][j] == -1)
                        {
                            flog = 0;
                            now.x = i;
                            now.y = j;
                        }
                    }
                    for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i++, j++)//由当前点向右下
                    {
                        if (color[i][j] == -1)
                        {
                            flog = 0;
                            now.x = i;
                            now.y = j;
                        }
                    }
                    flag = 0;
                    break;
                }
                num = 0;
                //由左下斜向右上'/'
                for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
                {
                    if (color[i][j] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
                {
                    if (color[i][j] == 1)
                    {
                        num++;
                    }
                    else
                        break;
                }
                if (num >= 3)//如果已经连成三个
                {
                    choose_score = 0;
                    int flog = 1;
                    for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i--, j++)//由当前点斜向右上
                    {
                        if (color[i][j] == -1)
                        {
                            flog = 0;
                            now.x = i;
                            now.y = j;
                        }
                    }
                    for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i++, j--)//由当前点斜下左下
                    {
                        if (color[i][j] == -1)
                        {
                            flog = 0;
                            now.x = i;
                            now.y = j;
                        }
                    }
                    flag = 0;
                    break;
                }
                num = 0;

            }
        }
    }
    //白棋进攻,找到对自己最有利的,判断当前白棋最多能连几个棋子
    int maxx = 0;
    if (choose_score)
    {
        for (int x = 0; x <= 15; x++)
        {
            for (int y = 0; y <= 15; y++)
            {
                if (color[x][y] == -1)//这一点可以落子
                {
                    int num = 0;//记录棋子数量
                    int max_num = 0;
                    //横向x不变
                    for (int i = y; i <= 15; i++)//向右
                    {
                        if (color[x][i] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    for (int i = y - 1; i >= 0; i--)//向左
                    {
                        if (color[x][i] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    max_num = max(max_num, num);
                    num = 0;
                    //竖向y不变
                    for (int i = x; i <= 15; i++)//向下
                    {
                        if (color[i][y] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    for (int i = x - 1; i >= 0; i--)//向上
                    {
                        if (color[i][y] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    max_num = max(max_num, num);
                    num = 0;
                    //由右下斜向左上'\'
                    for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
                    {
                        if (color[i][j] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
                    {
                        if (color[i][j] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    max_num = max(max_num, num);
                    num = 0;
                    //由左下斜向右上'/'
                    for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
                    {
                        if (color[i][j] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
                    {
                        if (color[i][j] == 0)
                        {
                            num++;
                        }
                        else
                            break;
                    }
                    max_num = max(max_num, num);
                    num = 0;

                    if (maxx <= max_num)
                    {
                        maxx = max_num;
                        now.x = x;
                        now.y = y;
                    }
                }
            }
        }
    }
    //MessageBox(NULL, to_string(now.x).c_str(), "Title(标题)", MB_OK);
    return now;
}
int main()
{
    chess fivech;
    fivech.welcome();//欢迎界面
    if (MODE == 1)//双人模式
    {
        fivech.PlayGame1();
    }
    else if (MODE == 2)//单人ai
    {
        fivech.PlayGame2();
    }
    getch();
    closegraph();
    return 0;
}

 

在这里附上编译好的下载地址:

云盘下载     密码:x1ao

项目源码在GitHub上:https://github.com/riba2534/Ink-FiveChess

欢迎fork…..(不过还是等写完吧,代码不忍直视~~~)

 

点赞
  1. riba2534说道:

    虽然没人看,自己沙发一下 :razz:

    1. thinkelreo说道:

      不不不,还是有人看的 :biggrin:

  2. ribald说道:

    还是很厉害的

  3. vonhyou说道:

    %%%很强大

  4. 千华缭乱说道:

    超级喜欢万代传承

发表评论

电子邮件地址不会被公开。 必填项已用*标注