编程题 随机步法

OrzMiku / 2023-08-20 / 原文

编程题 随机步法

编写程序, 生成一种贯穿10x10字符数组 (初始时全为字符' . ') 的"随机步法". 程序必须随机的从一个元素出发, 随机的走的另一个元素. 每次都只能向上下左右中选一个方向, 走出一步. 已经走过的位置用A-Z标记. 下面是一个输出示例:

. . . . . . . . . .
J I . . . . . . . .
K H G . . . . . . .
L E F . . . . . . .
M D C . . . . . . .
N O B A . . . . . .
Q P . . . . . . . .
R Y Z . . . . . . .
S X W . . . . . . .
T U V . . . . . . .
  • 不能走出边界
  • 不能走到走过的位置
  • 最多走到Z
  • 无法继续走时应停止并输出结果

代码

#include<stdio.h>
#include<time.h>
#define T 10

void mapInit(char map[T][T]); /* 地图初始化 */
int nextStep(int posX, int posY, char map[T][T]); /* 计算下一步 */
int setStep(int *i, int *j, int n, char map[T][T]); /* 走一步 */
void printMap(char map[T][T]); /* 打印地图 */


int main(void) {
	int i, j, n;
	char map[T][T];
	mapInit(map); /* 地图初始化 */
	char ch = 'A';
	srand((unsigned)time(NULL)); /* 随机数播种 */
	i = rand() % T;
	j = rand() % T;
	while (ch != 'Z' + 1) {
		map[i][j] = ch++;
		n = nextStep(i, j, map);
		if (!setStep(&i, &j, n, map)) break;
	}
	printMap(map);
	return 0;
}

/* 地图初始化 */
void mapInit(char map[T][T]) {
	int i, j;
	for (i = 0; i < T; i++) {
		for (j = 0; j < T; j++) {
			map[i][j] = '.';
		}
	}
}

/* 计算下一步 */
int nextStep(int posX, int posY, char map[T][T]) {
	/*
		result:
			- 0: 无法移动
			- 1: 上移
			- 2: 下移
			- 3: 左移
			- 4: 右移
	*/
	int result,next;
	int flags[4] = { 0 }; /* 标记下一步 */
	/*
		依次判断能否向某个方向移动
		如果不能移动, cnt计数器不变
		如果可以移动, cnt计数器加一, 且对应位置标记
			- 1: 上移
			- 2: 下移
			- 3: 左移
			- 4: 右移
		假如可以下移,右移
		flags = {2,4,0,0}
		cnt = 2
		(如果cnt为0,说明无法继续走)
		然后生成一个随机数, rand()%cnt
		假如cnt为2, 随机数范围 0-1
		然后根据随机数取出flags的一个值,返回
	*/
	int cnt = 0; /* 计数器, 计算下一步能走的可能数 */

	/* 判断上移 */
	if (posX == 0 || map[posX - 1][posY] != '.') {
		/* 在第一行或上一行这个位置已经走过了 */
		flags[cnt] = 0;
	}else {
		/* 可以上移 */
		flags[cnt++] = 1;
	}

	/* 判断下移 */
	if (posX == T-1 || map[posX + 1][posY] != '.') {
		/* 在最后一行或下一行这个位置已经走过了 */
		flags[cnt] = 0;
	}else {
		/* 可以下移 */
		flags[cnt++] = 2;
	}

	/* 判断左移 */
	if (posY == 0 || map[posX][posY - 1] != '.') {
		/* 在第一列或上一列这个位置已经走过了 */
		flags[cnt] = 0;
	}else {
		/* 可以左移 */
		flags[cnt++] = 3;
	}

	/* 判断右移 */
	if (posY == T - 1 || map[posX][posY + 1] != '.') {
		/* 在最后一列或下一列这个位置已经走过了 */
		flags[cnt] = 0;
	}else {
		/* 可以右移 */
		flags[cnt++] = 4;
	}

	if (cnt == 0) {
		/* 无路可走 */
		result = 0;
	}else {
		next = rand() % cnt; /* 下一步 */
		result = flags[next];
	}
	
	return result;
}

/* 走一步 */
int setStep(int *i, int *j, int n, char map[T][T]) {
	/*
		变量n
			- 0: 无法移动
			- 1: 上移
			- 2: 下移
			- 3: 左移
			- 4: 右移
	*/
	if (!n) return 0; /* 无法移动, 结束 */
	switch (n) {
	case 1:
		(*i)--;
		break;
	case 2:
		(*i)++;
		break;
	case 3:
		(*j)--;
		break;
	case 4:
		(*j)++;
		break;
	}
	return 1;
}

/* 打印地图 */
void printMap(char map[T][T]) {
	int i, j;
	for (i = 0; i < T; i++) {
		for (j = 0; j < T; j++) {
			if (j == T - 1) {
				printf("%c\n", map[i][j]);
			}else {
				printf("%c ", map[i][j]);
			}
		}
	}
}