(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