QT项目三:中国象棋

您所在的位置:网站首页 中国象棋怎么分类 QT项目三:中国象棋

QT项目三:中国象棋

2024-07-17 17:32:34| 来源: 网络整理| 查看: 265

1,简介

QT实现中国象棋单机版,本来以为会花费不少时间的。由于之前2个游戏项目的练手,这个主要只在走棋算法部分花了些时间研究,最后一共2个晚上完成。

由于只是QT学习,没有考虑更多复杂功能,比如人机对战等,那个可能算法就得花很长时间。

 

2,效果

 

 

3,设计思路

 

准备2个棋盘棋子图片:

 

棋子类:

 

#pragma once #include "qpainter.h" enum ITEM_TYPE{ ITEM_SHUAI = 0, //帅 ITEM_SHI, //士 ITEM_XIANG, //象 ITEM_JU, //车 ITEM_MA, //马 ITEM_PAO, //炮 ITEM_BING, //兵 ITEM_MAX, }; enum ITEM_COLOR{ COLOR_RED = 0, //红方 COLOR_BLACK, //黑方 COLOR_MAX, }; class Item { public: Item(){} Item(ITEM_TYPE t,ITEM_COLOR c,QPoint pt); ~Item(void); public: ITEM_TYPE m_type; //棋子类型 ITEM_COLOR m_color; //红方黑方 QPoint m_pt; //位置 bool m_bShow; //是否显示,实现选中时闪烁效果 };

可以看到,棋子类型的定义和图片中棋子顺序一致,是为了直接以此枚举值计算棋子在图片中的位置。

 

 

MainWindow.h:

 

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include "Item.h" #include "qmap.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void InitItems(); //初始化所有棋子位置 void NewGame(); //新游戏 bool FindItemAtPoint(QPoint pt,Item& item); //给定一个棋盘上的点,查找是否存在棋子 bool DeleteItemAtPoint(QPoint pt,bool& bDeleteSHUAI); //bDeleteSHUAI:是否打掉的是“帅”或“将” void SetItemShow(Item item,bool bShow); //设置棋子显隐 bool MoveItem(Item item,QPoint ptMoveTo); //走棋逻辑 void ChangeItemPoint(QPoint ptItem,QPoint pt); //改变棋子位置属性 void DrawItem(QPainter& painter,Item item); //绘制棋子 //获取棋子能移动的区域 void GetMoveArea(Item item,QVector& area); void GetMoveArea_JU(Item item,QVector& area); void GetMoveArea_MA(Item item,QVector& area); void GetMoveArea_XIANG(Item item,QVector& area); void GetMoveArea_SHI(Item item,QVector& area); void GetMoveArea_SHUAI(Item item,QVector& area); void GetMoveArea_PAO(Item item,QVector& area); void GetMoveArea_BING(Item item,QVector& area); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void timerEvent(QTimerEvent *); private: Ui::MainWindow *ui; int m_nItemWidth; int m_nItemHeight; QPixmap m_ItemsImage; //棋子图片 QVector m_items; //所有棋子 Item m_SelectedItem; bool m_bExistSelectedItem; //是否已存在选中的棋子 bool m_bIsRedTurn; //当前该红方下 }; #endif // MAINWINDOW_H

其中主要逻辑都在mousePressEvent 鼠标响应:

 

 

