C++实现汉诺塔游戏自动完成

article/2025/7/20 7:55:09

目录

  • 一、汉诺塔的规则
  • 二、数学递归推导式
  • 三、步骤实现
    • (一)汉诺塔模型
    • (二)递归实现
    • (三)显示
      • 1.命令行显示
      • 2.SDL图形显示
  • 四、处理用户输入及SDL环境配置
  • 五、总结
  • 六、源码下载

一、汉诺塔的规则

游戏由3根柱子和若干大小不一的圆盘组成,初始状态下,所有的圆盘按照大小顺序从大到小堆叠在其中一根柱子上。将所有圆盘从初始柱子移动到目标柱子上即算完成目标。但须遵守以下规则:

  1. 每次只能移动1个圆盘.
  2. 圆盘可以放置在任何1根柱子上,但不能放在比它小的圆盘上.

比如3个盘子的汉诺塔,1个可能的解法是这样的:
在这里插入图片描述

二、数学递归推导式

一个脑筋急转弯:把大象关冰箱要几步?

只要3步!1.把冰箱打开,2.把大象装进去,3.把冰箱关上。看似简单的道理,其实蕴含着数学递归思维在其中。
从a柱向b柱移动n个盘子,同样采用的是递归思维在里面,将其定义f(a,b,n),则可以有如下推导式:
f(a,b,n) = f(a,c,n-1) + f(a,b,1) + f(c,b,n-1)

解释一下:

f(a,b,n)代表从a柱向b柱移动n个盘子的过程,则先将n-1个盘子从a移到中间柱c上,再将a柱最底下的大盘子移到b柱上,最后将c柱上的n-1个盘子移到b柱上。当然只要n不为1,就一直递归下去,直到最基础的移动1个盘子。
设g(n)代表这个过程的盘子移动次数,则g(n)= 2g(n-1)+1,由此可得g(n)= 2 n 2^n 2n-1。

三、步骤实现

使用SDL库实现了图形显示,若对SDL库不了解的请阅读如下2篇引文(同时也实现了命令行显示,不了解SDL库也不影响理解):

  • 如何在Linux平台使用SDL库进行2D/3D游戏开发
  • SDL开发实战(二):SDL2.0核心API解析

(一)汉诺塔模型

这里涉及的知识点包括:类的定义、SDL_Renderer渲染器也就是画布。

//汉诺塔柱子,简化盘子为正整数
class Stick {public:deque<int> plates; //柱子放置盘子的栈int x, y; //柱子底中心位置int width, height; //柱子宽、高unsigned char r, g, b; //柱子颜色int pside, pheight; //盘子边长、厚度unsigned char pr, pg, pb; //盘子颜色Stick(int x, int y, int width, int height, unsigned char r, unsigned char g, unsigned char b,int pside, int pheight, unsigned char pr, unsigned char pg, unsigned char pb); //构造函数void show(SDL_Renderer*); //在指定渲染器绘制画面
};//整个汉诺塔模型
class Hanoi {private:SDL_Renderer * render; // 内置窗口渲染器指针public:Stick sticks[3]; //3根柱子Hanoi(SDL_Renderer *, int); //构造函数bool movePlate(int a, int b); //将1个盘子从a柱移到b柱void movePlates(int a, int b, int count); //将count个盘子从a柱移到b柱void show(); //在窗口绘制画面
};

(二)递归实现

这里涉及的知识点包括:类外实现、函数递归调用、deque容器,其中movePlate函数是移动1个盘子的基本操作,而movePlates则是移动多个盘子的函数,它通过递归调用逐渐缩小盘子数量,直到最后剩1个盘子后调用基本操作函数。

bool Hanoi::movePlate(int a, int b) {int plateA, plateB; //2根柱子顶端的盘子plateA = this->sticks[a].plates.back();if (!this->sticks[b].plates.empty()) {plateB = this->sticks[b].plates.back();if (plateA > plateB) return false;}//小盘子可以放在大盘子上this->sticks[a].plates.pop_back();this->sticks[b].plates.push_back(plateA);this->show(); //显示return true;
}void Hanoi::movePlates(int a, int b, int count) {if (count == 1) {this->movePlate(a, b);return;}//求出中间柱(0,1,2) -> (1,2,3) ->(0,1,2)int c = ((a+1) ^ (b+1)) - 1;this->movePlates(a, c, count-1); //从a柱移count-1个盘子到c柱this->movePlate(a, b); //从a柱移最后1个盘子到b柱this->movePlates(c, b, count-1); //从c柱移count-1个盘子到b柱
}

