首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与AI的乒乓游戏

与AI的乒乓游戏
EN

Code Review用户
提问于 2014-12-28 20:59:58
回答 3查看 2.2K关注 0票数 2

我使用SDL2.0为图形编写了一个用C++编写的乒乓球游戏。关于这个代码,我有几个问题:

  1. 我如何使人工智能更好,以这样的方式,它实际上是愚蠢的?现在,我的人工智能每次都能把球还给我,这是不公平的。我希望这名球员至少能在某些时候进球。某种百分比的错误变量可能会起作用,但不确定。
  2. 我怎样才能修复某些功能的丑陋呢?目前,我的load_rendered_text()函数接受2种文本,并返回2种纹理,当它只需要1件文本来处理1种纹理时,会被调用两次。而且,我的Ball::move_ball()函数有超过10个if语句,检查各种条件。怎么解决这个问题呢?
  3. 我的评论太多了吗?评论不够吗?我通常尝试并瞄准自我文档化代码。这意味着大多数情况下,代码应该告诉您它在不需要注释的情况下所做的事情。为了实现这一点,我已经尽了最大努力使用一致的命名,并且易于理解变量名。如果您发现任何命名错误或在这方面可能更好的事情,请告诉我。

乒乓游戏代码

代码语言:javascript
复制
class Ball
{
public:
    const int BALL_WIDTH = 15;
    const int BALL_HEIGHT = 15;
    const float BALL_VELOCITY = 2;

    Ball();
    void init_ball_direction();
    void move_ball(float timeStep, SDL_Rect playerPaddle, SDL_Rect aiPaddle);
    void render_ball();

private:
    float ballPositionX, ballPositionY;
    float ballVelocityX, ballVelocityY;
    bool isMovingDown, isMovingUp;
    bool isMovingLeft, isMovingRight;

    SDL_Rect bCollider;
};

...

class AI
{
public:
    const float AI_VELOCITY = 3;

    void init_ai();
    void move_ai();
    void handle_ai_events();

    SDL_Rect aiPaddle;

private:
    float aiYPosition;
    float aiVelocity;
};

...

void Ball::move_ball(float timeStep, SDL_Rect playerPaddle, SDL_Rect aiPaddle)
{
    //move the ball, its collider, and the raycast. Check for collisions with the paddles
    //by calling the check_collision() function.
    if(ballPositionY + BALL_HEIGHT > SCREEN_HEIGHT){
        isMovingDown = false;
        isMovingUp = true;
    }

    if(ballPositionY < 0){
        isMovingDown = true;
        isMovingUp = false;
    }

    if(ballPositionX + BALL_WIDTH > SCREEN_WIDTH){
        ballPositionX = SCREEN_WIDTH/2;
    }

    if(ballPositionX < 0){
        ballPositionX = SCREEN_WIDTH/2;
    }

    if(check_collision(bCollider, playerPaddle)){
        isMovingLeft = false;
        isMovingRight = true;
    }

    if(check_collision(bCollider, aiPaddle)){
        isMovingRight = false;
        isMovingLeft = true;
    }

    if(isMovingUp){
        ballPositionY -= ballVelocityY;
        bCollider.y = ballPositionY;
        bRaycastLine.y = ballPositionY;
    }

    if(isMovingDown){
        ballPositionY += ballVelocityY;
        bCollider.y = ballPositionY;
        bRaycastLine.y = ballPositionY;
    }

    if(isMovingLeft){
        ballPositionX -= ballVelocityX;
        bCollider.x = ballPositionX;
        bRaycastLine.x = ballPositionX;
    }

    if(isMovingRight){
        ballPositionX += ballVelocityX;
        bCollider.x = ballPositionX;
        bRaycastLine.x = ballPositionX;
    }
}

...

void AI::init_ai()
{
    //initialize the AI, not much here becaue the AI is very basic.
    aiPaddle.h = 40;
    aiPaddle.w = 10;
    aiPaddle.x = SCREEN_WIDTH - aiPaddle.w;
    aiPaddle.y = SCREEN_HEIGHT/2 - aiPaddle.h/2;

    aiYPosition = aiPaddle.y;
    aiVelocity = 0;
}

