白龙码~ 2021-06-09 07:44 采纳率: 0%
浏览 127
已结题

有懂MFC的嘛 孩子实在不会了

这是我的位图问题嘛 我照着书上的代码敲的 但是明明棋子下在交叉点却提示不在?

CChess.h
#pragma once
enum COLOR //棋子颜色
{
	BLACK,
	WHITE
};
class CChess
{
	int m_Num;//序号
	int m_x;//棋子位置x坐标
	int m_y;//棋子位置y坐标
	COLOR m_Color;//棋子颜色
public:
	CChess();
	~CChess();
	void Set(int num, int x, int y, COLOR color);//设置棋子属性
	COLOR GetColor()                             //取得棋子颜色 
	{
		return m_Color;
	}
	int GetX()                                   //取得棋子逻辑坐标x
	{
		return m_x;
	}
	int GetY()                                   //取得棋子逻辑坐标y
	{
		return m_y;
	}
	void Show(CDC* pDC);                         //显示棋子
	static int m_dx;                             //棋盘左上角屏幕坐标x
	static int m_dy;                             //棋盘左上角屏幕坐标y
	static double m_d;                           //棋子间距离
};

CChess.cpp
#include "pch.h"
#include "CChess.h"
#include "Resource.h"
int CChess::m_dx = 271;              //根据背景图调整
int CChess::m_dy = 68;              //根据背景图调整
double CChess::m_d = 36.5;            //根据背景图调整

CChess::CChess() {  }
CChess::~CChess() {  }

void CChess::Set(int num, int x, int y, COLOR color)
{
	m_Num = num;                          //设置落子序号
	m_x = x;                              //设置逻辑坐标x
	m_y = y;                              //设置逻辑坐标y
	m_Color = color;                      //设置落子颜色
}

void CChess::Show(CDC* pDC)
{
	CBitmap bmpMask;                       //棋子位图掩码
	bmpMask.LoadBitmap(IDB_BITMAP_MASK);   //输入棋子掩码位图资源
	CBitmap bmpQz;                         //棋子位图
	if (m_Color == WHITE)
	{
		bmpQz.LoadBitmap(IDB_BITMAP_BZ);   //载入白色棋子位图资源
	}
	else
	{
		bmpQz.LoadBitmap(IDB_BITMAP_HZ);   //载入黑色棋子位图资源
	}
	BITMAP bm;                             //位图信息
	bmpQz.GetObject(sizeof(BITMAP), &bm);  //取得位图信息
	CDC mDc0;                              //内存DC,用来显示棋子位图掩码
	mDc0.CreateCompatibleDC(pDC);          //创建用来显示棋子位图掩码的DC
	CBitmap* pOldBitmapMask = mDc0.SelectObject(&bmpMask);
	CDC mDc1;                              //内存DC,用来显示棋子位图
	mDc0.CreateCompatibleDC(pDC);          //创建用来显示棋子位图的DC
	CBitmap* pOldBitmapQz = mDc1.SelectObject(&bmpQz);
	//将掩码位图(棋子区域黑色,其它区域白色)与棋盘与运算,将棋子区域置黑,其他区域不变
	pDC->BitBlt(m_dx + m_x * m_d, m_dy + m_dy * m_d, bm.bmWidth, bm.bmHeight, &mDc0, 0, 0, SRCAND);
	//将掩码位图(棋子区域正常,其它区域黑色)与棋盘异或运算,显示棋子,其他区域不变
	pDC->BitBlt(m_dx + m_x * m_d, m_dy + m_dy * m_d, bm.bmWidth, bm.bmHeight, &mDc1, 0, 0, SRCPAINT);
	mDc1.SelectObject(pOldBitmapMask);
	mDc1.SelectObject(pOldBitmapQz);
}