(三)显示

分为2个显示模块,1个是Hanoi汉诺塔模型的显示函数,而它继续调用每根柱子的显示函数。

1.命令行显示

void Hanoi::show() {//逐根绘制for (int n = 0; n < 3; n++) {//画柱子和柱子上的盘子cout << "第" << n << "根柱:";  //命令行显示this->sticks[n].show();}cout << endl;// 命令行显示//显示SDL_Delay(1500); //1.5秒刷新
}void Stick::show() {//画盘子for (int i = 0; i < this->plates.size(); i++) {cout << this->plates.at(i) << " "; //命令行显示   }cout << ","; //命令行显示
}

以3层为例,显示结果如下:

第0根柱:3 2 1 ,第1根柱:,第2根柱:,
第0根柱:3 2 ,第1根柱:,第2根柱:1 ,
第0根柱:3 ,第1根柱:2 ,第2根柱:1 ,
第0根柱:3 ,第1根柱:2 1 ,第2根柱:,
第0根柱:,第1根柱:2 1 ,第2根柱:3 ,
第0根柱:1 ,第1根柱:2 ,第2根柱:3 ,
第0根柱:1 ,第1根柱:,第2根柱:3 2 ,
第0根柱:,第1根柱:,第2根柱:3 2 1 ,

2.SDL图形显示

在命令行显示基础上进行扩充:

void Hanoi::show() {//先用白色背景清屏SDL_SetRenderDrawColor(this->render, 255, 255, 255, 255);SDL_RenderClear(this->render);//逐根绘制for (int n = 0; n < 3; n++) {//画柱子和柱子上的盘子cout << "第" << n << "根柱:";  //命令行显示this->sticks[n].show(render);}cout << endl; // 命令行显示//显示SDL_RenderPresent(this->render);SDL_Delay(1500); //1.5秒刷新
}void Stick::show(SDL_Renderer * render) {//画柱子SDL_Rect rect = {x - width/2, y, width, height}; //x, y,宽、高SDL_SetRenderDrawColor(render, r, g, b, 255); //不透明SDL_RenderFillRect(render, &rect);//画盘子for (int i = 0; i < this->plates.size(); i++) {cout << this->plates.at(i) << " "; //命令行显示int px = this->x - this->plates.at(i) * this->pside / 2; //盘子左边沿,盘子单位长为20int py = 600 - (i + 1) * this->pheight; //窗口高600,盘子上边沿,盘子单位厚度为10SDL_Rect rect = {px, py, this->plates.at(i)*this->pside, this->pheight}; //盘子坐标(px, py)、边长、厚//填色SDL_SetRenderDrawColor(render, this->pr, this->pg, this->pb, 255); //盘子为天蓝色,不透明SDL_RenderFillRect(render, &rect);//画黑色边框SDL_SetRenderDrawColor(render, 0, 0, 0, 255); SDL_RenderDrawRect(render, &rect);}cout << ","; //命令行显示
}

四、处理用户输入及SDL环境配置

放置在main函数中,最后显示出来就是文章开头展示的动图了。

    int n; //汉诺塔层数cout << "请输入汉诺塔层数:" << flush;cin >> n;//初始化SDL成视频模式SDL_Init(SDL_INIT_VIDEO);//初始化窗口,标题为汉诺塔,位置(x,y)默认,尺寸800X600,窗口为显示模式SDL_Window *window = SDL_CreateWindow("汉诺塔", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN);if (!window) {cout << "窗口生成异常" << endl;return 1;}//初始化窗口渲染器,相当于画布,-1表示默认的渲染设备,使用软件渲染SDL_Renderer *render = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);if (!render) {cout << "渲染器生成异常" << endl;return 1;}//初始化汉诺塔Hanoi hanoi(render, n);hanoi.show(); //修复刚启动黑屏bughanoi.show();hanoi.movePlates(0, 2, n);SDL_DestroyRenderer(render);SDL_DestroyWindow(window);SDL_Quit();

五、总结

本篇文章摘记了使用C++语言实现汉诺塔游戏电脑自动完成的步骤,还没有实现用户交互,无多少可玩性,仅抛砖引玉,希望大家有所收获,如有好的建议欢迎留言,谢谢大家!

六、源码下载

C++语言实现汉诺塔自动完成


http://www.hkcw.cn/article/MiFyRFeWUb.shtml

相关文章

抖音评论数据采集解决方案推荐

