プロが教えるわが家の防犯対策術!

現在 簡単なパックマンゲームを作成しています。
以下のプログラムだと、
・敵が壁にあたると全く動かなくなる
という問題点があります。なので、例えば、「動ける(壁でない)方向のうち、移動後の距離が一番自機に近い方向に移動する」というアルゴリズムにしようと思ったのですが、全くコードが思い浮かべません。
どんなコードをかけばいいでしょうか。
できればコードを具体的に教えていただきたいです。
お願いいたします。

#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h> // system()
#include <windows.h> // Sleep()
#include <conio.h> // kbhit()

#define SIZE 15 // 一辺の長さ
#define EMPTY 0 // 何もない場所は0
#define WALL 1 // 壁
#define FOOD 2 // えさ(ドット)
#define POWER_FOOD 4 //パワーエサ
#define PACMAN 3// 主人公

#define SIZE 15 // 一辺の長さ
#define EMPTY 0 // 何もない場所は0
#define WALL 1  // 壁
#define FOOD 2  // えさ(ドット)
#define PACMAN 3// 主人公
 
int main()
{
    int wait_time = 300;
    int x, y;
    int food_count = 0;//エサの個数
    int cx, cy;//パックマン
    int ex, ey;//敵
    int key;
    int point = 0;
    int kx, ky;//自機の座標を保存
    int mx, my;//敵機の座標を保存
    int life = 3;
    // 壁 1、えさ 2、空白 0
    // field[y][x]となる
    int field[SIZE][SIZE] =
    {
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
      ・・・・・・・・・
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
    };
 
   
   
    cx = 7, cy = 7; //パックマンの初期位置
    ex = 1, ey = 1;//敵の初期位置
   
//エサの個数を数える
    for (y = 0; y < SIZE; y++)
    {
        for (x = 0; x < SIZE; x++)
        {
            if (field[y][x] == FOOD)
                food_count++;
        }
 
    }
 
    while (1)
    {
        // まずはPACMANの動き
 
        if (kbhit())
        {
            key = getch();//
            kx = cx, ky = cy;//自機の座標を保存する
            switch (key)
            {
            case '4':
                cx--;
                break;
            case '6':
                cx++;
                break;
            case '2':
                cy++;
                break;
            case '8':
                cy--;
                break;
            }
 
            cx = (cx + SIZE) % SIZE; //ワープ           
            switch (field[cy][cx])
            {
            case WALL://壁
                cx = kx, cy = ky; //動けないので cx, cy を元に戻す
                                 
                break;
            case FOOD:
                field[cy][cx] = 0;//餌を食べると餌が消える
                point += 10;      //得点加算
                food_count--;     //餌の数を減らしていく
                break;
            }
            if (cx == ex && cy == ey)
                life--;
        }

// 敵機の動き
       
mx = ex; my = ey;//敵機の座標を保存する
 
        if (ex > cx)
            ex--;
        else if (ex < cx)
            ex++;
        else if (ey > cy)
            ey--;
        else if (ey < cy)
            ey++;
       
        if (field[ey][ex] == WALL)  //もし敵機が壁に当たったらもとの座標に戻す。
        {
            ex = mx; ey = my;
        }
        ex = (ex + SIZE) % SIZE; //ワープ
 
        if (cx == ex && cy == ey) {
            life--;
            ex = 7, ey = 7;
            Sleep(wait_time);
        }
//画面表示
for (y = 0; y < SIZE; y++) {
            for (x = 0; x < SIZE; x++) {
                if (x == cx && y == cy)
                    printf("C ");
                else if (x == ex && y == ey)
                    printf("◇");
                else if (field[y][x] == FOOD)
                    printf(". ");
                else if (field[y][x] == WALL)
                    printf("■");
                else
                    printf(" ");
            }
            printf("\n");
        }

        printf("\n");
        printf(" (cx,cy) = (%d, %d)\n", cx, cy);
        printf(" point: %d\n", point);
        printf("  LIFE: %d\n", life);
 
        if (life == 0)
        {
            printf("game over\n");
         
            Sleep(wait_time);
            break;
        }
 
        if (food_count == 0)    
        {
            printf("game crer\n");
            Sleep(wait_time);
            break;
 
        }
        Sleep(wait_time);//

A 回答 (1件)

こんなかんじですか?


※実際にコンパイルしていませんので、入力ミスなどでエラーになるかもしれません。
 考え方だけ読み取って下さい。
※最小距離が同じ方向が複数あった場合、乱数などで方向を選択したようが良いですが
 下には、その処理はありません。
※数学的な意味での距離の計算は、√(ex-cx)^2+(ey-cy)^2と、ルートを使いますが、
 このプログラム上では意味がない(処理の無駄な)ので使用していません。

int delta = {{0,-1}, {1,0}, {0,1}, {-1,0}}; // 上、右、下、左方向の座標差分
int min_distance = 1000000; // 最小距離、初期値としてフィールド上の距離として存在しない大きい値をいれておく
int dir; // 方向
int d; // 距離
int go_dir; // 敵の進むべき方向

for(dir = 0; dir < 4; dir++){
  // 移動方向が壁ならば無視
  if(field[ey+delta[dir][1]][ex+delta[dir][1]] == WALL) continue;
  // 距離の計算
  d = (ex-cx+delta[dir][0])*(ex-cx+delta[dir][0])+(xy-cy+delta[dir][1])*(xy-cy+delta[dir][1])
  // 距離がmin_distanceより小さければ、その方向を最小距離方向にする
  if(d < min_distance){
    min_distance = d;
    go_dir = dir;
  }
}

// 敵の座標を更新(移動)
ex += delta[go_dir][0]];
ey += delta[go_dir][1]];
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A