C++海龟制图实现

海龟制图是一个经典的题目,是要编写一个输入命令,让海龟按命令前进的程序 。

一、题目描述

    在小学生中很流行的徽标语言使乌龟图形的概念声名远播。 想象一下,一只机械乌龟在C ++程序的控制下在房间里走动。 乌龟在上下两个位置之一中握住笔。当笔向下时,乌龟会在移动时追踪形状。 当笔在上面时,乌龟可以自由移动,而无需书写任何东西。 在此问题中,您将模拟乌龟的操作并创建一个计算机化的画板。请使用初始化为false的20 x 20阵列地板。 从包含它们的数组中读取命令。 始终跟踪乌龟的当前位置以及笔当前处于向上还是向下。 假定乌龟总是用笔向上从地板的位置(0,0)开始。 图中显示了程序必须处理的一组乌龟命令。 

     这里写图片描述

二、具体实现如下:

#include <iostream>
#include <iomanip>
using namespace std;
int matrix[100][100]={0},n=0,d=0,x=0,y=0;
void move(int);
void print();
int main()
{
    int command;
    while(cin>>command&&command!=0)
    {
        switch(command)
        {
            case 2:n=1;break;             //摁下笔,行走有墨迹
            case 1:n=0;break;             //提起笔,行走无墨迹
            case 3:move(3);break;         //向右转
            case 4:move(4);break;         //向左转
            case 5:move(5);break;         //向前走
            case 6:print();break;
            default: cout<<"wrong!";
        }
    }
    return 0;
}


void move(int command)
{
    int a,b,dir[4][2]={0,1,1,0,0,-1,-1,0};
    int t[8]={1,2,3,0,3,0,1,2};
    char comma;
    if(command!=5)                        //处理摁下3, 然后5,10的情况
        cin>>a>>comma>>b;
    else
        cin>>comma>>b;                    //处理5,10的情况
    if(command!=5)
        d=t[command&4|d];                 //解决方向问题
                                          //具体的推导可以使用状态图转换,见下
    else d=d;
    for(int i=0;i<b;i++)
    {
        if(matrix[x][y]==0)
            matrix[x][y]=n;
        if(i<b-1)
        {
            x+=dir[d][0];
            y+=dir[d][1];
        }
    }
}

void print()
{
    for(int i=0;i<25;i++)
    {
        for(int j=0;j<50;j++)
        {
            if(matrix[i][j]==0)cout<<"  ";
            else cout<<" *";
        }
        cout<<endl;
    }
}

 关于这里的方向转换问题,可以用状态转换图来更好的归纳

 首先我们先来定义方向:

图片无效

 注意这里x,y的情况跟我们熟悉的x是水平轴,y是垂直轴的情况不一致。这里x代表行,所以它的方向是垂直的。

然后画出状态转换图

图片无效

 画出状态转换图之后,其实我们可以用一大串的if else语句来实现方向转换功能,这里用数组把方向转换对存起来,效率会更高,该方法有些以空间换时间的意味。

正如上面所描述的意义,我们根据转换图先画出方向转换的关系,然后把这些关系以键值对的方式用map存起来,因为数组又可以理解成是键是下标、值是内容的map,所以可以用数组简化存储。

上面的图只举了向右转的例子,同理可得向左转的数组为{3,0,1,2}

if(command!=5)
        d=t[command&4|d];
else d=d;

然后上面的程序就是使用了数组来实现方向转换,这里用位运算的方法使得两个转向数组合并为一个,因为:

3&4=000, 此时   d=t[command&4|d]   等价于   d = t[d], 

4&4 = 100 ,此时   d=t[command&4|d]    等价于  d = t[d+4]。

如果不想这么复杂,你也可以用下面的方法, 可以达到同样的效果,几乎相同的效率。

int t1[4]={1,2,3,0};
int t2[4]={3,0,1,2};
if(command==3)
    d=t1[d];
else if(command==4)
    d=t2[d];
else
    d=d;        //command==5的情况,不用转向

 另外,你会发现,x,y的增减也是用数组存了起来,因为它也是一个:方向->(delta_x, delta_y) 的映射。

三、总结

   1.关于复杂的状态转换问题,我们可以把它存为一个键值对的映射,避免复杂的if else语句。

   2.键为小范围整数的键值对映射,转换成数组效率更好。

原创文章 26 获赞 33 访问量 1927

猜你喜欢

转载自blog.csdn.net/qq_40765537/article/details/78935960
今日推荐