在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例C/C++游戏开发 → 模拟一个模类游戏-棋盘游戏

模拟一个模类游戏-棋盘游戏

C/C++游戏开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:6.54M
  • 下载次数:21
  • 浏览次数:248
  • 发布时间:2020-02-26
  • 实例类别:C/C++游戏开发
  • 发 布 人:reyallen
  • 文件格式:.rar
  • 所需积分:2
 相关标签: 模拟 游戏 c++

实例介绍

【实例简介】模拟一个模类游戏: 1. 角色 (红棋,蓝棋) 

2. 模盘 4x4 

3. 走位 (规则:红棋橫走,蓝棋斜走)

【实例截图】

from clipboard

【核心代码】

设计 架构 
GameView: 游戏UI,负责界面显示 GameModel: 游戏数据,记录角色、每个角色 的位置。 GameRole: 角色定义。 GamePosition: 模盘位置坐标 

GameModel 
负责存储游戏相关的数据。 (1)角色(即棋子) (2)角色的位置 
如何定义角色的位置?   描述4x4共16个单元格,描述每个单元格里 有没有角色对象。 
规则:走位前做出判断 canMoveTo(from, to)     能否将from移至to位置 
moveTo(from, to)    将from移至to位置

负责具体的显示: 
paintEvent() 里画出棋盘 mouse/drag event来实现拖动操作 

#ifndef GAMEVIEW_H
#define GAMEVIEW_H

#include <QFrame>
#include <QtGui>

#include "GameModel.h"

class GameView : public QFrame
{
Q_OBJECT

public:
GameView(QWidget *parent);
~GameView();

private:
virtual void paintEvent ( QPaintEvent * event );
virtual void resizeEvent ( QResizeEvent * event );

// 鼠标支持
void mouseDoubleClickEvent ( QMouseEvent * event );
void mouseMoveEvent ( QMouseEvent * event );
void mousePressEvent ( QMouseEvent * event );
void mouseReleaseEvent ( QMouseEvent * event );

// 拖放支持
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent (QDragLeaveEvent * event );
void dragMoveEvent (QDragMoveEvent * event );
void dropEvent(QDropEvent *event);


private:
// 重置游戏
void reset();

// 当窗口改变大小时,重新计算单元格大小
void caculate();

// 从鼠标位置换算出单元格坐标
GamePosition getPostion(QPoint pt);

// 单元格中心的热点区域
QRect hotArea(GamePosition pos);

// 单元格区域
QRect selectedArea(GamePosition pos);

private:
QRect m_cells[4][4] ; // 4x4方格,每个单元的具体位置
GameModel m_gameModel;// 游戏数据

private:
/* 拖放操作 */
bool m_mousePressed; // 鼠标按下时,开始拖动
QPoint m_dragPosition;  // 拖动操作的起点
GamePosition m_posFrom; // 被拖动的那个起始坐标
GameRole* m_draggedIem; // 被拖动的那个单元格里的对象

bool m_allowDrop; // 拖放探测:允许drop在这里
GamePosition m_allowDropPos; // 目标单元格位置
};

#endif // GAMEVIEW_H





#include "GameView.h"

GameView::GameView(QWidget *parent)
: QFrame(parent)
{
// 添加拖放支持
setAcceptDrops(true);

reset();

}

GameView::~GameView()
{

}

// 重置游戏
void GameView::reset()
{
m_gameModel.reset();
m_mousePressed = false;
update();
}

// 当窗口改变大小时,重新计算单元格大小
void GameView::caculate()
{
int width = this->width();
int height = this->height();

// 计算4个方格的位置
for(int i=0; i<4; i )
{
int top = i*height/4;
int bottom = (i 1) * height/4;

for(int j=0; j<4; j )
{
int left = j*width/4;
int right = j*height/4;

m_cells[i][j] = QRect(left, top, width/4,height/4);
}
}
}

// 从鼠标位置换算出单元格坐标
GamePosition GameView::getPostion(QPoint pt)
{
for(int i=0; i<4; i )
{
for(int j=0; j<4; j )
{
QRect r = m_cells[i][j];
//r.adjust(2,2,-2,-2);

if(r.contains(pt))
{
return GamePosition(i,j);
}
}
}
return GamePosition();
}