CChessManager.h
#pragma once
#include "CChess.h"
#include <math.h>
#define MAX_ROWS 15                               //棋盘行数
#define MAX_COLS 15                               //棋盘列数
#define MAX_CHESS MAX_ROWS*MAX_COLS               //最多落子数
#define WIN_NUM  5                                //赢棋标准(连续五子)
class CChessManager
{
	CChess m_aChess[MAX_CHESS];                   //保存落子信息对象数组
	int m_nChess;                                 //落子个数
	COLOR m_Color;                                //当前将要落子的颜色
	bool CheckRows();                             //检查行是否达到赢棋标准
	bool CheckCols();                              //检查列是否达到赢棋标准
	bool CheckLSlash();                           //检查左斜线"\"方向是否达到赢棋标准
	bool CheckRSlash();                           //检查右斜线"/"方向是否达到赢棋标准
public:
	CChessManager();
	~CChessManager();
	void NewGame()
	{
		m_nChess = 0;
		m_Color = BLACK;
	}                                             //开始新的一局
	bool Xy2Xy(int x0, int y0, int& x1, int& y1); //物理坐标转为逻辑坐标,成功返回true
	int  Add(int x, int y);                       //在物理x,y处落子,成功返回0,没点中返回1,重复返回2
	void Show(CDC* pDC);                          //显示所有棋子
	bool GameOver();                              //判断游戏是否结束
	COLOR GetWinner()
	{
		return m_aChess[m_nChess - 1].GetColor();
	}                                             //取得获胜方棋子颜色
	CChess* GetQz(int x, int y);                  //取得指定逻辑坐标的棋子,无则返回空
};

CChessManager.cpp
#include "pch.h"
#include "CChessManager.h"
CChessManager::CChessManager() {
}
CChessManager::~CChessManager() {
}
bool CChessManager::Xy2Xy(int x0, int y0, int& x1, int& y1) {
	int x, y;
	for (int i = 0; i < 15; i++)
		for (int j = 0; j < 15; j++) {
			x = CChess::m_dx + i * CChess::m_d + CChess::m_d * 0.5;
			y = CChess::m_dy + i * CChess::m_d + CChess::m_d * 0.5;
			if (sqrt((x - x0 - 0.0) * (x - x0) + (y - y0) * (y - y0)) < 15) {
				x1 = i, y1 = j;
				return true;
			}
		}
	return false;
}
int CChessManager::Add(int x, int y) {
	int x1, y1;
	if (!Xy2Xy(x, y, x1, y1))
		return 1;
	for (int i = 0; i < m_nChess; i++)
		if (x1 == m_aChess[i].GetX() && y1 == m_aChess[i].GetY())
			return 2;
	m_aChess[m_nChess].Set(m_nChess, x1, y1, m_Color);
	m_nChess++;
	m_Color = (m_Color == WHITE ? BLACK : WHITE);
	return 0;
}
void CChessManager::Show(CDC* pDC) {
	for (int i = 0; i < m_nChess; i++)
		m_aChess[i].Show(pDC);
}
bool CChessManager::GameOver() {
	if (CheckRows())
		return true;
	if (CheckCols())
		return true;
	if (CheckLSlash())
		return true;
	if (CheckRSlash())
		return true;
	return false;
}
CChess* CChessManager::GetQz(int x, int y) {
	for (int i = 0; i < m_nChess; i++)
		if (m_aChess[i].GetX() == x && m_aChess[i].GetY() == y)
			return &m_aChess[i];
	return nullptr;
}
bool CChessManager::CheckRows() {
	CChess* pQz;
	COLOR color;
	int iCount;
	for (int i = 0; i < MAX_ROWS; i++)
	{
		iCount = 0;
		for (int j = 0; j < MAX_COLS; j++)
			if (pQz = GetQz(j, i)) {
				if (iCount == 0) {
					color = pQz->GetColor();
					iCount++;
				}
				else if (color = pQz->GetColor()) {
					iCount++;
					if (iCount == WIN_NUM)
						return true;
				}
				else {
					color = pQz->GetColor();
					iCount = 1;
				}
			}
			else
				iCount = 0;
	}
	return false;
}
bool CChessManager::CheckCols() {
	CChess* pQz;
	COLOR color;
	int iCount;
	for (int i = 0; i < MAX_COLS; i++)
	{
		iCount = 0;
		for (int j = 0; j < MAX_ROWS; j++)
		{
			if (pQz = GetQz(i, j))
			{
				if (iCount == 0)
				{
					color = pQz->GetColor();
					iCount++;
				}
				else if (color == pQz->GetColor())
				{
					iCount++;
					if (iCount == WIN_NUM)
					{
						return true;
					}
				}
				else
				{
					color = pQz->GetColor();
					iCount = 1;
				}
			}
			else
			{
				iCount = 0;
			}
		}
	}
	return false;
}
bool CChessManager::CheckLSlash()
{
	CChess* pQz;
	COLOR color;
	int iCount;
	for (int i = -14; i < MAX_COLS; i++)
	{
		iCount = 0;
		for (int j = 0; j < MAX_ROWS; j++)
		{
			if (pQz = GetQz(i + j, j))
			{
				if (iCount == 0)
				{
					color = pQz->GetColor();
					iCount++;
				}
				else if (color == pQz->GetColor())
				{
					iCount++;
					if (iCount == WIN_NUM)
					{
						return true;
					}
				}
				else
				{
					color = pQz->GetColor();
					iCount = 1;
				}
			}
			else
			{
				iCount = 0;
			}
		}
	}
	return false;
}
bool CChessManager::CheckRSlash()
{
	CChess* pQz;
	COLOR color;
	int iCount;
	for (int i = 0; i < MAX_COLS + 14; i++)
	{
		iCount = 0;
		for (int j = 0; j < MAX_ROWS; j++)
		{
			if (pQz = GetQz(i - j, j))
			{
				if (iCount == 0)
				{
					color = pQz->GetColor();
					iCount++;
				}
				else if (color == pQz->GetColor())
				{
					iCount++;
					if (iCount == WIN_NUM)
					{
						return true;
					}
				}
				else
				{
					color = pQz->GetColor();
					iCount = 1;
				}
			}
			else
			{
				iCount = 0;
			}
		}
	}
	return false;
}


