分析

在鼠标左键点击时,我们不能让新棋子在已有棋子的位置落下,同时我们还要让棋子在规定位置落下——棋盘线的交点处。

功能实现

创建数据类型

  • 创建头文件chessData.h和源文件chessData.cpp
  • chessData.cppmain.cpp分别引用头文件chessData.h
#include "chessData.h"
  • 将之前在main.cpp中写的棋盘数据剪贴chessData.h
const float BLOCKSIZE = 67.4;
const int BLOCK_GRAD_SIZE = 13;
  • chessData.h中定义常量 POS_OFFSET,即鼠标有效点击距离上限
const int POS_OFFSET = BLOCKSIZE * 0.4;
  • chessData.h定义结构体 ChessData
struct ChessData{
//储存当前游戏棋盘的情况,空白为0,黑棋为1,白棋为-1
int chessMap[BLOCK_GRAD_SIZE][BLOCK_GRAD_SIZE];
//储存各点的评分情况,用于之后的AI走棋
int scoreMap[BLOCK_GRAD_SIZE][BLOCK_GRAD_SIZE]; bool playFlag; //表示下棋放,true黑棋,false白棋(AI) };
  • main.cpp中添加全局变量game
ChessData game;

初始化数据类型

  • chessData.h中添加函数声明
void initChessData(ChessData*);
  • chessData.cpp
void initChessData(ChessData *data){
if(!data) return;
memset(data->chessMap,0,sizeof(data->chessMap));
memset(data->scoreMap,0,sizeof(data->scoreMap));
data->playFlag = true; }

判断有效点击

算法原理

实现

  • main.cpp中添加全局变量
int clickPosRow, clickPosCol;    //用于储存点击位置
  • 定义函数clickBoard()
//有效点击返回true,无效点击返回false
//MOUSEMSG为鼠标信息类型
bool clickBoard(MOUSEMSG msg){ //(鼠标点击坐标 - 边界长度)/ 格宽 = 行(列)数 //计算列数并取整
int col = (msg.x - MARGIN_X) / BLOCKSIZE;
//计算行数取整
int row = (msg.y - MARGIN_Y) / BLOCKSIZE; //计算棋子正确坐标,即格子左上角棋子应在的棋盘格线交点处坐标
int leftTopPosX = MARGIN_X + BLOCKSIZE * col;
int leftTopPosY = MARGIN_Y + BLOCKSIZE * row; }
  • 在文件最上方引用头文件math.h用于后期计算
#include <math.h>
  • 之后要判断棋子应在四个交点中具体哪一点上,这里我们用一个do-while循环。继续添加clickBoard()函数的定义
int len; //用于计算两点见的距离(根据中学所学两点间距离公式)
int selectPos = false; //作为返回值 do{
//左上角
len = sqrt((msg.x - leftTopPosX)*(msg.x - leftTopPosX) + (y - leftTopPosY)*(msg.y - leftTopPosY));
if(len < POS_OFFSET){
clickPosRow = row;
clickPosCol = col;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
} //右上角
len = sqrt((msg.x - leftTopPosX - BLOCKSIZE)*(msg.x - leftTopPosX - BLOCKSIZE) + (y - leftTopPosY)*(msg.y - leftTopPosY));
if(len < POS_OFFSET){
clickPosRow = row;
clickPosCol = col + 1;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
} //左下角
len = sqrt((msg.x - leftTopPosX)*(msg.x - leftTopPosX) + (y - leftTopPosY - BLOCKSIZE)*(msg.y - leftTopPosY - BLOCKSIZE));
if(len < POS_OFFSET){
clickPosRow = row + 1;
clickPosCol = col;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
} //右下角 len = sqrt((msg.x - leftTopPosX - BLOCKSIZE)*(msg.x - leftTopPosX - BLOCKSIZE) + (y - leftTopPosY - BLOCKSIZE)*(msg.y - leftTopPosY - BLOCKSIZE));
if(len < POS_OFFSET){
clickPosRow = row + 1;
clickPosCol = col + 1;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
} }while(0); return selectPos;

更新底层数据

  • chessData.h
void updateGameMap(ChessData* data, int row, int col);
  • chessData.cpp