内容概要 在当今数字化营销的背景下&#xff0c;抖音作为一款广受欢迎的短视频平台&#xff0c;吸引了众多用户和企业的关注。为了更好地理解用户反馈和优化营销策略&#xff0c;评论数据的采集显得尤为重要。本文将为读者提供一系列系统化的解决方案&#xff0c;涵盖多款高效…

若依框架-代码生成器的使用

1.服务启动 注意一定要启动Gen\GateWay\System 2.创建表 注意一定要写上字段的注释和表的注释。 1.注意主键的命名 2.注意驼峰命名法 3.代码生成 3.1 按照以下箭头步骤&#xff0c;选择生成的表&#xff0c;点击确定 3.2 核对生成表的结构 3.3 编辑生成表的基础信息 3.4 点…

河南46岁卡车司机已下葬 卡友团队千里送别

近日,46岁的河南卡车司机常志荣在青藏高原离世,卡友团队一同将其骨灰接回老家。6月1日,常志荣已经在老家安葬。他去世后留下了重组家庭的6个孩子,其中5个孩子还在上学。车友任先生透露,常志荣出发前同行曾建议他至少携带两罐氧气,但他为了省下30元费用,最终只购买了一罐…

交警回应豪车车主赖停车费被举报酒驾 代驾小哥报警揭发真相

近日,浙江宁波一名兰博基尼车主酒后请代驾将车开到小区,随后自己开车进车库。因不愿支付代驾小哥垫付的5元停车费,被对方举报酒驾。经检测,该车主血液中的酒精含量达59mg/100ml,达到酒驾标准,其驾驶证被扣12分,暂扣6个月,并被处以2000元以下罚款。代驾小哥石先生表示,…

Nat. Commun|借助深度学习分层方法,量化胎盘组织学全切片图像中细胞和显微解剖组织结构的变异性

小罗碎碎念 这篇文章提出了用于胎盘组织学全切片图像分析的深度学习框架HAPPY&#xff0c;其核心是通过三阶段流水线实现从细胞到组织结构的层次化建模。 首先利用RetinaNet定位细胞核。 再通过ResNet-50分类11种细胞类型 最后基于ClusterGCN图神经网络将细胞聚合成9类显微组织…

融智学道函数智慧系统研习(图文并茂)

融智学道函数智慧系统研习&#xff08;图文并茂&#xff09; 融智学创立者邹晓辉亲自设计和审订并规划布局人机互助制作全过程 摘要&#xff1a;本文呈现邹晓辉融智学理论的核心架构&#xff0c;包含四大公式可视化系统&#xff1a;1&#xff09;道函数&#xff08;f_Tao0&am…

小米YU7将推出5款全新车身颜色 更多经典配色即将揭晓

6月1日的消息显示,在5月22日的发布会上,小米YU7公布了四款颜色:钛金属色、宝石绿、熔岩橙和寒武岩灰。官方透露,除了已发布的四款颜色外,还有五款新颜色即将发布。回顾小米SU7刚推出时,提供了9种颜色选择,分为跑车色系、时尚色系、豪华色系和经典色系。基础款中的海湾蓝…

国足出征印尼25人大名单 刘若钒因伤落选

北京时间6月2日,中国男足公布了出征印度尼西亚雅加达的25人名单。刘若钒因伤落选,他在国足上海集训期间受到伤病困扰,缺席了数次合练。尽管恢复了有球训练,但最终未能进入出征印尼的名单。谢文能和林良铭将在对阵印度尼西亚的比赛里停赛。不过,两人还是会随队前往雅加达,…

国防大学副校长香会发言释放何信号 坚定维护亚太和平稳定

今年在新加坡举行的香格里拉对话会上,最重要的发言来自中国国防大学代表团团长、国防大学副校长兼教育长胡钢锋少将。他提出了“三个坚持三个反对”的倡议,这不仅反映了中国对亚太地区海上安全合作的看法,也展示了中国维护和平与稳定的决心。当地时间5月31日下午,胡钢锋在香…

尾号0000000的手机号拍出61.2万元 司法拍卖市场火热

端午节期间,司法拍卖市场异常活跃。6月1日,一个尾号为七个零的手机号码使用权以25万元起拍,吸引了13人报名参与竞拍。经过激烈竞争,该号码最终以61.2万元成交。据竞买公告显示,截至2025年4月23日,该手机号码无欠费,余额约9.14元。套餐为4G全国流量王8元套餐,未绑定宽带…

