【问题标题】:How to randomize the creation of objects of different classes? c++如何随机创建不同类的对象? C++
【发布时间】:2020-11-29 08:55:51
【问题描述】:

我正在使用 c++ 中的类进行项目,其中包括一辆可以避开板上障碍物的汽车。我想随机化 EnemiesCar、Nail、Hole 类对象的外观(最后两个是第一个的子类)。问题是当我生成随机数时,它变化太快,然后出现的对象消失了(板上的对象间歇性地出现在其他对象之间,因为随机数变化太快)。我该如何解决这个问题?是否有其他解决方案可以随机化类对象? (我尝试在 Game::randomAppear(EnemiesCar &myEn, Nail &myNe, Hole &myHo) 中实现这个功能,下面我只留下 EnemiesCar 类,因为它的子类相似)。

Game.cpp

#include "Game.h"
#include "Nail.h"
#include "EnemiesCar.h"
#include "Car.h"
#include "Hole.h"
#include <windows.h>
#include <iostream>
#include <thread>
#include <stdlib.h>     /* srand, rand */
#include <ctime>
using namespace std;

Game::Game(){
    running = true;
    counter = 100;
    maxScore = 0;
    maxLevel = 1;
    timeS = 100.0;
    level = 1;
    levelUp = 1000;
    levelDown = 0;
}