//鼠标点击,走棋、吃棋等逻辑 void MainWindow::mousePressEvent(QMouseEvent * e) { //获得鼠标点所对应的棋盘点pt QPoint pt; pt.setX( (e->pos().x() - START_X ) / RECT_WIDTH); pt.setY( (e->pos().y() - START_Y ) / RECT_HEIGHT); //是否有选中的棋子 if(m_bExistSelectedItem) { //已存在棋子,判断鼠标点击的是否是选中棋子 if (pt == m_SelectedItem.m_pt) { //再次点击已经选择的棋子,什么也不做 return; } //点击其它棋子 Item ClickedItem; if (FindItemAtPoint(pt,ClickedItem)) { //点击的同色的另外一个棋子,改选 if ( (m_bIsRedTurn && ClickedItem.m_color == COLOR_RED) || (!m_bIsRedTurn && ClickedItem.m_color != COLOR_RED)) { SetItemShow(m_SelectedItem,true); m_SelectedItem = ClickedItem; return; } } //点击的异色棋子,判断是否能走能吃 QVector moveArea; GetMoveArea(m_SelectedItem,moveArea); //获取已选择棋子的可移动区域 if (moveArea.contains(pt)) { //包含当前鼠标点中的棋子,则能吃 bool bDeleteSHUAI = false; DeleteItemAtPoint(pt,bDeleteSHUAI); ChangeItemPoint(m_SelectedItem.m_pt,pt); if (bDeleteSHUAI) { QString str = m_bIsRedTurn?QStringLiteral("红方胜利!"):QStringLiteral("黑方胜利!"); QMessageBox::information(NULL, "GAME OVER ",str, QMessageBox::Yes , QMessageBox::Yes); NewGame(); return ; } m_bExistSelectedItem = false; m_bIsRedTurn = !m_bIsRedTurn; update(); return ; } else { //不能走到该位置 return ; } } else { //当前没有选中棋子 Item ClickedItem; if (FindItemAtPoint(pt,ClickedItem)) { //如果点中一个棋子,是当前走棋方的颜色,就选中了 if ( (m_bIsRedTurn && ClickedItem.m_color == COLOR_RED) || (!m_bIsRedTurn && ClickedItem.m_color == COLOR_BLACK)) { m_SelectedItem = ClickedItem; m_bExistSelectedItem = true; return; } } } }

里面最重要的就是这个GetMoveArea 函数,用来获取每个棋子的可走动的区域:

 

 

void MainWindow::GetMoveArea(Item item,QVector& moveArea) { switch (item.m_type) { case ITEM_JU: { GetMoveArea_JU(item,moveArea); break; } case ITEM_MA: { GetMoveArea_MA(item,moveArea); break; } case ITEM_XIANG: { GetMoveArea_XIANG(item,moveArea); break; } case ITEM_SHI: { GetMoveArea_SHI(item,moveArea); break; } case ITEM_SHUAI: { GetMoveArea_SHUAI(item,moveArea); break; } case ITEM_PAO: { GetMoveArea_PAO(item,moveArea); break; } case ITEM_BING: { GetMoveArea_BING(item,moveArea); break; } } }

 

 

比如对于棋子“马”,求可以走到的位置:

 

void MainWindow::GetMoveArea_MA( Item item,QVector& moveArea ) { //棋子“马”的计算可移动区域算法简介: //1,求出8个待选位置,8个位置的偏移是(-2,-1)(-2,1)(2,-1)(2,1)(1,-2)(1,2)(-1,-2)(-1,2)存在关系:|x|+|y|=3 //2,判断待选位置是否在棋盘内 //3,判断中间是否有卡位的棋子 //4,位置上是否已存在同色棋子 Item item2; for (int i = -2; i0) { ptDirect = QPoint(1,0); } else { ptDirect = QPoint(-1,0); } } else { if (j>0) { ptDirect = QPoint(0,1); } else { ptDirect = QPoint(0,-1); } } QPoint ptHit = item.m_pt + ptDirect; //马的卡位元素位置 if (FindItemAtPoint(ptHit,item2)) { //卡位 continue; } if (FindItemAtPoint(ptNew ,item2) && item.m_color == item2.m_color) { //有本组item continue; } moveArea.append(ptNew); } } } }

其它棋子类似,就是仔细处理下就OK了。

 

 

4,源码

 

源码已上传至群文件,可在学习群免费下载!

群号码:1149411109

群名称:Qt实战派学习群

 

 

 

 

 

 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


    图片新闻

    实验室药品柜的特性有哪些
    实验室药品柜是实验室家具的重要组成部分之一,主要
    小学科学实验中有哪些教学
    计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
    实验室各种仪器原理动图讲
    1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
    高中化学常见仪器及实验装
    1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
    微生物操作主要设备和器具
    今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
    浅谈通风柜使用基本常识
     众所周知,通风柜功能中最主要的就是排气功能。在

    专题文章

      CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