首页 > 其他分享 >C语言——海龟作图(对之前所有内容复习)

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

时间:2024-11-30 15:34:34浏览次数:11  
标签:case commands 复习 floor 作图 C语言 int 数组 海龟

一.问题描述

海龟作图

     设想有一只机械海龟,他在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博客

标签:case,commands,复习,floor,作图,C语言,int,数组,海龟
From: https://blog.csdn.net/hjx1235/article/details/144121764

相关文章

  • C语言——指针初阶(三)
    目录一.指针-指针    代码1:运行结果:    代码2:运行结果:        代码3:运行结果:二.指针数组例:往期回顾一.指针-指针    指针减去指针的前提:两个指针指向同一块空间。    指针减去指针的绝对值得到两个指针之间的元素个数......
  • Java技术复习提升 17反射
    本章涉及到框架开发中必用的反射以及常用方法很重要注重理解并实践第17章反射17.1一个需求引出反射packagecom.fsl;publicclassCat{privateStringname="招财猫";publicintage=10;//public的publicCat(){}//无参构造器publi......
  • 洛谷 P2895 [USACO08FEB] Meteor Shower S C语言 bfs
    题目:https://www.luogu.com.cn/problem/P2895题目描述贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星摧毁的地方)。如果将牧场放入一个直角坐标系中,贝茜现在的位置是原......
  • 洛谷 P1162 填涂颜色 C语言 bfs
    题目:https://www.luogu.com.cn/problem/P1162由数字 0 组成的方阵中,有一任意形状的由数字 1 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 22。例如:6×6的方阵(n=6),涂色前和涂色后的方阵如下:如果从某个 0 出发,只向上下左右 4 个方向移动且仅经过其他 00 的情......
  • 洛谷 P1332 血色先锋队 C语言 bfs
    题目:https://www.luogu.com.cn/problem/P1332#submit题目背景巫妖王的天灾军团终于卷土重来,血色十字军组织了一支先锋军前往诺森德大陆对抗天灾军团,以及一切沾有亡灵气息的生物。孤立于联盟和部落的血色先锋军很快就遭到了天灾军团的重重包围,现在他们将主力只好聚集了起来,以......
  • C语言之用链表的方式解析与运算简单的波兰表达式
    C语言之用链表的方式解析与运算简单的波兰表达式我这里说的简单的波兰表达式,是指没有嵌套的加减乘除表达式,如:(+12),(-100905)定义基本的数据结构定义数据类型,全用大写字母,DT开头,后面附加类型名字:DT_OPERATOR定义表达式结构体,Express,自定义为Expr定义链表节点结......
  • C语言经典例题-13
    1.小乐乐走台阶题目描述:小乐乐上课需要走n阶台阶,因为他腿比较长,所以每次可以选择走一阶或者走两阶,那么他一共有多少种走法?输入描述:输入包含一个整数n(1≤n≤30)输出描述:输出一个整数,即小乐乐可以走的方法数。示例1输入:2输出:2示例2输入:10......
  • C语言中的结构体
    一.结构体声明首先要知道结构的成员可以是标量、数组、指针,甚至是其他结构体。例如描述一个学生:structStu{charname[20];intage;charsex[5];};那么如何创建一个结构体变量?intmain(){structStua,b,c;return0;}或者structStu{charname[20];......
  • C语言实现数组堆并解决TopK问题
    还是先定义结构体typedefintHPDataType;typedefstruct{HPDataType*array;intsize;intcapacity;}HP;voidHeapInit(HP*php){assert(php);php->array=NULL;php->capacity=php->size=0;}首先是它的初始化。voidHeapDestroy......
  • P5015 [NOIP2018 普及组] 标题统计 C语言
    先说思路:跟着题意来就好,其实更多的是考察fgets()函数的基础运用,之后用循环遍历字符串,若是遇到空格和换行符就不计入,反之count++;这里也可以直接用isalnum()直接对输入的字符是否是字母或是数字进行判断。以下是代码实现:#include<stdio.h>#include<ctype.h>intmain(){......