C++ Easyx 三子棋
目录
思路
框架编辑
读取操作
数据操作
绘制画面
游戏的数据结构
用二维数组来模拟棋盘格
赢的情况
平局情况
Code
代码细节部分
(1)初始化棋盘格
(2) 初始化棋子类型编辑
事件处理部分
落子
框架内代码的完善
数据处理框架代码的完善
检查是否赢了 (函数)
绘制图形框架代码的完善
绘制棋盘网格(函数)
绘制棋子 (函数)
绘制提示信息 (函数)
DBUG
优化
代码托管
三子棋/Test.cpp · 孙鹏宇/孙鹏宇的第一个仓库 - 码云 - 开源中国 (gitee.com)
思路
我们遵循先框架,后思路得的思路
框架
首先是读取操作:
读取操作
读取鼠标单击之后的信息

接下来是数据操作:
数据操作
我们只需要对游戏胜负进行判断
胜的清空:一条线三颗棋子都一样
平的情况:棋格全部填满还未分出胜负。
游戏结束时使用弹出告诉玩家游戏结果,然后退出主循环。
绘制画面
我们使用line函数绘制一个3*3的棋盘格:


x玩家时使用line函数对角线画两个线,轮到O玩家落子时时使用cirlce函数画个圆:

游戏的数据结构
用二维数组来模拟棋盘格
棋盘内容为字符串,初始化为‘-'

赢的情况
我们对赢得情况进行穷举:
一共有八种
平局情况
如果9个网格均被棋子填满却没有获胜的一方,那么就是平局:
Code
写代码同样遵循先框架再细节的原则:
我们先把上面的内容转化为代码:
框架:
#include<easyx.h>
#include<iostream>
using namespace std;//处理数据// //检测玩家是否赢了
bool Checkwin(char str)
{}
//检测是否平局
bool Checkavg(char str)
{}//绘制图像
//
//绘制棋盘格
void DrawBorad()
{}
//绘制棋子
void DrawPiece()
{}
//绘制提示信息
void DrawTipText()
{}
int main()
{initgraph(60,600);//绘制窗口bool flag = true;//退出主循环的标识列ExMessage msg;//存储消息BeginBatchDraw();//渲染缓冲区//主循环while (flag){//读取操作while(peekmessage(&msg))//读取消息{//读取到的细节如何处理稍息再说}cleardevice();//清屏//重新绘图DrawBorad();DrawPiece();DrawTipText();FlushBatchDraw();//刷新缓冲区}EndBatchDraw();//刷新缓冲区return 0;
}
代码细节部分
如果 x玩家赢了,我们可以用MessageBox()函数弹出了一个框,显示x玩家赢了:

代码如下:
同样的,O玩家获胜的情况和平局的情况也写一下:

设置两个全局
(1)初始化棋盘格
(2) 初始化棋子类型
事件处理部分
用msg来表示鼠标的位置:
怎么把鼠标的位置映射到数组下标呢?我们绘制的棋盘格的大小为600x600,分成三等份之后每个格子的大小为200x200:
所以我们求横坐标可以有这样一个公式:
代码为:
落子
(1)首先判断是否可以落子
(2) 落完子之后要切换下次落子的棋子类型

框架内代码的完善
把之前只写了框架没写实现的函数补全:

数据处理框架代码的完善
检查是否赢了 (函数)
按照我们之前列的八种赢的情况写:
Checkavg()函数
用两个for循环来遍历棋盘格中每一个元素,如果还有空格没有落子就返回false代表没有平局,最后如果没有返回false说明平局了,返回true:

绘制图形框架代码的完善
绘制棋盘网格(函数)
棋盘格的网格其实就是四条线:
我们可以通过图形绘制相关函数->line()函数来绘制:

首先棋盘格总大小是600x600,每个小格子是200x200:


绘制棋子 (函数)
(1)绘制棋子,首先用二维数组遍历一下棋盘,如果要落的棋子是'O',那就在棋格中间画圆。
(2)棋盘中心的求法:一个小格子长宽200x200,中心坐标为左上角坐标+100:
(3)画圆的方法:
(4)当棋子为'x'时就按小格子对角线画两条线
(5)对角线点求法:如下图
(6)画对角线的方法:
(7)如果不是'O'或者',那就什么都不用做。
(8)代码:
绘制提示信息 (函数)
适用settextcolor()函数将提示文本设高亮:

