题目:
随机步法(Random Walk)
编写程序,生成一种贯穿10×10字符数组(初始时全为字符’.')的“随机步法”。程序必须随机地从一个元素“走到”另一个元素,每次都向上、向下、向左或向右移动一个元素位置。已访问过的元素按访问顺序用字母A到Z进行标记。
下面是一个输出示例:
A . . . . . . . . .
B C D . . . . . . .
. F E . . . . . . .
H G . . . . . . . .
I . . . . . . . . .
J . . . . . . . Z .
K . . R S T U V Y .
L M P Q . . . W X .
. N O . . . . . . .
利用srand函数和rand函数产生随机数,然后查看次数除以4的余数。余数一共有4种可能的值(0、1、2和3),指示下一次移动的4种可能方向。在执行移动之前,需要检查两项内容:一是不能走到数组外面,二是不能走到已有字母标记的位置。只要一个条件不满足,就得尝试换一个方向移动。如果4个方向都堵住了,程序就必须终止了。下面是提前结束的一个示例:
A B G H I . . . . .
. C F O J K . . . .
. D E N M L . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
因为Y的4个方向都堵住了,所以没有地方可以放置下一步的Z了。
先放代码
/* 随机步法 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <string.h>
//全局变量,存储二位字符数组
char map[10][10];
//判断是否越界,越界返回true
bool isOutOfBound(int x, int y)
{
if(x < 0 || x > 9 || y < 0 || y > 9) return true;
else return false;
}
//判断这一步位置是否已经有字母,有则返回true
bool isPut(int x, int y)
{
if(map[x][y] != '.') return true;
else return false;
}
int main()
{
//设置随机数种子
srand((unsigned int)time(NULL));
//初始化地图(10×10)字符数组
for(int i = 0; i < 10; i++)
{
for(int j = 0;j < 10; j++)
{
map[i][j] = '.';
}
}
//记录当前该填入的是哪个字母
char c = 'A';
//设置起始位置并填入A;设置空置位判断下一步是否可以填入字母
int x = 0, y = 0;
int new_x = x, new_y = y;
map[x][y] = c++;
//记录当前位置四个方向的可行性 flag为4时证明四个方向均无法通过
int flag = 0;
//记录当前位置的四个方向是否已经访问过 1表示已经访问过
int visited[4];
memset(visited, 0, sizeof(visited));
while(c <= 'Z' && flag < 4)
{
//生成随机数代表移动方向 0向上 1向右 2向下 3向左
int num = rand() % 4;
switch (num)
{
case 0:
if(visited[0] == 1) continue;
visited[0] = 1;
new_y--;
break;
case 1:
if(visited[1] == 1) continue;
visited[1] = 1;
new_x++;
break;
case 2:
if(visited[2] == 1) continue;
visited[2] = 1;
new_y++;
break;
case 3:
if(visited[3] == 1) continue;
visited[3] = 1;
new_x--;
break;
}
flag++;
//判断是否可以填入字母
if(isOutOfBound(new_x, new_y) || isPut(new_x, new_y))
{
//不能填入则复原x,y
new_x = x;
new_y = y;
continue;
}
x = new_x;
y = new_y;
map[x][y] = c++;
flag = 0;
memset(visited, 0, sizeof(visited));
}
//循环结束,打印数组
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
printf("%c", map[i][j]);
}
printf("\n");
}
return 0;
}
代码用全局变量二维数组存储信息,用isOutOfBound和IsPut函数判断下一步位置是否可以放置字母。rand()函数可以以固定种子生成随机数,为了实现真正的随机数,用当前时间为种子,用srand()函数改变种子即可。
开始前初始化map数组,之后从(0, 0)位置开始随机前进。用new_x和new_y两个变量临时记录下一步的位置,便于当下一步位置无法放置字母时进行位置回退。若下一步位置不合理,则返回switch case重新生成随机数再进行尝试。这里一定要重新生成随机数而非令num = (num + 1) % 4,否则就不是真正的随机步法!! 但重新尝试仍有可能走到原先的方向,故用visited数组记录当前位置的四个方向是否被访问过。
每次成功访问,用flag进行记录。初始值为0,当flag为4时证明四个方向均已经访问过,即路被堵死,此时结束循环并打印数组。所以每次成功访问要记得把flag重新置0。同时visited数组也要清零。
循环结束后打印数组即可。
答案仅供参考,不要盲目copy哦~