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

C++——汉诺塔 题目描述 汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子a上,从下往上按照大小顺序摞着n片黄金圆盘。 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子c上,移动过程中可以借助b柱。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。 **问:**如何用最少的步数实现n个盘子的移动?请输出具体的移动方案。 输入格式 一行一个正整数n, 1≤n≤18 1≤n≤18 阅读详情

一、汉诺塔的规则

游戏由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库也不影响理解):

(一)汉诺塔模型

这里涉及的知识点包括:类的定义、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; //盘子左边沿,盘子单位长为20
        int py = 600 - (i + 1) * this->pheight; //窗口高600,盘子上边沿,盘子单位厚度为10
        SDL_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(); //修复刚启动黑屏bug
    hanoi.show();
    hanoi.movePlates(0, 2, n);

    SDL_DestroyRenderer(render);
    SDL_DestroyWindow(window);
    SDL_Quit();

五、总结

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

六、源码下载

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

【C++算法】汉诺塔问题 汉诺塔是非常经典的递归问题,我们先考虑只有三个盘子的情况,现在有ABC三个柱子,A上有三个盘子,我们要把A上的三个盘子移动到B上,那么就可以先把A上的一个盘子移动到B上,再把A上的一个盘子移动到C上,然后把B上的一个盘子移动到C上,然后把A上的一个盘子移动到B上,然后把C上的一个盘子移动到A上,然后把C上的一个盘子移动到B上,然后把A上的一个盘子移动到B上。汉诺塔编程,设 a,b,c 是 3 个塔座。开始时,在塔座 a 上有⼀叠共 n 个圆 盘,这些圆盘⾃下⽽上,由⼤到⼩地叠在⼀起。 阅读详情

相关推荐

汉诺塔问题C++语言

设有A、B、C三个塔座,在塔座A上有n个圆盘,这些圆盘自上而下由小到大的叠在一起。把n个盘子分解为n和n-1个盘子,所以必须先解决n-1个盘子的移动问题;依次类推,最后分解为一个盘子的移动问题,汉诺塔问题自然就解决了。②不能将较大的圆盘压在较小的圆盘之上;③移动中可以使用A、B、C任意一塔座。①每次只能移动一个圆盘;

ENIAC1024的博客 1910

汉诺塔(c++)

通常说,递归思想可以高效简单的解决问题,递归函数的关键就是将大问题拆分成小问题,汉诺塔就是将A柱子3个圆盘移动到C柱子上,想要移动,必须要借用B柱子。实现方法就是,将n-1 个圆盘由A柱子通过c移动到B柱子Hanoi(n-1,A,C,B),将A柱最下边的一个圆盘移动到c柱子cout

m0_73820126的博客 4287

汉诺塔游戏-----用C++编的

昨天没事在用别人的文曲星查字!突然看到那个汉诺塔游戏.....反正这两天刚好手有点痒,于是就有了: #ifndef  HANIO_H_#define HANIO_Hclass  Stack{private: enum{ MAX=50 }; int m_node[MAX]; int m_top;      int m_size; int m_index;  public: Stack(); 

GAME-LAB(游戏开发,微信公众号:fury-programer) 2702

c++实现汉诺塔(图文并茂)

手把手教你c++解决汉诺塔问题

lijingheng66的博客 8011

【递归类】C,C++写汉诺塔问题算法

汉诺塔问题是一个经典的递归算法问题,源于印度的一个古老传说。问题的目标是将一组大小不同的圆盘从一个柱子移动到另一个柱子,遵循特定的规则:每次只能移动一个盘子,且不能将大盘子放在小盘子上面。通过对汉诺塔问题的深入理解,学习者可以更好地掌握递归算法的思想,并在实际编程中应用这些概念。

Oo1101oO的博客 2472

C++实现的汉诺塔算法解析

汉诺塔(Hanoi Tower)游戏是计算机科学和数学领域中的一个经典问题,它源于印度的一个古老传说。相传有三根柱子和一些大小不一的圆盘,一开始这些圆盘按照大小顺序摞在一根柱子上,目标是通过最少的移动次数将它们全部移动到另一根柱子上,移动过程中必须遵守以下规则:每次只能移动一个圆盘。圆盘只能从塔顶取下并放置在另一根柱子的塔顶上。圆盘移动过程中不能被放在较小的圆盘上面。在计算机科学领域,汉诺塔问题不仅是递归算法教学的典型示例,而且它与数据结构如栈的操作密切相关。

weixin_35756690的博客 1151

汉诺塔游戏的设计

 汉诺塔游戏的设计 作者:苍竹先生 下载源代码 汉诺塔问题是最经典的递归问题,笔者就该问题设计了这个游戏,由用户交互游戏和自动演示两部分组成,支持撤销功能、选关、自动完成等功能。 首先建立了类CMap,该类主要实现用户每一步的操作和画图显示功能,记录的时候只须记录每组盘子的个数和盘子的矩形。代码和注释如下

ronin技术空间 802

C++程序设计:汉诺塔算法解析与实现

递归是一种在解决问题时,可以自我调用的方法。它是程序设计语言中一种非常重要的编程技巧,尤其适用于解决可以分解为相似子问题的任务。递归算法通过一个或多个简单的基本情况来结束递归调用,并且在这些基本情况之间建立一个递归关系,这个关系指导着算法如何从子问题的解构建当前问题的解。hanoiTower。

weixin_35757531的博客 1257

汉诺塔问题c++递归解法

​汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 摘自百度百科 相信大家很多都玩过或者听说过汉诺塔,下面我来举个例子:(当圆盘数为3时) 目标:将所有圆盘移动至2号杆(第2根杆子) 第一步:将黄色圆盘移动至2号杆上 ...

fangyxp的博客 1万+

MFC图形化汉诺塔游戏实现

汉诺塔问题是一个经典的递归问题,以其简单易懂的规则和复杂多变的解决方案闻名。问题的核心是将一系列大小不一的盘子从一个塔座移动到另一个塔座上,过程中遵守特定的规则:一次只能移动一个盘子,并且大盘子不能叠在小盘子上面。递归算法在解决汉诺塔问题时提供了一种优雅的解决方案,它将复杂问题分解为更小规模的相同问题,直到达到简单的情况可以轻松解决。MFC类库的发展与Visual C++的进化紧密相连。

weixin_30533301的博客 999

百度飞桨+文心大模型实战:生成式AI工程师认证备考全攻略(含真题解析)

本文详细解析百度飞桨与文心大模型结合的生成式AI工程师认证备考策略,涵盖认证体系、学习路径、核心技能突破及真题分析。帮助开发者掌握大模型原理、飞桨平台操作和文心大模型应用,高效通过工信部与百度联合认证考试。

loss4bartender的博客 682

汉诺塔游戏设计(C++控制台版)

汉诺塔游戏设计(C++控制台版) Hello! 小伙伴们。这次给大家带来小生的游戏作品——汉诺塔游戏。由于这是本人第一次设计游戏,可能某些地方存在问题,希望各位大佬能够批评指正,在这里,也感谢各位家仁们阅读此文章。 游戏简介 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一...

SkyBlue_Jame的博客 3041

TexGen模型导出到ABAQUS的inp文件:如何快速修改纱线材料属性(避坑指南)

本文针对TexGen模型导出到ABAQUS的inp文件后纱线材料属性缺失或错误的问题,提供了高效的解决方案。文章详细解析了inp文件结构,指导用户如何手动定位并修改纱线材料属性,并提供了可批量处理的Python脚本,帮助用户快速、精准地完成材料参数赋值,有效提升复合材料仿真工作效率。

ice55的博客 602

C++汉诺塔游戏

【问题描述】 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 【问题分析】 汉诺塔用递归理解较为简单,在理解时,不要局限常规,最好把三根柱子围成一个正三角形理解...

欢迎来到我的世界 4079

OpenClaw与Ollama本地AI部署指南

AI模型本地化部署是当前企业数字化转型的关键技术,通过开源框架Ollama可以在消费级硬件上运行大语言模型。本文以OpenClaw多智能体系统为例,详解从环境配置到模型优化的全流程实践,特别针对国内开发者遇到的网络问题提供了镜像加速等解决方案。这种私有化部署方案尤其适合金融数据分析、企业知识管理等对数据安全要求高的场景,通过模块化设计实现多智能体协作,同时保持对NVIDIA显卡和普通CPU的兼容性。

