⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gd22-01.cpp

📁 游戏开发数据结构Data Structures for Game Programmers
💻 CPP
字号:
// ============================================================================
//  GD22-01.cpp
//  Graphical Demonstration - Random Distributions
// ============================================================================
#include "SDLGUI.h"
#include <stdlib.h>
#include <time.h>
#include "RandomNumbers.h"
#include "Array.h"


// ============================================================================
//  Global Constants
// ============================================================================
const char PROGRAM_NAME[]   = "Graphical Demonstration 22-01 - Random Distributions";
const int WIDTH             = 800;
const int HEIGHT            = 600;
const int ITEMS             = 128;


// ============================================================================
//  Global Variables
// ============================================================================
SDLGUI* g_gui;
const int ARIAL = 0;
const int SMALLARIAL = 1;
const int BIGARIAL = 2;


char g_min1string[16] = "1";
char g_max1string[16] = "6";
char g_min2string[16] = "0";
char g_max2string[16] = "0";
char g_min3string[16] = "0";
char g_max3string[16] = "0";
char g_min4string[16] = "0";
char g_max4string[16] = "0";

int g_min1 = 1;
int g_max1 = 6;
int g_min2 = 0;
int g_max2 = 0;
int g_min3 = 0;
int g_max3 = 0;
int g_min4 = 0;
int g_max4 = 0;


int g_min;
int g_max;
int g_difference;
int g_outcomes;

// frequency tables
Array<int> g_theoreticalf( 1024 );
Array<int> g_actualf( 1024 );

// normalised frequency tables.
Array<float> g_theoreticalfn( 1024 );
Array<float> g_actualfn( 1024 );


bool g_theoreticalon = false;
bool g_actualon = false; 

int g_trials = 1000;
char g_trialstring[16] = "1000";

char g_currentstring[16] = "0";
int g_current = 0;
char g_theoreticalstring[64] = "";
char g_actualstring[64] = "";


SDL_Surface* g_graph;


// ============================================================================
//  Functions
// ============================================================================
void Normalise( Array<int>& p_table, Array<float>& p_normals, int p_count )
{
    int i;

    for( i = 0; i < p_table.Size(); i++ )
    {
        p_normals[i] = (float)(p_table[i]) / (float)p_count;
    }
}


template <class T>
void swap( T& l, T& r )
{
    T temp = l;
    l = r;
    r = temp;
}


void DrawGraph()
{
    float ymax = 0;
    int i;
    int x;
    float xmultiplier = 600.0f / (float)g_difference;

    // new x and y
    float nx, ny;

    // previous x and y
    float px, py;

    for( i = 0; i < g_difference; i++ )
    {
        if( g_theoreticalfn[i] > ymax )
            ymax = g_theoreticalfn[i];
        if( g_actualfn[i] > ymax )
            ymax = g_actualfn[i];
    }

    // clear the graph.
    SDL_FillRect( g_graph, NULL, SDL_MapRGB( g_graph->format, 255, 255, 255 ) );
    
    if( g_theoreticalon == true )
    {
        px = 50;
        py = 500 - ((g_theoreticalfn[0] / ymax) * 450);
        for( x = 1; x < g_difference; x++ )
        {
            nx = ((float)x * xmultiplier) + 50;
            ny = 500 - ((g_theoreticalfn[x] / ymax) * 450);
            SDLLine( g_graph, (int)px, (int)py, (int)nx, (int)ny, BLUE );
            px = nx;
            py = ny;
        }
    }

    if( g_actualon == true )
    {
        px = 50;
        py = 500 - ((g_actualfn[0] / ymax) * 450);
        for( x = 1; x < g_difference; x++ )
        {
            nx = ((float)x * xmultiplier) + 50;
            ny = 500 - ((g_actualfn[x] / ymax) * 450);
            SDLLine( g_graph, (int)px, (int)py, (int)nx, (int)ny, RED );
            px = nx;
            py = ny;
        }
    }

    // update the graph
    SDL_UpdateRect( g_graph, 0, 0, 0, 0 );

}