outtextxy()函数用来在窗口指定位置输出提示信息:

code:
DBUG
这样三子棋基本功能就做好了,但是有bug:
(1)闪退
(2)闪退过程中可以看见我们画的棋盘,发现棋盘网格线条错位:
原因:
(1)绘制棋盘时手误
(2)闪退的原因是我们在判断是否平局用的else,没设条件,此刻没输值就直接平局了(只要不是'O',‘x’就直接平局了),这显示不是我们要的,我们想要的是棋盘满了还没赢才平局,因此我们应该引用checkagv()函数。

修改:
修改完之后运行:
发现有两个错误
(1)鼠标左键不用点击,就可以落子
(2)落子位置和我们鼠标落点位置不配置

鼠标左键不用点击,就可以落子的原因:
应该选择ExMessage的WM_LBUTTONDOWN表实列,我选成第一个了:
落子位置不配置的原因:
(1)切换棋子类型应该包含在可以落子的前提下,如果不能落子也就没必要切换棋子类型了:
修改之后:
(2)
二维数组是按照横纵坐标系的:
但是我们的窗口确是纵横坐标系:

错误:

修改:
交互功能正常,但是渲染功能有问题,最后一颗棋子不会显示:
原因:
我们把重新绘图放在判断胜负的后面,当玩家赢了的时候会执行flag=fale,此时会执行重新绘图。
当再次循环时,flag因为false,所以退出循环。也就是绘图只执行了一次,一闪而过。

我们把绘图放到胜负判断之前,这样即便是不再进入循环,也是最后一次落子的下一次绘图不会显示,而最后一次落子的绘图会显示在当前窗口。

正常运行:

优化
当我们的程序跑起来之后,查看任务管理器,发现我们的程序消耗内存空间特别大;
这是因为计算机在执行while循环时特别快,我们编写的主循环在顷刻间已经被执行了成千上万次。
因此,为了不避免的销毁,我们可以使用sleep()函数使循环休眠几毫秒。
我们可以在主循环开头写一个开始数获取GetTickCount(),主循环结束位置写一个结尾数获取GetTickCount()函数。
通过计算 二者落差 可以得到 该主循环实际运行所需要的 毫秒数,简称实需数。
如果我们想在60帧率下刷新,那么就让1000/60=16,16为我们的期望值。
如果 实需数 < 期望值,说明不用休眠。
否则,实需数-期望值= 休眠数。
代码托管
三子棋/Test.cpp · 孙鹏宇/孙鹏宇的第一个仓库 - 码云 - 开源中国 (gitee.com)
相关文章:
C++ Easyx 三子棋
目录 思路 框架编辑 读取操作 数据操作 绘制画面 游戏的数据结构 用二维数组来模拟棋盘格 赢的情况 平局情况 Code 代码细节部分 (1)初始化棋盘格 (2) 初始化棋子类型编辑 事件处理部分 落子 框架内代码的完善 数据处…...
[NAND Flash 2.1] NAND Flash 闪存改变了现代生活
依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 1989年NAND闪存面世了,它曾经且正在改变了我们的日常生活。 NAND 闪存发明之所以伟大,是因为,…...
2015年五一杯数学建模B题空气污染问题研究解题全过程文档及程序
2015年五一杯数学建模 B题 空气污染问题研究 原题再现 近十年来,我国 GDP 持续快速增长,但经济增长模式相对传统落后,对生态平衡和自然环境造成一定的破坏,空气污染的弊病日益突出,特别是日益加重的雾霾天气已经干扰…...
java面试题,上楼梯有多少种方式
java面试题,上楼梯有多少种方式 题目:一个小孩上一个N级台阶的楼梯,他可以一次走1阶、2阶或3阶,那么走完N阶有多少种方式。 很自然的想法是使用递归: public class Test04 { public static int countWays(int n) {…...
8.HTTP工作原理
HTTP是什么 HTTP工作原理 HTTP协议的请求类型和响应状态码 总结 1.HTTP是什么 HTTP超文本传输协议就是在一个网络中上传下载文件的一套规则 2.HTTP工作原理 HTTP超文本传输协议的本质是TCP通信,链接—>请求—>响应—>断开 3.HTTP协议的请求类型和响应状…...
环境部署的学习笔记(Docker)
1 前言 在现场测试时,常常需要在现场机器上搭建开发环境,此时使用容器会是一个比较方便的途径; 2 常见的容器技术 2.1 Docker⭐️31k:目前使用最为广泛的容器技术 2.2 Nix⭐️13.8k:镜像文件占用会比Docker少 Chat…...
Navicat在分辨率不同的屏幕窗口显示大小不一致问题解决
1.主屏幕为2560*1600分辨率,能够显示较多数据连接 2.在第二屏幕分辨率低,字体变大,显示内容变少 解决办法: 1.右击navicat图标-属性 2.选择【兼容性】-在兼容性页面中选择**“更改高DPI设置”** 3…勾选“高DPI缩放替代”&a…...
通过代码搞明白JAVA中值传递和引用传递
public static void main(String[] args) {Map a new HashMap();a.put("a", 1);System.out.println(a "我在main中的值");aaa(a);System.out.println(a "我在main中的值");bbb(a);System.out.println(a "我在main中的值");int b …...
ambari 开启hdfs回收站机制
hdfs回收站类似于我们常用的windows中的回收站,被删除的文件会被暂时存储于此,和回收站相关的参数有两个: fs.trash.interval:默认值为0 代表禁用回收站,其他值为回收站保存文件时间,单位为分钟 fs.trash…...
服务器数据恢复—服务器重装系统导致逻辑卷发生改变的数据恢复案例
服务器数据恢复环境: 某品牌linux操作系统服务器,服务器中有4块SAS接口硬盘组建一组raid5阵列。服务器中存放的数据有数据库、办公文档、代码文件等。 服务器故障&检测: 服务器在运行过程中突然瘫痪,管理员对服务器进行了重装…...
软件工程之架构设计
从公众号转载,关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、架构设计的目的 1.什么是复杂的软件项目 复杂的软件项目通常有两个特点: 需求不确定 技术复杂 技术的复杂性主要体现在四个方面…...
oracle java.sql.SQLException: Invalid column type: 1111
1.遇到的问题 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{propertyuuid, modeIN, javaTypeclass java.lang.String, jdbcTypenull, numericScalenull, r…...
Mac 浏览器下载的文件名总是「乱码」
如果可以实现记得点赞分享,谢谢老铁~ 本文所说的方法是在出现文件名乱码情况下,如何恢复文件名的正确中文名称,并非一劳永逸地避免乱码的出现。这是由于下载文件名称乱码的出现,往往是系统、浏览器、网站三方面因素共…...
Redis Reactor事件驱动模型源码
前置学习:Redis server启动源码-CSDN博客 1、Redis服务器启动的时候就会就一直在轮询。 // 运行事件处理器,一直到服务器关闭为止 aeSetBeforeSleepProc(server.el,beforeSleep); aeMain(server.el);// 服务器关闭,停止事件循环 aeDeleteEven…...
cv2.error: OpenCV(4.7.0)
运行hsv脚本报错: cv2.error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function cv::cvtColor 解决方案: 这个错误信息是在使用OpenCV的cvtColor函…...
10.vue3项目(十):spu管理页面的sku的新增和修改
目录 一、sku静态页面的搭建 1.思路分析 2.代码实现 3.效果展示...
Java LeetCode篇-深入了解二叉树经典解法(三种方式实现:获取二叉树的最大深度)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 对称二叉树 1.1 判断对称二叉树实现思路 1.2 代码实现:判断对称二叉树 2.0 二叉树的最大深度 2.1 使用递归实现获取二叉树的最大深度思路 2.2 代码实…...
Image Segmentation Using Deep Learning: A Survey
论文标题:Image Segmentation Using Deep Learning:A Survey作者:发表日期:阅读日期 :研究背景:scene understanding,medical image analysis, robotic perception, video surveillance, augmented reality, and image…...
可视化开源编辑器Swagger Editor本地部署并实现远程访问管理编辑文档
最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 文章目录 Swagger Editor本地接口文档公网远程访问1. 部署Swagge…...
Java TCP协议实现一对一聊天与UDP协议实现群聊案例
JavaTCP协议实现一对一聊天与UDP协议实现群聊案例 1.TCP协议实现一对一聊天 1.1服务端运行结果 1.2客服端运行结果 1.3代码汇总 服务端 package twentyone;import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...