FiveInARowDlg.h

// FiveInARowDlg.h: 头文件
//

#pragma once
#include "CChessManager.h"

// CFiveInARowDlg 对话框
class CFiveInARowDlg : public CDialogEx
{
// 构造
	CChessManager m_Manager;
	CFont m_FontTimer;
	CFont m_FontOver;
	int m_iTime;
	bool m_bState;
public:
	CFiveInARowDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_FIVEINAROW_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	bool NewGame(int x, int y);
	bool About(int x, int y);
	afx_msg void OnTimer(UINT_PTR nIDEvent);
};


FiveInARowDlg.cpp

// FiveInARowDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "FiveInARow.h"
#include "FiveInARowDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CFiveInARowDlg 对话框



CFiveInARowDlg::CFiveInARowDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_FIVEINAROW_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CFiveInARowDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CFiveInARowDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_LBUTTONUP()
	ON_WM_TIMER()
END_MESSAGE_MAP()


// CFiveInARowDlg 消息处理程序

BOOL CFiveInARowDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	SetWindowPos(NULL, 0, 0, 1024, 768, SWP_NOZORDER | SWP_NOMOVE);
	m_FontTimer.CreatePointFont(250, "Segoe UI Semibold", NULL);
	m_FontOver.CreatePointFont(1666, "微软雅黑", NULL);
	m_bState = false;
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CFiveInARowDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CFiveInARowDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CPaintDC dc(this);
		CDialogEx::OnPaint();
		CBitmap bmp;
		BITMAP bm;
		bmp.LoadBitmap(IDB_BITMAP_BK);
		bmp.GetObject(sizeof(BITMAP), &bm);
		CDC MemDC;
		MemDC.CreateCompatibleDC(&dc);
		CBitmap* pOldBitmap = MemDC.SelectObject(&bmp);
		dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &MemDC, 0, 0, SRCCOPY);
		MemDC.SelectObject(pOldBitmap);
		m_Manager.Show(&dc);
		CDialogEx::OnPaint();
	}
}
void CFiveInARowDlg::OnLButtonUp(UINT nFlags, CPoint point) {
	if (NewGame(point.x, point.y))
		return;
	if (About(point.x, point.y))
		return;
	if (!m_bState) {
		AfxMessageBox("请选择“开始”按钮开始新的游戏,按Esc键退出游戏!");
		return;
	}
	int r = m_Manager.Add(point.x, point.y);
	if (r == 0) {
		CClientDC dc(this);
		m_Manager.Show(&dc);
		if (m_Manager.GameOver()) {
			KillTimer(1);
			CString csTemp;
			if (m_Manager.GetWinner() == WHITE)
				csTemp.Format("白方胜!");
			else
				csTemp.Format("黑方胜!");
			m_bState = false;
			CClientDC dc(this);
			CFont* pOldFont = dc.SelectObject(&m_FontOver);
			int OldBKMode = dc.GetBkMode();
			COLORREF OldColor, NewColor1 = RGB(60, 60, 60), NewColor2 = (250, 50, 50);
			dc.SetBkMode(TRANSPARENT);
			OldColor = dc.SetTextColor(NewColor1);
			dc.TextOut(158, 208, csTemp);
			dc.SetTextColor(NewColor2);
			dc.TextOut(150, 200, csTemp);
			dc.SetTextColor(OldColor);
			dc.SetBkMode(OldBKMode);
			dc.SelectObject(pOldFont);
		}
	}
	if (r == 1)
		AfxMessageBox("请在棋盘交叉点落子!");
	else if (r == 2)
		AfxMessageBox("不可以重复落子!");
	CDialogEx::OnLButtonUp(nFlags, point);
}
bool CFiveInARowDlg::NewGame(int x, int y) {
	int x0 = 35, y0 = 150, x1 = 200, y1 = 185;
	if ((x >= x0 && x <= x1) && (y >= y0 && y <= y1)) {
		m_Manager.NewGame();
		Invalidate();
		m_iTime = 0;
		SetTimer(1, 1000, NULL);
		m_bState = true;
		return true;
	}
	return false;
}
bool CFiveInARowDlg::About(int x, int y) {
	int x0 = 35, y0 = 70, x1 = 200, y1 = 95;
	if ((x >= x0 && x <= x1) && (y >= y0 && y <= y1)) {
		CAboutDlg dlg;
		dlg.DoModal();
		return true;
	}
	return false;
}
void CFiveInARowDlg::OnTimer(UINT_PTR nIDEvent) {
	switch (nIDEvent) {
	case 1: {
		CClientDC dc(this);
		CFont* pOldFont;
		pOldFont = dc.SelectObject(&m_FontTimer);
		m_iTime++;
		CString csTemp;
		csTemp.Format("%04d", m_iTime);
		COLORREF OldColor, NewColor = RGB(150, 50, 50);
		OldColor = dc.SetTextColor(NewColor);
		dc.TextOut(725, 20, csTemp);
		dc.SetTextColor(OldColor);
		dc.SelectObject(pOldFont);
		break;
	}
	}
	CDialogEx::OnTimer(nIDEvent);
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CFiveInARowDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

  • 写回答

4条回答 默认 最新

  • 关注

    调试一下或者打印一些信息出来,看看是不是那里算错了坐标。

    评论

报告相同问题?

悬赏问题

  • ¥15 wpf界面一直接收PLC给过来的信号,导致UI界面操作起来会卡顿
  • ¥15 init i2c:2 freq:100000[MAIXPY]: find ov2640[MAIXPY]: find ov sensor是main文件哪里有问题吗
  • ¥15 运动想象脑电信号数据集.vhdr
  • ¥15 三因素重复测量数据R语句编写,不存在交互作用
  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