// ============================================================================
//  Callbacks
// ============================================================================
void calculate()
{
    // find the mins and maxs.

    // die 1.
    g_min1 = atoi( g_min1string );
    g_max1 = atoi( g_max1string );
    if( g_min1 > g_max1 )
        swap( g_min1, g_max1 );
    sprintf( g_min1string, "%d", g_min1 );
    sprintf( g_max1string, "%d", g_max1 );

    // die 2
    g_min2 = atoi( g_min2string );
    g_max2 = atoi( g_max2string );
    if( g_min2 > g_max2 )
        swap( g_min2, g_max2 );
    sprintf( g_min2string, "%d", g_min2 );
    sprintf( g_max2string, "%d", g_max2 );

    // die 3
    g_min3 = atoi( g_min3string );
    g_max3 = atoi( g_max3string );
    if( g_min3 > g_max3 )
        swap( g_min3, g_max3 );
    sprintf( g_min3string, "%d", g_min3 );
    sprintf( g_max3string, "%d", g_max3 );

    // die 4
    g_min4 = atoi( g_min4string );
    g_max4 = atoi( g_max4string );
    if( g_min4 > g_max4 )
        swap( g_min4, g_max4 );
    sprintf( g_min4string, "%d", g_min4 );
    sprintf( g_max4string, "%d", g_max4 );


    g_min = g_min1 + g_min2 + g_min3 + g_min4;
    g_max = g_max1 + g_max2 + g_max3 + g_max4;
    g_difference = g_max - g_min + 1;

    // if the array isn't large enough to hold all the possible 
    // values, then resize them.
    if( g_difference > g_theoreticalf.Size() )
    {
        g_theoreticalf.Resize( g_difference );
        g_actualf.Resize( g_difference );
        g_theoreticalfn.Resize( g_difference );
        g_actualfn.Resize( g_difference );
    }

    g_outcomes =    (g_max1 - g_min1 + 1) * 
                    (g_max2 - g_min2 + 1) * 
                    (g_max3 - g_min3 + 1) * 
                    (g_max4 - g_min4  +1);

    // convert the trials to a number. If invalid, set to 1, 
    // and write it back to the textbox.
    g_trials = atoi( g_trialstring );
    if( g_trials <= 0 )
    {
        g_trials = 1;
    }
    sprintf( g_trialstring, "%d", g_trials );

    int a, b, c, d;

    // clear the frequency tables
    for( a = 0; a < g_difference; a++ )
    {
        g_theoreticalf[a] = 0;
        g_actualf[a] = 0;
    }


    // fill the theoretical frequency table.
    for( a = g_min1; a <= g_max1; a++ )
    {
        for( b = g_min2; b <= g_max2; b++ )
        {
            for( c = g_min3; c <= g_max3; c++ )
            {
                for( d = g_min4; d <= g_max4; d++ )
                {
                    g_theoreticalf[(a+b+c+d) - g_min]++;
                }
            }
        }
    }

    for( a = 0; a < g_trials; a++ )
    {
        b =  RandomRange( g_min1, g_max1 );
        b += RandomRange( g_min2, g_max2 );
        b += RandomRange( g_min3, g_max3 );
        b += RandomRange( g_min4, g_max4 );
        g_actualf[b - g_min]++;
    }


    // normalise the tables.
    Normalise( g_theoreticalf, g_theoreticalfn, g_outcomes );
    Normalise( g_actualf, g_actualfn, g_trials );

    if( g_current > g_max )
        g_current = g_max;
    if( g_current < g_min )
        g_current = g_min;
    sprintf( g_currentstring, "%d", g_current );

    DrawGraph();
}




void TheoreticalToggle()
{
    g_theoreticalon = !g_theoreticalon;
    DrawGraph();
}

void ActualToggle()
{
    g_actualon = !g_actualon;
    DrawGraph();
}



void CurrentDown()
{
    if( g_current > g_min )
        g_current--;
    sprintf( g_currentstring, "%d", g_current );
}

void CurrentUp()
{
    if( g_current < g_max )
        g_current++;
    sprintf( g_currentstring, "%d", g_current );
}