void AI::handle_ai_events()
{
    //check if the raycasted line is above/below the AI paddle...
    if(bRaycastLine.y > aiPaddle.y + aiPaddle.h){
        aiVelocity += AI_VELOCITY;
    } else if(bRaycastLine.y < aiPaddle.y){
        aiVelocity -= AI_VELOCITY;
    }
}

void AI::move_ai()
{
    //apply the velocities to the AI...
    aiYPosition = aiVelocity;
    aiPaddle.y = aiYPosition;

    if(aiYPosition < 0){
        aiYPosition -= aiVelocity;
        aiPaddle.y = aiYPosition;
    }

    if(aiYPosition > aiPaddle.y + SCREEN_HEIGHT){
        aiYPosition += aiVelocity;
        aiPaddle.y = aiYPosition;
    }
}

bRaycastLine是一个跟踪球位置的SDL_Rect

EN

回答 3

Code Review用户

回答已采纳

发布于 2014-12-28 21:49:44

一种让人工智能“蠢蛋”的方法是给它一个障碍。你可以限制它的移动速度,直到它不总是赢。

另一种选择是在球弹出后随机化球的轨迹,然后给出关于球轨迹的有限信息,而是将其表示为潜在状态的集合,当球离AI桨越来越近时,它就会变窄。

为了使用这样的方法,你需要首先使人工智能变得更聪明,这样它就可以进行轨迹预测,并且仍然能够以有限的信息做出现实的反应。

不用说,这就更难了。

票数 2
EN

Code Review用户

发布于 2014-12-29 04:05:44

我不清楚你是否需要存储变量isMovingLeft..。假设你没有,你可以让函数move_ball简单一点。

代码语言:javascript
复制
void Ball::move_ball(float timeStep, SDL_Rect playerPaddle, SDL_Rect aiPaddle)
{
   int upDown = 0;
   int leftRight = 0;

   //move the ball, its collider, and the raycast. Check for collisions with the paddles
   //by calling the check_collision() function.
   if(ballPositionY + BALL_HEIGHT > SCREEN_HEIGHT){
      upDown = 1;
   }

   if(ballPositionY < 0){
      upDown = -1;
   }

   if(ballPositionX + BALL_WIDTH > SCREEN_WIDTH){
      ballPositionX = SCREEN_WIDTH/2;
   }

   if(ballPositionX < 0){
      ballPositionX = SCREEN_WIDTH/2;
   }

   if(check_collision(bCollider, playerPaddle)){
      leftRight = 1;
   }

   if(check_collision(bCollider, aiPaddle)){
      leftRight = -1;
   }

   ballPositionY -= upDown*ballVelocityY;;
   ballPositionX -= leftRight*ballVelocityX;

   if ( upDown != 0 ) {
      bCollider.y = ballPositionY;
      bRaycastLine.y = ballPositionY;
   }

   if ( leftRight != 0 ) {
      bCollider.x = ballPositionX;
      bRaycastLine.x = ballPositionX;
   }

}
票数 1
EN

Code Review用户

发布于 2015-02-12 23:46:33

有几件事在脑海中浮现:

  • 有限的速度:这似乎已经实现了,但你总是可以减少这个值。
  • 响应时间:如果你想接近人类所做的事情,那么你的人工智能必须有一个大于0的反应时间。一个简单的实现是当球达到一定的Y值时开始移动(当然,如果您从上到下玩,而且Y轴是垂直的)。
  • 预测:有一件事是把偏见放在你的人工智能的理想位置。一些现实的事情可能是设置你的人工智能的最终目的地在高斯分布围绕着球的预期位置。正如其他人所提到的,当球越来越近时,高斯形状会变窄(这就是人类所做的,他首先粗略估计,然后随着球越来越近,它就会变窄)。在这里帮助您实现:C++中的正态分布
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/75082

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档