C语言可视化数独游戏 (含源码和开发报告)

前几个月C语言结课,做了个数独游戏的大作业。因为不满足于命令行界面的简陋效果,就现学了Win32 API做了个可视化界面。程序的运行效果图如下:

下载源码及报告:C语言数独游戏大作业(含报告/Win32可视化)

功能概要

1. 按右侧的上下键可以切换数独图。数独图存在文件目录map下,运行程序会自动读取目录下全部数独图。

2. 按右下方的Go按钮,可以快速解出最终答案。这里的解题算法采用深搜直接暴力破解。

3. 选中数独图上的某一格,其行、列、九宫格会加深颜色,以做提示。

解题代码

/* 使用solveSudoku算法解数独 */
int solveSudoku(pNode *p, int depth) {                        //深度为地图坐标x*9+y;函数返回值为布尔值0、1,表示是否解出
    int i, j, x, y;
    int book[10];                                   //标记该位置各位数可否填入
    x = depth / 9;                                  //坐标x
    y = depth % 9;                                  //坐标y
    if (depth == 81) return 1;                      //到达地图最后位置,返回真

    if (p->solution[x][y] == 0) {                           //如果该位置待填入数字
        memset(book, 0, sizeof(book));                //初始化book数组

        for (i = 0; i < 9; i++) {                   //在book中标记行、列、九宫格中出现数字
            book[p->solution[x][i]] = 1;
            book[p->solution[i][y]] = 1;
        }
        for (i = 0; i < 3; i++)
            for (j = 0; j < 3; j++)
                book[p->solution[x / 3 * 3 + i][y / 3 * 3 + j]] = 1;

        for (i = 1; i <= 9; i++)                            //遍历填入可填入的数字,递归下一个深度
            if (book[i] == 0) {
                p->solution[x][y] = i;
                if (solveSudoku(p, depth + 1)) return 1;
                p->solution[x][y] = 0;
            }
        return 0;                                   //遍历完所有数字仍未解出,返回假
    }
    else {                                          //如果该位置有数字
        if (solveSudoku(p, depth + 1)) return 1;
        return 0;
    }
}

绘制窗口

/* 窗口绘制函数 */
void drawScene(HWND hWnd)
{
    HDC hdc;
    HPEN hpen;
    HBRUSH hbrush;
    HFONT hfont;
    PAINTSTRUCT ps;

    int i, j;

    hdc = BeginPaint(hWnd, &ps);

    /* 绘制数独图圆角底板 */
    hbrush = CreateSolidBrush(RGB(106, 106, 106));
    hpen = CreatePen(PS_NULL, 1, 0);
    SelectObject(hdc, hpen);
    SelectObject(hdc, hbrush);
    RoundRect(hdc, x, y, x + 9 * squareWidth, y + 9 * squareWidth, 20, 20);

    /* 如果选中,绘制选中小格及其行、列、九宫格 */
    if ((iMouse >= 0) && (iMouse <= 8) && (jMouse >= 0) && (jMouse <= 8)) {
        hbrush = CreateSolidBrush(RGB(97, 97, 97));
        hpen = CreatePen(PS_NULL, 1, 0);
        SelectObject(hdc, hpen);
        SelectObject(hdc, hbrush);
        Rectangle(hdc, x + iMouse * squareWidth, y, x + (iMouse + 1)*squareWidth, y + 9 * squareWidth);
        Rectangle(hdc, x, y + jMouse * squareWidth, x + 9 * squareWidth, y + (jMouse + 1)*squareWidth);
        Rectangle(hdc, x + iMouse / 3 * 3 * squareWidth, y + jMouse / 3 * 3 * squareWidth, x + (iMouse / 3 + 1) * 3 * squareWidth, y + (jMouse / 3 + 1) * 3 * squareWidth);
        hbrush = CreateSolidBrush(RGB(65, 224, 170));
        hpen = CreatePen(PS_NULL, 1, 0);
        SelectObject(hdc, hpen);
        SelectObject(hdc, hbrush);
        Rectangle(hdc, x + iMouse * squareWidth, y + jMouse * squareWidth, x + (iMouse + 1)*squareWidth, y + (jMouse + 1)*squareWidth);
    }

    /* 绘制九宫格分割线 */
    hpen = CreatePen(PS_SOLID, 1, RGB(76, 76, 76));
    SelectObject(hdc, hpen);
    for (i = 1; i < 9; i++) {
        MoveToEx(hdc, x, y + i * squareWidth, NULL);
        LineTo(hdc, x + 9 * squareWidth, y + i * squareWidth);
        MoveToEx(hdc, x + i * squareWidth, y, NULL);
        LineTo(hdc, x + i * squareWidth, y + 9 * squareWidth);
    }
    hpen = CreatePen(PS_SOLID, 3, RGB(76, 76, 76));
    SelectObject(hdc, hpen);
    for (i = 1; i < 3; i++) {
        MoveToEx(hdc, x, y + i * squareWidth * 3, NULL);
        LineTo(hdc, x + 9 * squareWidth, y + i * squareWidth * 3);
        MoveToEx(hdc, x + i * squareWidth * 3, y, NULL);
        LineTo(hdc, x + i * squareWidth * 3, y + 9 * squareWidth);
    }

    /* 如果解题按钮已点击,绘制数独答案数字 */
    hfont = CreateFont(squareWidth, 2 * squareWidth / 5, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SCRIPT, TEXT("Calibri"));
    SelectObject(hdc, hfont);
    SetBkMode(hdc, TRANSPARENT);
    TCHAR cha[2] = { 0 };
    if (solved == 1) {
        SetTextColor(hdc, RGB(160, 191, 180));
        for (i = 0; i < 9; i++)
            for (j = 0; j < 9; j++) {
                _itow(p->solution[i][j], cha, 10);
                TextOut(hdc, x + squareWidth / 3 + i * squareWidth, y + j * squareWidth, cha, 1);
            }
    }

    /* 绘制数独原题数字 */
    SetTextColor(hdc, RGB(230, 230, 230));
    for (i = 0; i < 9; i++)
        for (j = 0; j < 9; j++)
            if (p->map[i][j] != 0) {
                _itow(p->map[i][j], cha, 10);
                TextOut(hdc, x + squareWidth / 3 + i * squareWidth, y + j * squareWidth, cha, 1);
            }

    EndPaint(hWnd, &ps);

}

 

  • 5
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两只程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值