int main( int argc, char* argv[] )
{

    srand( time( 0 ) );

    // declare coordinates.
    int x, y;

    // declare event holder
    SDL_Event event;

    // set our at exit function
    atexit( SDL_Quit );

    //initialize systems
    SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
    TTF_Init();
    SDL_EnableUNICODE( true );

    // create the GUI and set the caption.
    g_gui = new SDLGUI( WIDTH, HEIGHT, ITEMS, WHITE );
    SDL_WM_SetCaption( PROGRAM_NAME, 0); 

    // load the fonts
    g_gui->SetFont( "arial.ttf", ARIAL, 17, TTF_STYLE_NORMAL );
    g_gui->SetFont( "arial.ttf", SMALLARIAL, 12, TTF_STYLE_NORMAL );
    g_gui->SetFont( "arial.ttf", BIGARIAL, 24, TTF_STYLE_NORMAL );


    // add the 4 random ranges


    // range 1
    g_gui->AddLabel( 5, 10, "Range 1", BIGARIAL, BLACK, WHITE );

    // min1
    g_gui->AddLabel( 10, 40, "min", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 5, 60, 40, 20, g_min1string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );

    // max1
    g_gui->AddLabel( 55, 40, "max", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 50, 60, 40, 20, g_max1string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );


    // range 2
    g_gui->AddLabel( 5, 110, "Range 2", BIGARIAL, BLACK, WHITE );

    // min2
    g_gui->AddLabel( 10, 140, "min", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 5, 160, 40, 20, g_min2string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );

    // max2
    g_gui->AddLabel( 55, 140, "max", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 50, 160, 40, 20, g_max2string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );


    // range 3
    g_gui->AddLabel( 5, 210, "Range 3", BIGARIAL, BLACK, WHITE );

    // min3
    g_gui->AddLabel( 10, 240, "min", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 5, 260, 40, 20, g_min3string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );

    // max3
    g_gui->AddLabel( 55, 240, "max", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 50, 260, 40, 20, g_max3string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );


    // range 4
    g_gui->AddLabel( 5, 310, "Range 4", BIGARIAL, BLACK, WHITE );

    // min4
    g_gui->AddLabel( 10, 340, "min", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 5, 360, 40, 20, g_min4string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );

    // max4
    g_gui->AddLabel( 55, 340, "max", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 50, 360, 40, 20, g_max4string, 6, ARIAL,
                       BLACK, WHITE, true, calculate );

    
    // calculate button
    g_gui->AddButton( 0, 550, "ovalbuttonblue.bmp", "ovalbuttonblue.bmp", 
                       "Calculate", ARIAL, BLACK, BLACK, calculate );


    // the checkboxes
    g_gui->AddCheckbox( 120, 520, "checkboxup.bmp", "checkboxdown.bmp", 
                        "Theoretical Distribution", ARIAL, BLUE, WHITE, 
                        TheoreticalToggle );
    g_gui->AddCheckbox( 120, 550, "checkboxup.bmp", "checkboxdown.bmp", 
                        "Actual Distribution", ARIAL, RED, WHITE, 
                        ActualToggle );

    // the number of trials.
    g_gui->AddLabel( 400, 500, "Random Trials", ARIAL, BLACK, WHITE );
    g_gui->AddTextBox( 400, 520, 80, 20, g_trialstring, 6, ARIAL,
                       BLACK, WHITE, true, calculate );


    // the current sample buttons/labels.
    g_gui->AddLabel( 400, 550, "Current:", ARIAL, BLACK, WHITE );
    g_gui->AddButton( 400, 570, "littlebuttongrey-up.bmp", "littlebuttongrey-down.bmp", 
                       "<", SMALLARIAL, BLACK, BLACK, CurrentDown );
    g_gui->AddButton( 460, 570, "littlebuttongrey-up.bmp", "littlebuttongrey-down.bmp", 
                       ">", SMALLARIAL, BLACK, BLACK, CurrentUp );
    g_gui->AddTextBox( 420, 570, 40, 20, g_currentstring, 6, ARIAL,
                       BLACK, WHITE, false, 0 );


    g_gui->AddTextBox( 550, 520, 200, 20, g_theoreticalstring, 64, ARIAL,
                       BLACK, WHITE, false, 0 );
    g_gui->AddTextBox( 550, 550, 200, 20, g_actualstring, 64, ARIAL,
                       BLACK, WHITE, false, 0 );
    
    // create the graph bitmap    
    SDL_PixelFormat* pix = SDL_GetVideoInfo()->vfmt;
    g_graph = SDL_CreateRGBSurface( 0, 700, 500, pix->BitsPerPixel,
                                 pix->Rmask, pix->Gmask, pix->Bmask, pix->Amask );

    calculate();


    // main message loop.
    while( 1 )
    {
        //look for an event
        if( SDL_PollEvent( &event ) )
        {
            //an event was found
            if( event.type == SDL_QUIT ) 
                break;
            if( event.type == SDL_MOUSEBUTTONDOWN ) 
            {
                // get the mouse state.
                SDL_GetMouseState( &x, &y );

                // tell the GUI that a button has been pressed
                g_gui->MouseDown( x, y );
            }
            if( event.type == SDL_MOUSEBUTTONUP ) 
            {
                // get the mouse state.
                SDL_GetMouseState( &x, &y );

                // tell the GUI that a button has been released
                g_gui->MouseUp( x, y );
            }
            if( event.type == SDL_KEYDOWN )
            {
                // a key was pressed.
                if( event.key.keysym.sym == SDLK_ESCAPE )
                {
                    // if ESC was pressed, quit the program.
                    SDL_Event quit;
                    quit.type = SDL_QUIT;
                    SDL_PushEvent( &quit );
                }


                // tell the GUI that a key was pressed.
                g_gui->KeyDown( event.key.keysym.sym, 
                                event.key.keysym.mod,
                                event.key.keysym.unicode );
            }

            // only redraw when an event occurs.

            // create the percentage strings.
            sprintf( g_theoreticalstring, "Theoretical: %f%%", 
                     g_theoreticalfn[g_current - g_min] * 100.0f );

            sprintf( g_actualstring, "Actual: %f%%", 
                     g_actualfn[g_current - g_min] * 100.0f );

           
            g_gui->Draw();
    
            g_gui->Blit( g_graph, 100, 0 );
            g_gui->Line( 100, 0, 100, 600, GREY );
            g_gui->Line( 101, 0, 101, 600, BLACK );
            g_gui->Line( 100, 500, 800, 500, GREY );
            g_gui->Line( 100, 501, 800, 501, BLACK );

            x = (int)((float)(g_current - g_min) * (600.0f / (float)g_difference)) + 150; 
            g_gui->Line( x, 0, x, 500, BLACK );

            // tell the GUI to update itself
            g_gui->Update();
        }   // end event loop.

    }
  
    // done
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -