C语言——海龟作图(对之前所有内容复习)

一.问题描述

海龟作图

     设想有一只机械海龟,他在C程序控制下在屋里四处爬行。海龟拿了一只笔,这支笔或者朝上,或者朝下。当笔朝下时,海龟用笔画下自己的移动轨迹;当笔朝上时,海龟在移动过程中什么也不画。

      使用一个50*50的数组floor,用于记录海龟绘制的图形,数组元素初始化为0在海龟爬行过程中,如果笔朝下,就把数组floor中对应于海龟所处位置的元素置为1。当给出命令6(打印命令)后,数组中元素为1的位置全部用星号显示,元素为0的位置全部用空格显示。

      海龟会从一个装有命令的数组中读取各种命令。

      假定海龟总是从地板上(0,0)出发,并且开始时笔是朝上的。

首先我们逐个分析:

二.问题解决

1. 头文件与宏定义

#include <stdio.h>// 定义命令数组大小和图形数组大小
#define COMMANDSIZE 100
#define PICSIZE 50
  • #include <stdio.h>:引入标准输入输出库,用于实现基本的输入输出功能,如printfscanf函数。
  • COMMANDSIZE:定义了存储用户输入命令的数组的大小,用于限制可接收的命令数量。
  • PICSIZE:确定了用于记录海龟绘制图形的二维数组的行数和列数,这里设定为 50 * 50 的矩阵。

2. 函数声明

void getCommand(int commands[], int size);
void draw(int commands[], int size, int floor[][PICSIZE], int rows, int cols);
void printArray(int a[][PICSIZE], int rows, int cols);
  • 这三个函数分别负责获取用户输入的命令、根据命令控制海龟作图以及将绘制的图形以可视化形式打印出来。
  • 函数声明告诉编译器这些函数的存在及其参数类型和返回值类型,使得在main函数中调用这些函数时编译器能够识别。

3. main函数

int main(void) {int commands[COMMANDSIZE];  // 存储命令int floor[PICSIZE][PICSIZE] = { 0 };  // 存储图片getCommand(commands, COMMANDSIZE);  // 获取命令draw(commands, COMMANDSIZE, floor, PICSIZE, PICSIZE);  // 作图return 0;
}
  • main函数中,首先定义了两个数组:
    • commands数组用于存储用户输入的命令,其大小由COMMANDSIZE决定。
    • floor二维数组用于记录海龟绘制的图形,初始化为全 0,表示初始时没有绘制任何内容。
  • 然后依次调用getCommand函数获取用户输入的命令,将commands数组和其大小作为参数传递进去。
  • 接着调用draw函数,传递commands数组、其大小、floor数组以及floor数组的行数和列数作为参数,根据输入的命令控制海龟在floor数组上 “作画”。

4. getCommand函数