// 单元格中心的热点区域
QRect GameView::hotArea(GamePosition pos)
{
QRect rRed = m_cells[pos.x][pos.y];
QRect rHot = QRect(0,0,33,33);
rHot.moveCenter(rRed.center());
return rHot;
}

// 单元格区域
QRect GameView::selectedArea(GamePosition pos)
{
QRect rSelected = m_cells[pos.x][pos.y];
return rSelected.adjusted(1,1,-1,-1);
}

// Widget事件
void GameView::resizeEvent ( QResizeEvent * event )
{
caculate();
}
// Widget事件
void GameView::paintEvent ( QPaintEvent * event )
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);

int width = this->width();
int height = this->height();
QRect rect(0,0, width, height);

QPen pen;

// 背景
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(QColor(0xFF,0xFF, 0xFF)));
painter.drawRect(rect);

// 4x4方格
pen.setStyle(Qt::SolidLine);
pen.setColor(QColor(0x33,0x33, 0x33));
painter.setPen(pen);
int i,j;
for(i=0; i<=4; i )
{
int xpos = i*width/4;
int ypos = i*height/4;
painter.drawLine(xpos, 0, xpos, height);
painter.drawLine(0, ypos, width, ypos);
}

// 棋子:如果该单元格里有棋子,则画出该棋子
for(i=0; i<4; i )
{
for(int j=0; j<4; j )
{
GamePosition pos(i,j);
GameRole* role = m_gameModel.at(pos);
if(role != NULL)
{
QRect rRed = hotArea(pos);
painter.drawPixmap(rRed, role->icon);
}
}
}

// 拖放显示:高亮选中目标单元格
if(m_mousePressed && m_allowDrop)
{
QRect area = selectedArea(m_allowDropPos);
painter.setBrush(QColor(0x66, 0x66, 0x66));
painter.drawRect(area);

QRect hot = hotArea(m_allowDropPos);
painter.drawPixmap(hot, m_draggedIem->icon);

pen.setStyle(Qt::DotLine);
pen.setColor(QColor(0xEE, 0xEE, 0xEE));
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
painter.drawEllipse(hot.adjusted(-2,-2,2,2));
}
}

// 忽略双击事件
void GameView::mouseDoubleClickEvent ( QMouseEvent * event )
{
QWidget::mouseDoubleClickEvent(event);
}

// 鼠标按下
void GameView::mousePressEvent ( QMouseEvent * event )
{
m_mousePressed = true;
m_draggedIem = NULL;
m_allowDrop = false;

// 记下起点
m_dragPosition = event->pos();
m_posFrom = getPostion(event->pos());
QRect hot = hotArea(m_posFrom);
if(hot.contains(event->pos()))
{
m_draggedIem = m_gameModel.at(m_posFrom);
}


QFrame::mousePressEvent(event);
}
// 鼠标松开
void GameView::mouseReleaseEvent ( QMouseEvent * event )
{
m_mousePressed = false;
m_allowDrop = false;
update();
}
// 鼠标移动
void GameView::mouseMoveEvent ( QMouseEvent * event )
{
if(!m_mousePressed) return;
if(!m_draggedIem) return;

// 只允许用左键拖动
if (!(event->buttons() & Qt::LeftButton))
return;

// 移动一定距离后,才算是开始拖动
if ((event->pos() - m_dragPosition).manhattanLength()
< QApplication::startDragDistance())
return;

// 找到拖动的项
QString text = "what";

// 创建数据
QDrag *drag = new QDrag(this);

QMimeData *mimeData = new QMimeData;
mimeData->setData("game/move", QByteArray("no need"));
drag->setMimeData(mimeData);
//drag->setPixmap(m_draggedIem->icon);

// 启动拖放start a drag
Qt::DropAction result = drag->exec(Qt::CopyAction | Qt::MoveAction);

// 检查操作有没有成功/有没有被取消
if(Qt::IgnoreAction != result)
{

}
else
{
// 按住ctrl键: Qt::CopyAction
// 没按: Qt::MoveAction
}
m_mousePressed = false;
m_allowDrop = false;
}

// 拖放事件
// 有东西被拖进来(拖着、未松开鼠标)
void GameView::dragEnterEvent(QDragEnterEvent *event)
{
QStringList formats = event->mimeData()->formats();
for(int i=0; i<formats.size(); i )
{
QString fmt = formats.at(i);
qDebug() << "Format:" << fmt;
}

if (event->mimeData()->hasFormat("game/move"))
{
event->acceptProposedAction();
}
}
// 拖放事件: 经过目标单元格时,要检查是否可以移到这里
void GameView::dragMoveEvent (QDragMoveEvent * event )
{
GamePosition posTo = getPostion(event->pos());

// 检查是否可以移动到目标位置 
if(m_gameModel.canMoveTo(m_posFrom, posTo) )
{
if (event->mimeData()->hasFormat("game/move"))
{
event->acceptProposedAction();

// 更新显示
m_allowDrop = true;
m_allowDropPos = posTo;
update();
return;
}
}

m_allowDrop = false;
update();
event->ignore();
}
// 拖放事件
void GameView::dragLeaveEvent (QDragLeaveEvent * event )
{
QFrame::dragLeaveEvent(event);
}


// 有东西被放下(松开鼠标)
void GameView::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("game/move"))
{
QString text  = event->mimeData()->text();

// 移动到目标单元格,并重绘
GamePosition posTo = getPostion(event->pos());
m_gameModel.moveTo(m_posFrom, posTo);
update();

event->acceptProposedAction();
}

}




#ifndef _GAME_ROLE_H
#define _GAME_ROLE_H

#include <QPixmap>

/* 角色定义 */

class GameRole
{
public:
GameRole():id(-1)
{
}
GameRole(int id, QString imagePath)
{
this->id = id;
icon.load(imagePath);
}

public:
// 每个角色设置一个ID类型
enum{ BLUE, RED };

public:
int id; // ID
QPixmap icon; // 相应的图标显示
};




#endif

#ifndef _GAME_MODEL_H
#define _GAME_MODEL_H

#include "GameRole.h"
#include "GamePosition.h"

/* 棋盘数据 */
class GameModel
{
public:
GameModel();

// 重置游戏
void reset();

// 获取x,y处的角色
GameRole* at(GamePosition pos);

// 测试:是否可以从from位置移到to位置
bool canMoveTo(GamePosition from, GamePosition to);

// 移动
void moveTo(GamePosition from, GamePosition to);

private:
// 记录每一位置有哪个角色
GameRole* m_layout[4][4];

// 创建N个角色 (本例中一共2个角色)
GameRole* m_roles[2];
};


#endif



#include <stdio.h>
#include <math.h>
#include <string.h>

#include "GameModel.h"
#include <QDebug>

GameModel::GameModel()
{
// 创建角色
m_roles[0] = new GameRole(GameRole::RED, ":/Resources/roleRed.png");
m_roles[1] = new GameRole(GameRole::BLUE, ":/Resources/roleBlue.png");

reset();
}

void GameModel::reset()
{
// 角色的初始位置
memset(m_layout, 0, sizeof(m_layout));
m_layout[0][0] = m_roles[0]; // 红棋
m_layout[3][3] = m_roles[1]; // 蓝棋
}

// 获取x,y处的角色
GameRole* GameModel::at(GamePosition pos)
{
return m_layout[pos.x][pos.y];
}

// 测试:是否可以从from位置移到to位置
bool GameModel::canMoveTo(GamePosition from, GamePosition to)
{
qDebug("canMoveTo: (%d,%d) -> (%d,%d) ", from.x, from.y, to.x, to.y);

GameRole* roleFrom = at(from);
GameRole* roleTo = at(to);
if(roleTo != NULL)
return false; // 目标位置已经有棋子占位

// 红棋规则
if(roleFrom->id == GameRole::RED)
{
if(from.x == to.x)
{
if(abs(from.y - to.y) == 1) 
return true;
}
else if(from.y == to.y)
{
if(abs(from.x - to.x) == 1) 
return true;
}
}

// 蓝棋规则
if(roleFrom->id == GameRole::BLUE)
{
int dx = from.x - to.x;
int dy = from.y - to.y;
if(abs(dx) == 1 && abs(dy) == 1)
return true;
}

return false;
}

// 移动
void GameModel::moveTo(GamePosition from, GamePosition to)
{
GameRole* role = at(from);
m_layout[from.x][from.y] = NULL;
m_layout[to.x][to.y] = role;
}



标签: 模拟 游戏 c++

实例下载地址

模拟一个模类游戏-棋盘游戏

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警