void Game::gotoXY(int x, int y)
{
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

void Game::resetBoard()
{
    for(int j=0;j<20;j++){
        for(int i=1;i<20;i++){
            matrix[i][j]=0;
        }
    }
}

void Game::createTab()
{
    for(int j=0;j<20;j++){
        for(int i=0;i<21;i++){
            if(i==0 || i==20){
                    gotoXY(i,j);
                    cout<<"b";
            }else if(j == 19){
                    gotoXY(i,j);
                    cout<<"*";
            }else if(matrix[i][j]==1){
                    gotoXY(i,j);
                    cout<<"m";
            }else if(matrix[i][j]==2){
                    gotoXY(i,j);
                    cout<<"e";
            }else if(matrix[i][j]==3){
                    gotoXY(i,j);
                    cout<<"c";
            }else if(matrix[i][j]==4){
                    gotoXY(i,j);
                    cout<<"h";
            }else {
                gotoXY(i,j);
                cout<<" ";
            }
        }
    }
}



void Game::checkSamePosition(EnemiesCar EN, Nail NE)
{
    if(NE.xPos == EN.xPos && NE.yPos == EN.yPos){
        NE.xPos = NE.xPos + 2;
    }
}

int Game::checkMaxScore()
{
    if(maxScore < counter){
        maxScore = counter;
    }
    return maxScore;
}

int Game::checkMaxLevel()
{
    if(maxLevel < level){
        maxLevel = level;
    }
    return maxLevel;
}

void Game::TabLevelUp()
{
    system("cls");
    gotoXY(5, 5);
    cout << "Next Level" << endl;
    gotoXY(5, 7);
    cout << "Level: " << level;
}

void Game::TabLevelDown()
{
    system("cls");
    gotoXY(5, 5);
    cout << "Previous Level" << endl;
    gotoXY(5, 7);
    cout << "Level: " << level;
}

void Game::gameLevels(Car &car)
{
    if(counter == levelUp){
        level++;
        TabLevelUp();
        Sleep(5000);
        gotoXY(40, 9);
        cout << "level " << level;
        levelDown = levelUp;
        levelUp = levelUp + 1000;
        gotoXY(40, 10);
        cout << "next " << levelUp;
        if(timeS >= 40){
            double update = timeS - 20.0;
            timeS = update;
            gotoXY(40, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else if(timeS == 20 || timeS == 30){
            double update = timeS - 10.0;
            timeS = update;
            gotoXY(40, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else if(timeS >= 10 && timeS < 20){
            double update = timeS - 5.0;
            timeS = update;
            gotoXY(40, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else if(timeS == 0){
            Sleep(timeS);
        }else{
            double update = timeS - 0.5;
            timeS = update;
            gotoXY(40, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }
        playGame(car);
    }else if(counter < levelDown){
        level--;
        TabLevelDown();
        Sleep(5000);
        levelUp = levelDown;
        levelDown = levelDown - 1000;
        if(timeS >= 40 && timeS < 100){
            double update = timeS + 20.0;
            timeS = update;
            gotoXY(45, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else if(timeS == 20 || timeS == 30){
            double update = timeS + 10.0;
            timeS = update;
            gotoXY(45, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else if(timeS == 10 && timeS < 20){
            double update = timeS + 5.0;
            timeS = update;
            gotoXY(45, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else if(timeS < 10 && level <= 17){
            double update = timeS + 0.5;
            timeS = update;
            gotoXY(45, 7);
            cout << "tmpIf " << timeS;
            Sleep(update);
        }else{
            Sleep(timeS);
        }
        playGame(car);
    }else{
        Sleep(timeS);
    }
}

void Game::showLevelScore()
{
    gotoXY(50, 1);
    cout<<"Score: " << counter;
    gotoXY(50, 3);
    cout<<"Level: " << level;
}

void Game::gameEnd()
{
    if(counter <= 0){
        running = false;
        Sleep(1000);
        system("cls");
        gotoXY(5,4);
        cout << "GAME OVER!!!";
        gotoXY(5,6);
        cout << "MAX LEVEL: " << checkMaxLevel();
        gotoXY(5,7);
        cout << "MAX SCORE: " << checkMaxScore();
        gotoXY(0,0);
    }
}
int Game::generateRandomNumber()
{
    int rEne = rand() % 3;
    gotoXY(50, 5);
    cout << "R: " << rEne << endl;
    return rEne;
}

void Game::randomAppear(EnemiesCar &myEn, Nail &myNe, Hole &myHo)
{
    int rEne = generateRandomNumber();
    if(rEne == 0){
        myEn.appear();
        myEn.drawEnemies(myEn.xPos, myEn.yPos, matrix);
        myEn.move();
    }else if(rEne == 1){
        myNe.appear();
        myNe.drawNails(myNe.xPos, myNe.yPos, matrix);
        myNe.move();
    }else{
        myHo.appear();
        myHo.drawHoles(myHo.xPos, myHo.yPos, matrix);
        myHo.move();
    }
}


void Game::playGame(Car &mycar){

    EnemiesCar myEnmCar = EnemiesCar();
    Nail nails = Nail();
    Hole holes = Hole();

    while(this->running){

        srand (time(NULL));
        resetBoard();

        randomAppear(myEnmCar, nails, holes);
        
        checkSamePosition(myEnmCar, nails);

        /*myEnmCar.appear();
        myEnmCar.drawEnemies(myEnmCar.xPos, myEnmCar.yPos, matrix);
        myEnmCar.move();*/
        /*gotoXY(3, 22);
        cout << "enmpos: " << myEnmCar.xPos << myEnmCar.yPos << endl;*/

        /*nails.appear();
        nails.drawNails(nails.xPos, nails.yPos, matrix);
        nails.move();

        holes.appear();
        holes.drawHoles(holes.xPos, holes.yPos, matrix);
        holes.move();*/

        mycar.drawCar(mycar.xPos, mycar.yPos, matrix);
        mycar.checkCollusion(myEnmCar, nails, holes, &counter, &level);

        createTab();

        myEnmCar.addScore(mycar, &counter);
        nails.addScore(mycar, &counter);
        holes.addScore(mycar, &counter);


        showLevelScore();

        checkMaxLevel();
        checkMaxScore();

        gameEnd();

        gameLevels(mycar);

    }
}

void Game::startGame()
{
    srand (time(NULL));
    Car mycar = Car();


    thread myThread(&Car::myListener, &mycar, &mycar);


    playGame(mycar);


    Sleep(5000);


    myThread.detach();
}

EnemiesCar.h

#ifndef ENEMIESCAR_H
#define ENEMIESCAR_H
#include "Game.h"

class Game;
class Car;
class Nail;

class EnemiesCar
{
    public:
        const int xInit[9] = {2, 4, 6, 8, 10, 12, 14, 16, 18};
        int xPos;
        int yPos;
        Game games = Game();

        EnemiesCar();
        void appear();
        void drawEnemies(int x, int y, int myMatr[21][20]);
        //void draw();
        void move();
        void addScore(Car car, int *countScore);
};

#endif // ENEMIESCAR_H

EnemiesCar.cpp

#include <windows.h>
#include <iostream>
#include "EnemiesCar.h"
#include "Game.h"
#include "Car.h"
#include "Nail.h"
using namespace std;

EnemiesCar::EnemiesCar()
{
        int randomX = rand() % 6;
        xPos=xInit[randomX];
        yPos=0;
}

/*void EnemiesCar::drawEnemies(int x, int y)
{
    Game games = Game();
    if(y<20 && y>=-0){
        games.matrix[x][y] = 2;
        cout << "drawEne" <<endl;
    }
}*/

void EnemiesCar::appear()
{
    if(yPos==18){
        int randomNo = rand() % 21;
        /*games.gotoXY(35, 7);
        cout << "a: " << randomNo << " ";*/
        if(randomNo >= 0 && randomNo <= 3){
            xPos = 2;
        }else if(randomNo == 4 || randomNo == 5){
            xPos = 4;
        }else if(randomNo == 6 || randomNo == 7){
            xPos = 6;
        }else if(randomNo == 8 || randomNo == 9){
            xPos = 8;
        }else if(randomNo == 10 || randomNo == 11){
            xPos = 10;
        }else if(randomNo == 12 || randomNo == 13){
            xPos = 12;
        }else if(randomNo == 14 || randomNo == 15){
            xPos = 14;
        }else if(randomNo == 16 || randomNo == 17){
            xPos = 16;
        }else{
            xPos = 18;
        }
        yPos = -3;
    }
}

void EnemiesCar::drawEnemies(int x, int y, int myMatr[21][20])
{
    if(y<20 && y>=-0){
        myMatr[x][y] = 2;
        myMatr[x-1][y+1] = 2;
        myMatr[x+1][y+1] = 2;
        myMatr[x][y+1] = 2;
        myMatr[x][y+2] = 2;
    }
}

void EnemiesCar::move()
{
    yPos++;
}

void EnemiesCar::addScore(Car car, int *countScore)
{
    if((this->xPos <= car.xPos-3 && this->yPos == 16) || (this->xPos >= car.xPos+3 && this->yPos == 16)){
        *countScore = *countScore + 100;
    }
}

【问题讨论】:

  • 只需在02 范围内获取一个随机数(使用std::uniform_int_distribution 非常简单),并为每种情况获取一个switch
  • 或者如果都有一个共同的基类(或者本身就是基类),那么一个X元素数组,每个元素都是一个lambda,它创建了适当的对象,并且返回类型是指向基类的指针。然后在0X - 1(含)范围内创建一个随机数,作为调用工厂函数的索引。
  • “变化太快”到底是什么意思?每当你生成一个随机对象时,你都会得到一个(新的)随机对象。您是否希望获得与以前相同的产品?
  • @einpoklum 我给你举个例子,当 rand() 生成第一个数字,例如 0,从我的函数中出现一个 EnemiesCar,但是 EnemiesCar 没有时间到达底部棋盘,因为 rand () 生成另一个随机数,例如 1(因此出现 Nail),而之前出现的 EnemiesCar 消失了(如果 rand () 再次出现 0,则会重新出现)。我希望我是清楚的。

标签: c++ oop c++11 random time


【解决方案1】:

看来您需要做的是将外观/绘图与随机数的生成分开。您需要跟踪已经生成的“随机敌人”,并在绘制棋盘时考虑它们——而且只考虑它们;与此无关,每隔几回合或由适当的事件触发时,生成一个新的随机敌人/汽车/任何东西,将其添加到已生成的集合中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    相关资源
    最近更新 更多