void updateGameMap(ChessData* data, int row, int col){
if(!data) return; if(data->playFlag){
data->chessMap[row][col] = 1;
}else{
data->chessMap[row][col] = -1;
} data->playFlag = !data->playFlag; //换下棋方 }
  • main.cpp
//玩家走棋
void manGo(){
chessDown(clickPosRow,clickPosCol,CHESS_BLACK);
updateGameMap(&game, clickPosRow, clickPosCol); }

C++五子棋(三)——判断鼠标有效点击的更多相关文章

  1. unity3D基础学习 通过判断鼠标点击的是否是目标物体,物体旋转,滑动滚轮缩放拉近视角

    贴代码: 摄像机的拉近视角代码: public Transform target;     public float minFov = 15f;     public float maxFov = 7 ...

  2. GDI画图,判断鼠标点击点在某一画好的多边形、矩形、图形里

    Region.IsVisible方法 简单方便准确 private bool CheckPntInPoly(Point[] points, Point pnt) { || pnt == Point.E ...

  3. js 如何判断鼠标点击事件还是js代码调用

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  4. 精通Web Analytics 2.0 (5) 第三章:点击流分析的奇妙世界:指标

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第三章:点击流分析的奇妙世界:指标 新的Web Analytics 2.0心态:搞定它.新的闪亮系列工具:是的.准备好了吗?当然 ...

  5. C#之在treeview中鼠标点击的所选的节点触发事件

    一.背景 如下图所示,我想实现通过鼠标点击treeview的根节点,然后在文本框控件中显示鼠标点击的节点号. 二.程序实现 因为是要通过鼠标点击才发生的事情,所以这属于一个事件,需要触发才行,刚开始不 ...

  6. 【Unity3D】简单常用的功能实现1——鼠标点击实现移动

    [鼠标点击实现移动] 第一步,在要移动的GameObject的Inspector面板中添加角色控制器组件并调整参数. 参数的调整可以依照Scene面板,如下图的绿色线框(角色控制器组件是一种胶囊形状的 ...

  7. JS判断鼠标进入容器方向的方法和分析window.open新窗口被拦截的问题

    1.鼠标进入容器方向的判定 判断鼠标从哪个方向进入元素容器是一个经常碰到的问题,如何来判断呢?首先想到的是:获取鼠标的位置,然后经过一大堆的if..else逻辑来确定.这样的做法比较繁琐,下面介绍两种 ...

  8. JS判断鼠标移入元素的方向

    最终效果 这里的关键主要是判断鼠标是从哪个方向进入和离开的 $("li").on("mouseenter mouseleave",function(e) { v ...

  9. Matlab判断鼠标移动

    set(gcf,'WindowButtonMotionFcn',@get_cur_positon); 其中第二项是判断鼠标移动的属性参数,第三项为回调函数 et. main.m clear;clc;s ...

随机推荐

  1. IDW插值得到降水量分布图

    4 具体思路 4.1 加载数据 (1)点击[添加数据],选择"中国地面气候资料国际交换站数据集台站信息.csv"."省份.shp"和"2011年中国地 ...

  2. Java 程序性能问题

    ● 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步 ...

  3. STM32控制永磁同步电机 | FOC电机控制算法概述

    1. FOC基本概念 参考:https://www.sohu.com/a/432103720_120929980 FOC(field-oriented control)为磁场导向控制,又称为矢量控制( ...

  4. [Java编程思想] 第七章 复用类

    第七章 复用类 第一种方法非常直观:只需在新的类中产生现有类的对象(组合). 第二种方法更细致一些:它按照现有类的类型来创建新类(继承). 7.1 组合语法   只需将对象引用置于新类中即可. cla ...

  5. 什么是Spring的依赖注入?

    依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释.这概念是说你不用创建对象,而只需要描述它如何被创建.你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个 ...

  6. uWSGI+django+nginx的工作原理流程与部署

    二.必要的前提 2.1 准备知识 django 一个基于python的开源web框架,请确保自己熟悉它的框架目录结构. uWSGI 一个基于自有的uwsgi协议.wsgi协议和http服务协议的web ...

  7. 解释 MySQL 外连接、内连接与自连接的区别 ?

    先说什么是交叉连接: 交叉连接又叫笛卡尔积,它是指不使用任何条件,直接将一 个表的所有记录和另一个表中的所有记录一一匹配. 内连接 则是只有条件的交叉连接,根据某个条件筛选出符合条件的记录,不符合 条 ...

  8. Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法 ?

    1.关闭缓存 swap; 2.堆内存设置为:Min(节点内存/2, 32GB); 3.设置最大文件句柄数: 4.线程池+队列大小根据业务需要做调整: 5.磁盘存储 raid 方式--存储有条件使用 R ...

  9. 学习Squid(二)

    第6章 squid代理模式案例 6.1 squid传统正向代理生产使用案例 6.1.1 squid传统正向代理两种方案 (1)普通代理服务器 作为代理服务器,这是SQUID的最基本功能:通过在squi ...

  10. c++中的左值和右值的理解

    1.左值和右值的概念 C++中左值(lvalue)和右值(rvalue)是比较基础的概念,虽然平常几乎用不到,但C++11之后变得十分重要,它是理解 move/forward 等新语义的基础. 左值与 ...