weixin_34302561的博客 397

人工智能之语言领域 自然语言处理 第六章 情感分析

情感分析(Sentiment Analysis),又称意见挖掘(Opinion Mining),旨在自动识别和提取文本中表达的主观情感、态度或情绪。从用户评论到社交媒体,从产品反馈到政治舆情,情感分析已成为企业决策、品牌监控和人机交互的关键技术。本章将深入介绍情感分析的层级结构、核心技术、主流模型,并通过社交媒体舆情实战案例完整演示分析与可视化流程。层级目标示例词级(Word-level)判断单个词的情感倾向“好” → 正面;“差” → 负面句级(Sentence-level)判断整个句子的情感极性。

咚咚王者的博客 856

汉诺塔游戏

汉诺塔游戏 汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。 如何解决汉诺塔问题? 要想玩转汉诺塔,需要先理解递归。 如果一个问题可以不断地分解为类型相同,规模更小的子问题,并且有明确...

Shishishi888的博客 1704

哈希拓展攻击CTF题做法

kali下载相关工具hash-ext-attack:hash拓展题目特征:2023楚慧杯upload_shell实验吧之让我进去:前言:具体怎么加密解密补位的原理我不懂,深入理解的部分我在文末挂了链接,以下也只是我做题的结论和通解,可能不准确(但是做题还挺准确),有错误欢迎指出:是在密码加密过程中引入的一个随机值,它与密码结合使用,目的是增加密码的复杂性和安全性。在密码加密中,常见的做法是将用户提供的密码进行哈希处理,然后存储哈希值而不是明文密码

2301_76690905的博客 2419

汉诺塔游戏的图形化实现——C++实现

汉诺塔游戏的图形化实现

ctz6d1p的博客 895

Zotero+Obsidian+Bookxnote联动让文献阅读丝滑般体验

摘录文字或图片到Obsidian

weixin_43694742的博客 1万+

手把手教你用键盘在Ubuntu上给Lerobot机械臂采集HIL-SERL训练数据(附完整配置文件)

本文详细介绍了在Ubuntu系统中使用键盘控制Lerobot机械臂进行HIL-SERL训练数据采集的完整流程。从环境准备、机械臂校准到键盘遥操系统配置和数据采集优化,提供了实战指南和常见问题解决方案,帮助读者高效获取高质量训练数据,推动具身智能和强化学习应用的发展。

weixin_30733003的博客 479

汉诺塔C++代码

一个简单的汉诺塔游戏代码,很简单,不过挺有意思 #include "stdafx.h" #include<iostream> using namespace std; class hanio //定义一个类 { public : ~hanio(){} //析构函数 void han(int n,char a,char b,char c) { ...

weixin_39106536的博客 3041

华为OD技术面八股_C++_05

汇总华为OD技术面C++方向技术面八股文,提供详细解答。

qq_45776114的博客 413

来玩汉诺塔游戏

目录汉诺塔游戏用C++来实现游戏 汉诺塔游戏 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。**游戏规则:**在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 图片来源于网络 用C++来实现游戏 ①、将A柱子移动到C柱子上,首先需要计算起始A柱子上的盘子个数,如第一步。 ②、将A柱子上的盘子移动到B柱子上,以C柱子

weixin_44585751的博客 299

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C++实现汉诺塔游戏用户交互

本文介绍了基于C++和SDL库的汉诺塔游戏交互功能实现方法。主要内容包括:1) 模型调整,定义Stick类和Hanoi类,使用静态变量和构造函数初始化参数;2) 实现电脑自动完成汉诺塔步骤,显示移动过程和手指状态;3) 通过SDL事件捕获响应方向键操作,包括拿起/放下盘子(UP/DOWN键)和左右移动手指(LEFT/RIGHT键);4) 图形界面显示优化,支持设置刷新频率。该实现让玩家可以通过键盘交互操作汉诺塔游戏,提升了游戏的可玩性。

hele_two的专栏 531

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: C++实现伽罗华域生成及四则运算(二)
下一篇: C++实现伽罗华域生成及四则运算(三)
hele_two
博客等级 码龄14年 141粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值