void getCommand(int commands[], int size) {int i;i = 0;printf("input the commands\n");scanf("%d", &commands[i]);while (commands[i]!= 9) {if (commands[i] == 5) {  // 继续读取前进的格数printf("input steps: ");i++;scanf("%d", &commands[i]);}i++;scanf("%d", &commands[i]);}
}
  • 这个函数用于获取用户输入的命令序列。
  • 首先初始化索引变量i为 0,然后提示用户输入命令。
  • 使用scanf函数读取用户输入的第一个命令,并存储到commands数组中。
  • 进入while循环,只要当前命令不是结束标记 9,就继续读取命令。
    • 如果读取到的命令是 5,表示海龟要向前移动,此时需要额外读取一个表示移动格数的整数,并将其存储到commands数组的下一个位置(i自增后存储)。
    • 无论何种命令,每次读取完命令后i都会自增,准备读取下一个命令。

5. draw函数

void draw(int commands[], int size, int floor[][PICSIZE], int rows, int cols) {int write = 0;  // 笔的朝向,0表示朝上,1表示朝下int row = 0, col = 0;  // 海龟当前位置int dir = 0;  // 海龟的朝向,0表示北,1表示东,2表示南,3表示西for (int i = 0; i < size && commands[i]!= 9; i++) {switch (commands[i]) {case 1:write = 0;break;case 2:write = 1;break;case 3:  // 右转dir = (dir + 1) % 4;break;case 4:  // 左转dir = (dir + 3) % 4;break;case 5: {  // 画图int steps = commands[++i];  // 获取前进格数for (int j = 0; j < steps; j++) {if (write == 1) {  // 如果笔朝下,则画图floor[row][col] = 1;}// 根据海龟朝向更新位置switch (dir) {case 0:  // 向北if (row > 0) {row--;}break;case 1:  // 向东if (col < cols - 1) {col++;}break;case 2:  // 向南if (row < rows - 1) {row++;}break;case 3:  // 向西if (col > 0) {col--;}break;}}break;}case 6:printArray(floor, rows, cols);break;}}
}
  • 此函数是海龟作图的核心逻辑部分。
  • 定义了三个变量来记录海龟的状态:
    • write表示笔的朝向,初始化为 0(朝上)。
    • rowcol表示海龟当前在floor数组中的位置,初始化为 (0, 0)。
    • dir表示海龟的朝向,初始化为 0(向北)。
  • 使用for循环遍历commands数组中的命令,直到遇到结束标记 9 或超出数组范围。
    • 根据不同的命令,通过switch语句进行相应的操作:
      • 命令 1:将write设置为 0,使笔朝上。
      • 命令 2:将write设置为 1,使笔朝下,准备绘制轨迹。
      • 命令 3:使海龟右转,通过将dir加 1 并对 4 取模来更新朝向(实现循环转向)。
      • 命令 4:使海龟左转,通过将dir加 3 并对 4 取模来更新朝向(实现循环转向)。
      • 命令 5:首先获取前进格数steps,然后在一个内层循环中,根据笔的朝向和海龟的当前位置,在floor数组中记录轨迹(如果笔朝下),并根据海龟的朝向更新其位置。
      • 命令 6:调用printArray函数打印当前floor数组中的图形。

6. printArray函数

void printArray(int a[][PICSIZE], int rows, int cols) {int row, col;printf("the array is:\n");for (row = 0; row <= rows - 1; row++) {for (col = 0; col <= cols - 1; col++) {if (a[row][col]!= 0) {printf("*");}else {printf(" ");}}printf("\n");}
}
  • 该函数用于将floor数组中的图形以可视化形式打印出来。
  • 使用两层嵌套的for循环遍历floor数组的每一个元素。
  • 如果元素的值不为 0,表示海龟在该位置绘制过,打印星号 “*”;否则打印空格 “ ”。
  • 每行遍历完后打印换行符,以形成正确的图形输出格式。

三.完整代码如下所示

#include <stdio.h>// 定义命令数组大小和图形数组大小
#define COMMANDSIZE 100
#define PICSIZE 50// 函数声明
void getCommand(int commands[], int size);
void draw(int commands[], int size, int floor[][PICSIZE], int rows, int cols);
void printArray(int a[][PICSIZE], int rows, int cols);int main(void) {int commands[COMMANDSIZE];  // 存储命令int floor[PICSIZE][PICSIZE] = { 0 };  // 存储图片getCommand(commands, COMMANDSIZE);  // 获取命令draw(commands, COMMANDSIZE, floor, PICSIZE, PICSIZE);  // 作图return 0;
}// 获取命令函数
void getCommand(int commands[], int size) {int i;i = 0;printf("input the commands\n");scanf("%d", &commands[i]);while (commands[i]!= 9) {if (commands[i] == 5) {  // 继续读取前进的格数printf("input steps: ");i++;scanf("%d", &commands[i]);}i++;scanf("%d", &commands[i]);}
}// 作图函数
void draw(int commands[], int size, int floor[][PICSIZE], int rows, int cols) {int write = 0;  // 笔的朝向,0表示朝上,1表示朝下int row = 0, col = 0;  // 海龟当前位置int dir = 0;  // 海龟的朝向,0表示北,1表示东,2表示南,3表示西for (int i = 0; i < size && commands[i]!= 9; i++) {switch (commands[i]) {case 1:write = 0;break;case 2:write = 1;break;case 3:  // 右转dir = (dir + 1) % 4;break;case 4:  // 左转dir = (dir + 3) % 4;break;case 5: {  // 画图int steps = commands[++i];  // 获取前进格数for (int j = 0; j < steps; j++) {if (write == 1) {  // 如果笔朝下,则画图floor[row][col] = 1;}// 根据海龟朝向更新位置switch (dir) {case 0:  // 向北if (row > 0) {row--;}break;case 1:  // 向东if (col < cols - 1) {col++;}break;case 2:  // 向南if (row < rows - 1) {row++;}break;case 3:  // 向西if (col > 0) {col--;}break;}}break;}case 6:printArray(floor, rows, cols);break;}}
}// 打印图形函数
void printArray(int a[][PICSIZE], int rows, int cols) {int row, col;printf("the array is:\n");for (row = 0; row <= rows - 1; row++) {for (col = 0; col <= cols - 1; col++) {if (a[row][col]!= 0) {printf("*");}else {printf(" ");}}printf("\n");}
}

接下来我们尝试绘制想要的图形。

比如我们要绘制12*12的矩形我们只需要这样:

运行结果如下:

三角形套三角形(类似谢尔宾斯基三角形的简单形式)

  • 初始状态:笔朝上,海龟在原点 (0, 0)。
  • 输入命令:
    • 2(笔朝下,开始绘制)
    • 5 12(向前移动 12 格,绘制大三角形的一条边)
    • 4(左转)
    • 5 6(向前移动 6 格,准备绘制内部小三角形的边)
    • 3(右转)
    • 5 6(向前移动 6 格,绘制内部小三角形的一条边)
    • 4(左转)
    • 5 3(向前移动 3 格,准备绘制更小三角形的边)
    • 3(右转)
    • 5 3(向前移动 3 格,绘制更小三角形的一条边)
    • 4(左转)
    • 5 1.5(向前移动 1.5 格,可根据实际精度调整,准备绘制最内部三角形的边)
    • 3(右转)
    • 5 1.5(向前移动 1.5 格,绘制最内部三角形的一条边)
    • 1(笔朝上,停止绘制)
    • 6(打印图形)
    • 9(结束命令输入)
  • 图形效果:绘制出一个大三角形,内部嵌套两个逐渐变小的三角形。
  • 运行结果

  •         ** **   **     **       **         **           **             *
    *****************
    *               **             **           **         **       **     **   ** **

    本期海龟作图就分享到这里。

  • 往期回顾:

C语言——指针初阶(一)-CSDN博客

C语言函数递归经典题型——汉诺塔问题-CSDN博客

C语言——数组基本知识(二)-CSDN博客

C语言——数组基本知识(一)-CSDN博客

C语言——数组逐元素操作练习-CSDN博客

C语言编程练习:验证哥德巴赫猜想 进制转换 rand函数-CSDN博客

C语言——函数基本知识(三)-CSDN博客

C语言——函数基本知识(二)-CSDN博客

C语言 ——函数基本知识(一)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/480230.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Maven】继承和聚合

5. Maven的继承和聚合 5.1 什么是继承 Maven 的依赖传递机制可以一定程度上简化 POM 的配置&#xff0c;但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本&#xff0c;且这些模块之间不存在依赖关系&#xff0c;这就导致同一个依赖…

Android 性能优化:内存优化(理论篇)

内存作为App程序运行最重要的资源之一&#xff0c;需要运行过程中做到合理的资源分配与回收&#xff0c;不合理的内存占用轻则使得用户应用程序运行卡顿、ANR、黑屏&#xff0c;重则导致用户应用程序发生 OOM&#xff08;out of memory&#xff09;崩溃。喜马直播随着近些年的业…

技能之发布自己的依赖到npm上

目录 开始 解决 步骤一&#xff1a; 步骤二&#xff1a; 步骤三&#xff1a; 运用 一直以为自己的项目在github上有了&#xff08;之传了github&#xff09;就可以进行npm install下载&#xff0c;有没有和我一样萌萌的同学。没事&#xff0c;萌萌乎乎的不犯罪。 偶然的机…

【选择排序和交换排序】直接选择排序、堆排序、冒泡排序、快速排序

【选择排序和交换排序】直接选择排序、堆排序、冒泡排序、快速排序 1. 选择排序1.1 直接选择排序1.1.1详细过程1.1.2 代码实现1.1.3 复杂度和稳定性 1.2 堆排序 2. 交换排序2.1 冒泡排序2.1.1 代码实现2.1.2 复杂度和稳定性 2.2 快速排序——挖坑法2.2.1详细过程2.2.2 代码实现…

DI依赖注入详解

DI依赖注入 声明了一个成员变量&#xff08;对象&#xff09;之后&#xff0c;在该对象上面加上注解AutoWired注解&#xff0c;那么在程序运行时&#xff0c;该对象自动在IOC容器中寻找对应的bean对象&#xff0c;并且将其赋值给成员变量&#xff0c;完成依赖注入。 AutoWire…

51c大模型~合集79

我自己的原文哦~ https://blog.51cto.com/whaosoft/12661268 #还是回谷歌好 创业一年半&#xff0c;胖了30斤&#xff0c;AI大佬感叹 回到大厂&#xff0c;和老领导重聚。 「由于工作强度和不健康的生活方式&#xff0c;我已胖了 15 公斤。」 本周一&#xff0c;知名 AI 学…

工业AI质检 AI质检智能系统 尤劲恩(上海)信息科技有限公司

来的现代化工厂&#xff0c;将逐步被无人化车间取代&#xff0c;无人工厂除了产线自动化&#xff0c;其无人质检将是绕不开的话题。尤劲恩致力于帮助工业制造领域上下游工厂减员增效、提高品质效率&#xff0c;真正实现无人质检IQC/IPQC/OQC的在线质检系统。分析生产环节真实品…

【CSS in Depth 2 精译_062】第 10 章 CSS 中的容器查询(@container)概述 + 10.1 容器查询的一个简单示例

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第十章 CSS 容器查询】 ✔️ 10.1 容器查询的一个简单示例 ✔️ 10.1.1 容器尺寸查询的用法 ✔️ 10.2 深入理解容器10.3 与容器相关的单位10.4 容器样式查询的用法10.5 本章小结 文章目录 第 10…

ELK(Elasticsearch + logstash + kibana + Filebeat + Kafka + Zookeeper)日志分析系统

文章目录 前言架构软件包下载 一、准备工作1. Linux 网络设置2. 配置hosts文件3. 配置免密登录4. 设置 NTP 时钟同步5. 关闭防火墙6. 关闭交换分区7. 调整内存映射区域数限制8. 调整文件、进程、内存资源限制 二、JDK 安装1. 解压软件2. 配置环境变量3. 验证软件 三、安装 Elas…

视频汇聚平台Liveweb国标GB28181视频平台监控中心设计

在现代安防视频监控领域&#xff0c;Liveweb视频汇聚平台以其卓越的兼容性和灵活的拓展能力&#xff0c;为用户提供了一套全面的解决方案。该平台不仅能够实现视频的远程监控、录像、存储与回放等基础功能&#xff0c;还涵盖了视频转码、视频快照、告警、云台控制、语音对讲以及…

Linux 内核 调用堆栈打印函数

文章目录 内核函数调用堆栈打印1. dump_stack()一、作用二、工作原理三、实现方式四、示例实际演示 2.WARN_ON()3. panic()一、函数作用二、函数行为三、panic() 函数的参数四、使用场景 4. BUG_ON()使用场景 内核函数调用堆栈打印 1. dump_stack() dump_stack()是Linux内核中…

C语言——指针初阶(一)

目录 一.什么是指针&#xff1f;&#xff1f;&#xff1f; 指针是什么&#xff1f; 指针变量&#xff1a; 总结&#xff1a; 总结&#xff1a; 二.指针和指针类型 指针-整数&#xff1a; 总结&#xff1a; 指针的解引用 总结&#xff1a; 三.野指针 如何规避野指针 往期…

【Redis】Redis 预备知识

目录 1. 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 2. 数据结构和内部编码 3. 单线程架构 Redis 提供了5种数据结构&#xff0c;理解每种数据结构的特点对于 Redis 开发运维非常重要&#xff0c;同时掌握每种数据结构的常见命令&#xff0c;会在使用 Redis 的时…

Facebook广告无法投放是什么原因?

Facebook作为全球知名的社媒平台&#xff0c;同时也成为许多知名海外企业的广告首选。但很投手在投放过程中也发现&#xff0c;Facebook 广告投放失败或者被拒投&#xff0c;那到底为什么呢&#xff1f; 其实Facebook广告有着非常严格的审核制度&#xff0c;通常投放失败可能是…

【uniapp】轮播图

前言 Uniapp的swiper组件是一个滑块视图容器组件&#xff0c;可以在其中放置多个轮播图或滑动卡片。它是基于微信小程序的swiper组件进行封装&#xff0c;可以在不同的平台上使用&#xff0c;如微信小程序、H5、App等。 效果图 前端代码 swiper组件 <template><vi…

【JavaEE】多线程(3)

首先回顾一下线程不安全的原因&#xff1a; 线程是随机调度&#xff0c;抢占式执行的修改共享数据&#xff0c;多个线程修改同一个变量多个线程修改共享数据的操作不是原子性&#xff0c;&#xff08;count是3个CPU指令&#xff0c;但是赋值操作就是原子性的&#xff09;内存可…

(0基础保姆教程)-JavaEE开课啦!--12课程(Spring MVC注解 + Vue2.0 + Mybatis)-实验10

一、常见的SpringMVC注解有哪些&#xff1f; 1.Controller&#xff1a;用于声明一个类为 Spring MVC 控制器。 2.RequestMapping&#xff1a;用于将 HTTP 请求映射到特定的处理方法上。可以指定请求类型&#xff08;GET、POST等&#xff09;和URL路径。 3.GetMapping&#xff…

20241124 Typecho 视频插入插件

博文免不了涉及到视频插入这些,网上的插件都或多或少的比较重,和Typecho的风格不搭配 后面就有了DPlay插件精简而来的VideoInsertion插件 VideoInsertion: Typecho 视频插入插件 目录结构 rockhinlink-ht2:/var/www/html/typecho/usr/plugins/VideoInsertion$ tree -h [4.…

网络地址转换

NAT概述 解决公有地址不足&#xff0c;并且分配不均匀的问题 公有地址&#xff1a;由专门的机构管理、分配&#xff0c;可以在因特网上直接通信 私有地址&#xff1a;组织和个人可以任意使用&#xff0c;只能在内网使用的IP地址 A、B、C类地址中各预留了一些私有IP地址 A&…

H5流媒体播放器EasyPlayer.js网页直播/点播播放器如果H.265视频在播放器上播放不流畅,可以考虑的解决方案

随着流媒体技术的迅速发展&#xff0c;H5流媒体播放器已成为现代网络视频播放的重要工具。其中&#xff0c;EasyPlayer.js网页直播/点播播放器作为一款功能强大的H5播放器&#xff0c;凭借其全面的协议支持、多种解码方式以及跨平台兼容性&#xff0c;赢得了广泛的关注和应用。…