【问题标题】:how to store pieces in gomoku如何在五子棋中存储碎片
【发布时间】:2017-12-02 16:57:23
【问题描述】:

我目前正在学习 MFC,并决定制作五子棋游戏。这是我到目前为止的代码。

**mainframe.h** 

class CMainFrame : public CFrameWnd
{

public:
CMainFrame();
protected: 
DECLARE_DYNAMIC(CMainFrame)


public:


public:


public:



public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif


protected:
DECLARE_MESSAGE_MAP()
void DrawBoard(CDC* pDC);
int m_nNextChar;
int board[15][15];
static const int EMPTY = 0, WHITE = 1, BLACK = 2;

public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnPaint();
};


**mainframe.cpp**

#include "stdafx.h"
#include "01.win32tomfc.h"

#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMainFrame

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()

int diameter = 23;
int size = 40;
int xCod;
int yCod;
int xCodx;
int yCody;
// CMainFrame ¹¹Ôì/Îö¹¹

CMainFrame::CMainFrame()
{
m_nNextChar = BLACK;

Create(NULL, _T("Generic Sample Application"));
CRect rect(0, 0, 700, 700);
CalcWindowRect(&rect);
SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
    SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
}

CMainFrame::~CMainFrame()
{
}



// CMainFrame Õï¶Ï

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}

#endif //_DEBUG


// CMainFrame ÏûÏ¢´¦Àí³ÌÐò



void CMainFrame::DrawBoard(CDC * pDC)
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = pDC->SelectObject(&pen);

for (int i = 1; i <= 16; i++) {
    pDC->MoveTo(40 * i, 40);
    pDC->LineTo(40 * i, 640);

    pDC->MoveTo(40, 40 * i);
    pDC->LineTo(640, 40 * i);
}

pDC->SelectObject(pOldPen);
}


void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);

CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(BLACK_BRUSH);

xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;

if (m_nNextChar != BLACK )
    return;
else {

    if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
        dc.Ellipse(xCod, yCod, xCodx, yCody);
    }
}

m_nNextChar = WHITE;


CFrameWnd::OnLButtonDown(nFlags, point);
}


void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);

CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(WHITE_BRUSH);

xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;


if (m_nNextChar != WHITE)
    return;

else {

    if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
            dc.Ellipse(xCod, yCod, xCodx, yCody);
        }
}

m_nNextChar = BLACK;

CFrameWnd::OnRButtonDown(nFlags, point);
}


void CMainFrame::OnPaint()
{
CPaintDC dc(this); 
DrawBoard(&dc);

}

我的代码在函数 DrawBoard() 中绘制了一个 15 X 15 的网格,并分别在 OnLButtonDown 和 OnRButtonDown 中绘制了黑白部分。事情是当我运行程序并单击以绘制黑色块然后是白色块时,白色块可以绘制在黑色块上,反之亦然。所以我想创建一个二维数组 board[15][15] 以在绘制时存储一块,以便不能在当前块上绘制不同的块(我在正确的轨道上)。我试过了,但我似乎不知道该怎么做。我不是很擅长编程并意识到这可能很容易,但我们将不胜感激。请解释我将如何以正确的方式进行。

这是我尝试过的。

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
 CClientDC dc(this);

 CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
 CPen* pOldPen = dc.SelectObject(&pen);
 dc.SelectStockObject(BLACK_BRUSH);

xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;

if ((m_nNextChar != BLACK) && (board[xCod][yCod] = WHITE) )
    return;
else {

    if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
        dc.Ellipse(xCod, yCod, xCodx, yCody);
        board[xCod][yCod] = BLACK;
    }
}

void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);

CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(WHITE_BRUSH);

xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;


if (m_nNextChar != WHITE && (board[xCod][yCod] = BLACK))
    return;
else {

    if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
            dc.Ellipse(xCod, yCod, xCodx, yCody);
            board[xCod][yCod] = WHITE;
        }
}

m_nNextChar = BLACK;

CFrameWnd::OnRButtonDown(nFlags, point);
}

【问题讨论】:

    标签: visual-c++ mfc


    【解决方案1】:

    您应该在OnPaint 中完成所有绘图。不要在OnLButtonDown等其他函数中绘制。相反,从OnLButtonDown 获取必要的信息并调用Invalidate,这将重新绘制窗口。

    这是一个例子。为简单起见,我创建了一个结构info 和一个二维数组datadata 存储每个单元格的所有信息,即矩形和颜色。必须初始化一次data,根据data中的信息进行绘制

    #include <vector>
    
    class CMainFrame : public CFrameWnd
    {
        ...
        struct info
        {
            CRect rect;
            int color;
        };
        std::vector<std::vector<info>> data;
    };
    
    CMainFrame::CMainFrame()
    {
        ...
        data.resize(15);
        for(int i = 0; i < data.size(); i++)
            data[i].resize(15);
    
        int xoffset = 20;
        int yoffset = 20;
        for(int row = 0; row < 15; row++)
        {
            for(int col = 0; col < 15; col++)
            {
                data[row][col].rect.SetRect(0, 0, size + 1, size + 1);
                data[row][col].rect.MoveToXY(xoffset + row * size, yoffset + col * size);
            }
        }
    }
    
    void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
    {
        CFrameWnd::OnLButtonDown(nFlags, point);
        for(int row = 0; row < 15; row++)
        {
            for(int col = 0; col < 15; col++)
            {
                if(data[row][col].color)
                    break;
    
                if(data[row][col].rect.PtInRect(point))
                {
                    data[row][col].color = WHITE;
                    break;
                }
            }
        }
        Invalidate(FALSE);
    }
    
    void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
    {
        CFrameWnd::OnRButtonDown(nFlags, point);
        for(int row = 0; row < 15; row++)
        {
            for(int col = 0; col < 15; col++)
            {
                if(data[row][col].color)
                    break;
    
                if(data[row][col].rect.PtInRect(point))
                {
                    data[row][col].color = BLACK;
                    break;
                }
            }
        }
        Invalidate(FALSE);
    }
    
    void CMainFrame::OnPaint()
    {
        CPaintDC dc(this);
        CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
        dc.SelectObject(&pen);
        CBrush white, black;
        white.CreateSolidBrush(RGB(255, 255, 255));
        black.CreateSolidBrush(RGB(0, 0, 0));
    
        for(int row = 0; row < 15; row++)
        {
            for(int col = 0; col < 15; col++)
            {
                dc.Rectangle(data[row][col].rect);
    
                if(data[row][col].color)
                {
                    CBrush *oldbrush;
                    if(data[row][col].color == WHITE)
                        oldbrush = dc.SelectObject(&white);
                    else
                        oldbrush = dc.SelectObject(&black);
                    dc.Ellipse(data[row][col].rect);
                    dc.SelectObject(oldbrush);
                }
            }
        }
    }
    

    【讨论】:

    • 嗨,非常感谢您的帮助。我们不应该在其他函数中进行任何绘图是否有特定原因?
    • 我应该澄清一下。可以在DrawBoard(CDC* pDC) 或任何其他函数中绘制,只要绘制响应WM_PAINT 消息(MFC 捕获WM_PAINT 并将其传递给OnPaint)。就像你之前设置的那样,如果你调整了窗口的大小,就会强制显示一个绘制消息,并且所有的椭圆都会被删除。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 2010-09-08
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多