“随机漫步”(Random Walk)模拟演示

(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


 

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值