【Windows小游戏】圈叉棋
acmilan2015/12/31软件综合 IP:四川
按照惯例,这种小程序不再更新,所以有bug的话请自己改。

运行界面:

CaptureOOXX.png

<code class="lang-cpp">// OOXX.cpp : Defines the entry point for the console application.
//
    
//#include "stdafx.h"
    
#define UNICODE 1
#include <windows.h>
#include <windowsx.h> // HANDLE_MSG
    
HWND hMainWnd;
    
int data[3][3] = { 0 };
int status = 1;
    
RECT rects[3][3] = { 
    0, 0, 100, 100,
    100, 0, 200, 100,
    200, 0, 300, 100,
    0, 100, 100, 200,
    100, 100, 200, 200,
    200, 100, 300, 200,
    0, 200, 100, 300,
    100, 200, 200, 300,
    200, 200, 300, 300,
};
    
void DrawHash(HDC hdc, RECT firstrc) // 绘制边线
{
    int width = firstrc.right - firstrc.left;
    int height = firstrc.bottom - firstrc.top;
    MoveToEx(hdc, firstrc.left, firstrc.bottom, NULL);
    LineTo(hdc, firstrc.left + 3 * width, firstrc.bottom);
    MoveToEx(hdc, firstrc.left, firstrc.bottom + height, NULL);
    LineTo(hdc, firstrc.left + 3 * width, firstrc.bottom + height);
    MoveToEx(hdc, firstrc.right, firstrc.top, NULL);
    LineTo(hdc, firstrc.right, firstrc.top + 3 * height);
    MoveToEx(hdc, firstrc.right + width, firstrc.top, NULL);
    LineTo(hdc, firstrc.right + width, firstrc.top + 3 * height);
}
    
void DrawO(HDC hdc, RECT rc) // 绘制O
{
    Ellipse(hdc, rc.left + 10, rc.top + 10, rc.right - 10, rc.bottom - 10);
}
    
void DrawX(HDC hdc, RECT rc) // 绘制X
{
    MoveToEx(hdc, rc.left, rc.top, NULL);
    LineTo(hdc, rc.right, rc.bottom);
    MoveToEx(hdc, rc.right, rc.top, NULL);
    LineTo(hdc, rc.left, rc.bottom);
}
    
void MainWnd_OnPaint(HWND hwnd)
{
    // WM_PAINT界面重绘消息
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps); // 开始重绘
        
    DrawHash(hdc, rects[0][0]); // 绘制边线
    
    for (int j = 0; j < 3; j++)
    {
        for (int k = 0; k < 3; k++) // 绘制棋子
        {
            if (data[j][k] == 1)
                DrawO(hdc, rects[j][k]);
            else if (data[j][k] == 2)
                DrawX(hdc, rects[j][k]);
        }
    }
    
    EndPaint(hwnd, &ps); // 结束重绘
}
    
void DropOX(HWND hwnd, int j, int k) // 落子
{
    if (data[j][k] == 0) // 如果这个位置没有棋子
    {
        data[j][k] = status; // 落子
        if (status == 1)
            status = 2; // 换对手
        else
            status = 1;
        InvalidateRect(hwnd, NULL, FALSE); // 绘制棋子
    }
}
    
void WinGame(HWND hwnd, int winner) // 显示胜负并重新开局
{
    switch (winner)
    {
    case 0:
        MessageBox(hwnd, L"No one won the game.", L"Result", MB_OK);
        break;
    case 1:
        MessageBox(hwnd, L"'O' won the game.", L"Result", MB_OK);
        break;
    case 2:
        MessageBox(hwnd, L"'X' won the game.", L"Result", MB_OK);
        break;
    }
    memset(data, 0, sizeof data); // 重新开局
    InvalidateRect(hwnd, NULL, TRUE); // 重新绘制界面
}
    
void DetectWinner(HWND hwnd) // 检测是否有胜出
{
    if (data[0][0] != 0
        && data[0][0] == data[1][1]
        && data[1][1] == data[2][2])
        return WinGame(hwnd, data[0][0]); // 正对角线
    if (data[0][2] != 0
        && data[0][2] == data[1][1]
        && data[1][1] == data[2][0])
        return WinGame(hwnd, data[0][2]); // 反对角线
    for (int j = 0; j < 3; j++)
    {
        if (data[0][j] != 0
            && data[0][j] == data[1][j]
            && data[1][j] == data[2][j])
            return WinGame(hwnd, data[0][j]); // 横向
        if (data[j][0] != 0
            && data[j][0] == data[j][1]
            && data[j][1] == data[j][2])
            return WinGame(hwnd, data[j][0]); // 纵向
    }
    int zeros = 0;
    for (int j = 0; j < 3; j++)
        for (int k = 0; k < 3; k++) // 计数空位
            if (data[j][k] == 0)
                zeros++;
    if (zeros == 0) // 如果全部下满
    {
        int ones = 0, twos = 0;
        for (int j = 0; j < 3; j++)
            for (int k = 0; k < 3; k++) // 计数两种棋子
            {
                if (data[j][k] == 1)
                    ones++;
                else if (data[j][k] == 2)
                    twos++;
            }
        if (ones > twos)
            return WinGame(hwnd, 1); // 圈多于叉
        else if (twos > ones)
            return WinGame(hwnd, 2); // 叉多余圈
        else
            return WinGame(hwnd, 0); // 相等(实际不可能出现)
    }
}
    
