这是我的位图问题嘛 我照着书上的代码敲的 但是明明棋子下在交叉点却提示不在?
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);
}