上位机系统 设备初始化Load界面开发

效果 设备加载完后打开主界面 思路 1.创建一个 SplashWindow.xaml 就是上面效果图,主要是显示系统名称和正在加载的信息,进度条。 2.在 SplashWindow 的后台执行加载代码。 3.最后打开主界面 为什么要写这片文章,以前的项目也有这个界面但实现都很复杂,用到了线程间的数…

SQL Relational Algebra(数据库关系代数)

目录 What is an “Algebra” What is Relational Algebra? Core Relational Algebra Selection Projection Extended Projection Product&#xff08;笛卡尔积&#xff09; Theta-Join Natural Join Renaming Building Complex Expressions Sequences of Assignm…

董宇辉龙舟夺冠又赢鸭 传统文化焕发新活力

5月31日,陕西安康迎来了第25届汉江龙舟节的开幕。开幕式上,龙舟方阵展演、龙舟横渡汉江以及抢鸭子、摸鲤鱼等传统环节轮番上演,节日氛围浓厚。据了解,今年有27支队伍共600多名选手参加了龙舟竞渡比赛。当天,董宇辉现身安康龙舟文化园,与现场市民和游客热情互动,并齐声高…

为何大巴黎没了姆巴佩进球反而更多 全攻全守战术奏效

巴黎圣日耳曼夺得队史第一座欧冠冠军奖杯,超级巨星姆巴佩在社交账号上向老东家表示祝贺:“伟大的日子终于来临,这场胜利是属于整个俱乐部的荣光,恭喜巴黎圣日耳曼!”过去六个赛季,姆巴佩以大巴黎当家球星的身份夺得法甲金靴奖。他去年夏天从大巴黎加盟上赛季欧冠冠军皇家…

俄称击落162架乌军无人机 俄军持续攻势

当地时间5月30日,俄罗斯国防部发布战报称,在过去一周里,俄军对乌克兰境内的国防工业设施、军用机场基础设施、武器弹药储存设施等目标实施了打击。在苏梅、哈尔科夫、顿涅茨克等地,俄军打退了乌军多次进攻并发动攻势。俄防空部队击落了1439架固定翼无人机,并控制了苏梅、哈…

印度游客摸老虎屁股时遭扑咬 现场惊魂一幕

泰国普吉岛知名观光景点“老虎王国”近日发生一起惊险事件。一名印度游客在与老虎合影时,因触摸老虎遭到攻击,现场画面在社交媒体上引发广泛关注。该景点以“一生仅有一次的与虎互动体验”为卖点,吸引众多游客前往。事发时,这名游客手持链条与老虎并排站立,驯兽师正用棍棒…

C#实现远程锁屏

前言 这是一次提前下班没有锁屏进而引发的一次思考后的产物&#xff0c;思考的主要场景是当人离开电脑后&#xff0c;怎么能控制电脑锁屏&#xff0c;避免屏幕上的聊天记录被曝光。 首先想到通过系统的电源计划设置闲置超时时间熄屏&#xff0c;这可能是最接近场景的解决方案&a…

重读《人件》Peopleware -(15)Ⅱ 办公环境 Ⅷ 撑伞之步:构建理想办公环境(上)

在本章中&#xff0c;我们将探讨理想办公环境的特点&#xff0c;并尝试回答以下问题&#xff1a; 什么样的空间能最好地让员工感到舒适、快乐和高效&#xff1f; 什么样的工作空间能让员工对自己的工作感到最满意&#xff1f; 如果你在一个典型的嘈杂且单调的企业环境中工作…

兰博基尼车主赖停车费被代驾举报酒驾 5元引发的酒驾案

近日,浙江宁波一名兰博基尼车主酒后请代驾将车开到小区,随后自己开车进车库。因不愿支付代驾小哥垫付的5元停车费,被对方举报酒驾。经检测,该车主血液中的酒精含量达59mg/100ml,达到酒驾标准,其驾驶证被扣12分,暂扣6个月,并被处以2000元以下罚款。事发当晚11时30分许,…

乌总统称亲自筹划蛛网行动一年半 精心策划载入史册

乌克兰在与俄罗斯举行第二轮谈判前夕,发动了“蛛网”行动,袭击了俄罗斯多地。据报道,此次行动中的无人机是通过货柜车偷运进入俄方领土的。乌克兰总统泽连斯基表示,准备工作超过一年半,并且经过精心策划。他赞扬此次行动堪称精彩,并形容乌军此次行动“无疑将载入史册”。…