(1)、任务描述
有一类问题总称为“随机漫步”(Random Walk)问题,这类问题长久以来吸引着数学界的兴趣。所有这些问题即使是最简单的解决起来也是极其困难的。而且它们在很大程度上还远没有得到解决。一个这样的问题可以描述为:
在矩形的房间里,铺有n×m块瓷砖,现将一只(醉酒的)蟑螂放在地板中间一个指定方格里。蟑螂随机地从一块瓷砖“漫步”到另一块瓷砖(可能是在找一片阿司匹林)。假设它可能从其所在的瓷砖移动到其周围八块瓷砖中的任何一个(除非碰到墙壁),那么它把每一块瓷砖都至少接触一次将花费多长时间?
虽然这个问题可能很难用纯粹的概率技术来解决,但是使用计算机的话却十分容易。使用计算机解决此问题的技术称为“模拟”。这种技术广泛应用于工业中,用来预测运输流量,存货控制等等。
现在,利用所学的C语言程序设计和数据结构基础知识,建立一个“随机漫步”(Random Walk)模拟演示系统,并将得到的模拟结果(模拟产生的数据)保存,以供研究使用。
(2)、设计目的
利用二维数组解决复杂的实际问题;了解实际问题到计算机问题的转化;了解算法设计中边界条件的重要性。
(3)、基本要求
程序必须满足:
①能够处理所有的n和m值, n和m满足:2<n≤40,2≤m≤20;
②能够对“n = 15,m = 15,起始点为(10,10)”和“n = 39,m = 19,起始点为(1,1)”进行实验。
③具有迭代限制,即实验过程中蟑螂进入方块的最大次数为MAX =50000时,程序能够终止。
对于每次试验,打印:
①蟑螂进行的合法移动的总次数。
②最终的计数器数组,显示出漫步的“密度”,即输出在实验中每一块瓷砖被接经过的次数。
代码清单:
(1)MAIN.cpp
#include <iostream>
using namespace std;
#include "RandWalk.h"
int main(void)
{
RandWalk();
system("PAUSE");
return 0;
}
(2)RandWalk.h
#ifndef RANDWALK_H_INCLUDED
#define RANDWALK_H_INCLUDED
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h> //头文件区
#include "Operation.h"
#include "Simulate.h"
void RandWalk(void)
{
//功能:进入Rand Walk模拟演示系统,选择操作
system("color 0E");
bool quit = false;
while(!quit)
{
system("cls");
menu();
int choose;
scanf("%d",&choose);
switch(choose)
{
case 1:
displayExplanation();
break;
case 2:
quit = simulate();
break;
case 3:
quit = true;
break;
default:
printf("\t您的输入不合法!\n\t ");
system("PAUSE");
break;
}
}
}
#endif // RANDWALK_H_INCLUDED
(3)Operation.h
#ifndef OPERATION_H_INCLUDED
#define OPERATION_H_INCLUDED
#define PREINSTALL_SIZE 10000
void menu(void)
{
//功能:打印菜单
puts(" 欢迎进入\"Random Walk\"模拟演示系统:");
puts("\t\t===================================================");
puts("\t\t_1.查看演示说明.");
puts("\t\t_2.进行模拟演示.");
puts("\t\t_3.对此演示不感兴趣,退出程序.");
puts("\t\t====================================================");
printf(" 输入序号,进行选择:");
}
void displayExplanation(void)
{
//操作:读取文件displayExplanation.txt
//功能:对Random Walk模拟演示系统进行解释说明
FILE* fp = fopen("displayExplanation.txt","rw");
if(!fp)
{
fprintf(stderr,"EEOR:打开文件出错!\n");
exit(EXIT_FAILURE);
}
char Exp[PREINSTALL_SIZE],ch;
int index = 0;
while(ch = fgetc(fp),ch != EOF)
Exp[index++] = ch;
MessageBox(NULL,TEXT(Exp),TEXT("演示说明:"),0);
fclose(fp);
}
void inputPrompt(void)
{
puts("\t地板上铺有n×m块瓷砖,请您确定m、n的值:");
printf("\t注:n和m满足:<n≤,≤m≤: ");
}
#endif // OPERATION_H_INCLUDED
(4)Simulate.h
#ifndef SIMULATE_H_INCLUDED
#define SIMULATE_H_INCLUDED
#define ITERATIVE_MAX 50000 //迭代限制
struct coordinate
{
//功能;确定对象的坐标位置
int x,y;
};
struct layout
{
//功能:表示矩形的房间,并将模拟得到的数据保存于二维数组中
int length,width;
int **array;//二维数组计数器
};
struct situation
{
//功能:表示当前时刻模拟系统所处的局面情形
struct layout tile; //漫游布局
struct coordinate position; //对象所处位置
int passed; //已走过的瓷砖数目
int iteration; // 迭代限制
};
void InitLayout(struct layout &e)
{
//功能:初始化二维数组计数器e.array,使其初始值均为
e.array = (int**)calloc(e.length,sizeof(int*));
for(int i = 0; i < e.length; ++i)
{
e.array[i] = (int*)calloc(e.width,sizeof(int));
for(int j = 0; j < e.width; ++j)
e.array[i][j] = 0;
}
}
void DestoryLayout(struct layout &e)
{
//功能:销毁结构体e,释放初始化过程中申请的内存
if(!e.array)
{
for(int i = 0; i < e.length; ++i)
free(e.array[i]);
free(e.array);
}
e.array = NULL;
e.length = e.width = 0;
}
bool judgePosition(struct coordinate p,struct layout l)
{
//功能:判断蟑螂的坐标位置是否合法
//若合法,返回true;否则,返回false
if(p.x < 0 || p.y < 0 || p.x > l.width || p.y > l.length)
return false;
else
return true;
}
void InitSituation(struct situation &e)
{
//操作:提示并输入蟑螂所在坐标位置(x,y)
//功能:初始化当前时刻模拟系统所处的局面情形
inputPrompt();
scanf("%d%d",&e.tile.length,&e.tile.width);
InitLayout(e.tile);
printf("\t请输入蟑螂所在坐标位置(x,y): ");
scanf("%d%d",&e.position.x,&e.position.y);
while(!judgePosition(e.position,e.tile))
{
printf("\t您输入的值不合法!\n\t请重新输入坐标位置(x,y):");
scanf("%d%d",&e.position.x,&e.position.y);
}
e.iteration = 0;
e.passed = 0;
}
void DestorySituation(struct situation &e)
{
//功能:销毁结构体e,释放初始化过程中申请的内存
DestoryLayout(e.tile);
e.iteration = 0;
e.passed = 0;
e.position.x = e.position.y = 0;
}
void manage(struct situation &e)
{
//功能:模拟的基本操作过程,并得到相应的结果
int imove[8] = {-1,0,1,1,1,0,-1,-1},jmove[8] = {1,1,1,0,-1,-1,-1,0};
while(1)
{
int iTemp = rand()%8;
if(e.position.x + imove[iTemp] > 0 && e.position.y + jmove[iTemp] > 0 && e.position.x + imove[iTemp] <= e.tile.width && e.position.y + jmove[iTemp] <= e.tile.length)//判断移动的方向是否合法
{
e.position.x += imove[iTemp];
e.position.y += jmove[iTemp];
e.iteration++;
if(!e.tile.array[e.position.y - 1][ e.position.x - 1])
e.passed++;
e.tile.array[e.position.y - 1][ e.position.x - 1]++;
}
if(e.passed == e.tile.width*e.tile.length || e.iteration == ITERATIVE_MAX)
break;
}
}
void displayLayout(struct layout e)
{
//功能:输出模拟过程中得到的数据
for(int i = 0; i < e.length; ++i)
{
for(int j = 0; j < e.width; ++j)
printf("%d ",e.array[i][j]);
puts("");
}
}
void dispalyFormate(int m)
{
//功能:格式化输出int型数据
char s[5];
s[4] = '\0';
int i = 0;
while(m)
{
s[i++] = (char)(m%10 + '0');
m = m/10;
}
int j = i - 1,k = 0;
while(j > k)
{
char cTemp = s[k];
s[k] = s[j];
s[j] = cTemp;
j--,k++;
}
while(i != 3)
s[i++] = ' ';
printf("%s",s);
}
void dispalyFormateLayout(struct layout e)
{
//功能:格式化输出模拟过程中得到的数据,
//并将数据存入到RandomWalk_Data.txt记事本文件中
FILE* fp;
//fp = fopen("RandomWalk_Data.txt","w");
//fp = fopen("RandomWalk_Data.xls","w");
fp = fopen("RandomWalk_Data.dat","w");
if(!fp)
printf("ERROR!\n");
for(int i = 0; i < e.length; ++i)
{
for(int j = 0; j < e.width; ++j)
{
dispalyFormate(e.array[i][j]);
//将数据读入文件中
fprintf(fp,"%d ",e.array[i][j]);
}
puts("");
fprintf(fp,"\n");
}
fclose(fp);
}
bool conclusion(void)
{
MessageBox(NULL, TEXT("模拟已结束,模拟数据已存入相应的记事本中.\n\t如果想观看,请输入\"1\"." "\n\t输入\"2\",重新进入演示系统.\n\t输入其他字符将退去本系统."),
TEXT("提示信息:"),0);
int iTemp;
printf("继续:");
scanf("%d",&iTemp);
switch(iTemp)
{
case 2:
return false;
case 1:
//system("start RandomWalk_Data.txt");
//system("start RandomWalk_Data.xls");
system("start RandomWalk_Data.dat");
default:
return true;
}
}
bool simulate(void)
{
struct situation EXAMPLE;
InitSituation(EXAMPLE);
displayLayout(EXAMPLE.tile);
manage(EXAMPLE);
dispalyFormateLayout(EXAMPLE.tile);
printf("Iteration:%d\n",EXAMPLE.iteration);
printf("Passed:%d\n",EXAMPLE.passed);
DestorySituation(EXAMPLE);
return conclusion();
}
#endif // SIMULATE_H_INCLUDED