void MainWnd_OnLButtonDown(HWND hwnd, BOOL dblclk, int x, int y, UINT vkey)
{
    // WM_LBUTTONDOWN鼠标按下消息
    POINT pt = { x, y };
    for (int j = 0; j < 3; j++)
    {
        for (int k = 0; k < 3; k++)
        {
            if (PtInRect(&rects[j][k], pt)) // 如果在落子区域按下
            {
                DropOX(hwnd, j, k); // 落子
                DetectWinner(hwnd); // 检测是否有胜出
            }
        }
    }
}
    
BOOL MainWnd_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
    // WM_CREATE窗口创建消息
    RECT rcwindow, rcclient;
    GetWindowRect(hwnd, &rcwindow);
    GetClientRect(hwnd, &rcclient);
    rcwindow.right += 300 - (rcclient.right - rcclient.left);
    rcwindow.bottom += 300 - (rcclient.bottom - rcclient.top);
    MoveWindow(hwnd, rcwindow.left, rcwindow.top,
        rcwindow.right - rcwindow.left,
        rcwindow.bottom - rcwindow.top, FALSE); // 保证客户区为300x300
    return TRUE;
}
    
void MainWnd_OnDestroy(HWND hwnd)
{
    // WM_DESTROY窗口销毁消息
    PostQuitMessage(0);
}
    
LRESULT CALLBACK MainWnd_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // WndProc窗口消息处理函数
    switch (message)
    {
        HANDLE_MSG(hwnd, WM_CREATE, MainWnd_OnCreate);
        HANDLE_MSG(hwnd, WM_DESTROY, MainWnd_OnDestroy);
        HANDLE_MSG(hwnd, WM_PAINT, MainWnd_OnPaint);
        HANDLE_MSG(hwnd, WM_LBUTTONDOWN, MainWnd_OnLButtonDown);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
    
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR lpszCmdLine, int nCmdShow)
{
    // wWinMain入口点
    WNDCLASSEX wc = {
        sizeof wc,
        CS_HREDRAW | CS_VREDRAW, // 窗口显示方式
        MainWnd_WndProc, // 窗口消息处理函数
        0, 0, // 类附加数据、窗口附加数据
        NULL, // 模块句柄(EXE模块可NULL)
        LoadIcon(NULL, IDI_APPLICATION), // 图标
        LoadCursor(NULL, IDC_ARROW), // 鼠标指针
        (HBRUSH)GetStockObject(WHITE_BRUSH), // 背景画刷
        NULL, // 菜单
        L"MyOOXXClass", // 窗口类名
        LoadIcon(NULL, IDI_APPLICATION) // 小图标
    };
    RegisterClassEx(&wc); // 注册窗口类
    
    hMainWnd = CreateWindowEx( // 创建窗口
        WS_EX_OVERLAPPEDWINDOW, // 扩展风格
        L"MyOOXXClass", L"OOXX", // 窗口类,窗口标题
        WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, // 基本风格
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, // 四角坐标
        NULL, NULL, NULL, NULL); // 父窗口,菜单或序号,模块句柄,附加信息
    ShowWindow(hMainWnd, nCmdShow); // 显示窗口
    UpdateWindow(hMainWnd); // 刷新窗口
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) // 获取消息(同时分发高优先级消息)
    {
        TranslateMessage(&msg); // 翻译键盘消息
        DispatchMessage(&msg); // 分发消息
    }
    
    return (int)msg.wParam; // 收到WM_QUIT,GetMessage返回FALSE退出
}</windowsx.h></windows.h></code>

attachment icon OOXX.rar 41.97KB RAR 26次下载
来自:计算机科学 / 软件综合
2
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
acmilan 作者
8年4个月前 IP:四川
802509
这里编译时没开XP支持,所以不兼容XP。XP用户可以用Visual Studio 2010自己编译一下。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年2个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}