我正在用C语言做一个学校项目,基本上我需要做的是创建一个智能体网格(人类,僵尸或无),并随机选择哪些是我手动控制的或"AI“控制的。基本上,人类需要逃离僵尸,僵尸必须追逐人类才能感染它们,当没有人类留下时,游戏就结束了。
问题是,在每一轮之前,应该随机选择谁先玩,为此我需要洗牌代理(不接触网格,因为代理位置保持不变,唯一变化的是它们在数组中的位置,我应该用它来挑选谁先玩)。
我遇到了一些关于混洗的问题,因为我调用了这个函数,在我混洗代理之后,我打印了他们的Ids。它只是给了我很多很多0,在一些随机数之间,比如3,6,10,等等,还有更多。
代码如下:
主文件:
#include "showworld.h"
#include "example.h"
#include "shuffle.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/** Horizontal world size. */
#define WORLD_X 20
/** Vertical world size. */
#define WORLD_Y 20
/**
* Structure defining agent properties.
*
* @note This is an example which will probably not work in a fully functional
* game. Students should develop their own implementation of
* ::get_agent_info_at() and agent/world data structures.
* */
typedef struct {
AGENT_TYPE type; /**< Agent type. */
unsigned char playable; /**< Is agent playable? */
unsigned short id; /**< Agent ID. */
} AGENT;
/**
* Structure defining world properties.
*
* @note This is an example which will probably not work in a fully functional
* game. Students should develop their own implementation of
* ::get_agent_info_at() and agent/world data structures.
* */
typedef struct {
AGENT *grid; /**< World is a grid composed of agents. */
unsigned int xsize; /**< Horizontal world size. */
unsigned int ysize; /**< Vertical world size. */
} WORLD;
/* This function is an implementation of the definition provided by the
* ::get_agent_info_at() function pointer. It only works for AGENT and WORLD
* example structures defined in this file. */
unsigned int example_get_ag_info(void *world, unsigned int x, unsigned int y);
int main() {
/* An instance of a WORLD structure. */
WORLD my_world;
/* An instance of a SHOWWORLD world display. */
SHOWWORLD *sw = NULL;
/* A by-dimensional array of agents, representing agents in a grid. */
AGENT agent_grid[WORLD_X][WORLD_Y];
/* Number of agents created so far. */
unsigned int nagents = 0;
/* Initialize world display. */
sw = showworld_new(WORLD_X, WORLD_Y, example_get_ag_info);
/* Initialize random number generator. */
srand(time(NULL));
/* **************************************************************** */
/* Cycle through all cells in grid and randomly place agents in it. */
/* **************************************************************** */
for (int i = 0; i < WORLD_X; ++i) {
for (int j = 0; j < WORLD_Y; ++j) {
/* Possible agent in grid. By default we assume there is none. */
AGENT ag = {None, 0, 0};
/* Obtain a probability between 0 and 99. */
unsigned char probability = rand() % 100;
/* There is 10% probability of creating an agent. */
if (probability < 10) {
/* If we got here, an agent will be placed at (i,j). */
/* Randomly define agent type. */
ag.type = (rand() % 2 == 0) ? Human : Zombie;
/* Give 10% probablity of agent being playable by user. */
ag.playable = (rand() % 10 == 0);
/* Assign agent ID and then increment number of agents so
far. */
ag.id = nagents++;
}
/* Assign possible agent to grid at (i,j). */
agent_grid[i][j] = ag;
}
}
/* ******************************* */
/* Populate the my_world variable. */
/* ******************************* */
/* A bidimensional array of agents can be interpreted as a pointer to
agents. */
my_world.grid = (AGENT *) agent_grid;
/* World size is defined by constants in this example. */
my_world.xsize = WORLD_X;
my_world.ysize = WORLD_Y;
/* ********************************************************************* */
/* Show world using the simple_show_world() function. This function can */
/* be used in the first part of the project. */
/* ********************************************************************* */
showworld_update(sw, &my_world);
shuffle(my_world.grid, nagents);
/* Before finishing, ask user to press ENTER. */
printf("Press ENTER to continue...");
getchar();
/* Destroy world display. */
showworld_destroy(sw);
/* Bye. */
return 0;
}
/**
* This function is an implementation of the ::get_agent_info_at() function
* definition. It only works for ::AGENT and ::WORLD structures defined in this
* example.
*
* It basically receives a pointer to a ::WORLD structure, obtains the AGENT
* structure in the given coordinates, and returns the agent information in a
* bit-packed `unsigned int`.
*
* @note This is an example which will probably not work in a fully functional
* game. Students should develop their own implementation of
* ::get_agent_info_at() and agent/world data structures.
*
* @param w Generic pointer to object representing the simulation world.
* @param x Horizontal coordinate of the simulation world from where to fetch
* the agent information.
* @param y Vertical coordinate of the simulation world from where to fetch
* the agent information.
* @return An integer containing bit-packed information about an agent, as
* follows: bits 0-1 (agent type), bit 2 (is agent playable), bits 3-18 (agent
* ID). Bits 19-31 are available for student-defined agent extensions.
* */
unsigned int example_get_ag_info(void *w, unsigned int x, unsigned int y) {
/* The agent information to return. */
unsigned int ag_info = 0;
/* Convert generic pointer to world to a WORLD object. */
WORLD *my_world = (WORLD *) w;
/* Check if the given (x,y) coordinates are within bounds of the world. */
if ((x >= my_world->xsize) || (y >= my_world->ysize)) {
/* If we got here, then the coordinates are off bounds. As such we will
report that the requested agent is of unknown type. No need to
specify agent ID or playable status, since the agent is unknown. */
ag_info = Unknown;
} else {
/* Given coordinates are within bounds, let's get and pack the request
agent information. */
/* Obtain agent at specified coordinates. */
AGENT ag = my_world->grid[x * my_world->xsize + y];
/* Is there an agent at (x,y)? */
if (ag.type == None) {
/* If there is no agent at the (x,y) coordinates, set agent type to
None. No need to specify agent ID or playable status, since
there is no agent here. */
ag_info = None;
} else {
/* If we get here it's because there is an agent at (x,y). Bit-pack
all the agent information as specified by the get_agent_info_at
function pointer definition. */
ag_info = (ag.id << 3) | (ag.playable << 2) | ag.type;
}
}
/* Return the requested agent information. */
return ag_info;
}下面是shuffle函数
#include "example.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(AGENT *agents, unsigned int nagents) {
printf("%s\n\n", "------------- Shuffling agents ----------------");
unsigned int i=0;
unsigned int j=0;
AGENT temp;
srand(time(NULL));
for (i = nagents - 1; i > 0; i--) {
j = (rand() % i);
temp = agents[i];
agents[i] = agents[j];
agents[j] = temp;
}
for (i = 0; i < nagents; i++) {
printf("\n\t%d", agents[i].id);
}这是showworld文件:
#include "showworld.h"
#include <stdio.h>
#include <stdlib.h>
/* The implementation of `SHOWWORLD` type used in this simple text-based world
* visualization code. In this simple case, we only need to keep track of the
* world dimensions and of the function pointer which knows how to read an
* agent from the world data structure.
*
* For a more complex implementation, for example based on the g2 library,
* it would also be necessary to keep the g2 device.
* */
struct showworld {
unsigned int xdim;
unsigned int ydim;
get_agent_info_at aginfo_func;
};
/* Create a new display/visualization object for the simulation world.
*
* This function obeys the `showworld_new()` prototype defined in
* `showworld.h`. */
SHOWWORLD *showworld_new(
unsigned int xdim,
unsigned int ydim,
get_agent_info_at aginfo_func) {
SHOWWORLD *sw = NULL;
sw = malloc(sizeof(SHOWWORLD));
sw->xdim = xdim;
sw->ydim = ydim;
sw->aginfo_func = aginfo_func;
return sw;
}
/* Destroy a display/visualization object for the simulation world.
*
* This function obeys the `showworld_destroy()` prototype defined in
* `showworld.h`. */
void showworld_destroy(SHOWWORLD *sw) {
free(sw);
}
/* Update the simulation world display/visualization.
*
* This function obeys the `showworld_update()` prototype defined in
* `showworld.h`. */
void showworld_update(SHOWWORLD *sw, void *w) {
printf("\n");
/* Cycle through all the rows */
for (unsigned int y = 0; y < sw->ydim; ++y) {
/* Cycle through all the columns for the current row */
for (unsigned int x = 0; x < sw->xdim; ++x) {
/* Get state of the world (in bit packed fashion) using the user
supplied function. */
unsigned int item = sw->aginfo_func(w, x, y);
/* Extract the agent type (2 bits). */
AGENT_TYPE ag_type = item & 0x3;
/* Extract whether the agent is playable (1 bit). */
unsigned char playable = (item >> 2) & 0x1;
/* Extract the agent ID (16 bits). */
unsigned short ag_id = (item >> 3) & 0xFFFF;
/* Determine the agent type. */
switch (ag_type) {
/* If no agent is present at (x,y) just print a dot. */
case None:
printf(" . ");
break;
/* If human agent present at (x,y) print 'h' or 'H'. */
case Human:
if (playable) {
/* Uppercase 'H' for player-controlled human agent. */
printf("H");
} else {
/* Lowercase 'h' for AI-controlled human agent. */
printf("h");
}
/* Print the agent ID in front of the 'h'/'H'. */
printf("%02X ", ag_id);
break;
/* If zombie agent present at (x,y) print 'z' or 'Z'. */
case Zombie:
if (playable) {
/* Uppercase 'Z' for player-controlled zombie agent. */
printf("Z");
} else {
/* Lowercase 'z' for AI-controlled zombie agent. */
printf("z");
}
/* Print the agent ID in front of the 'h'/'H'. */
printf("%02X ", ag_id);
break;
/* Print '?' if unknown type detected. This should *never*
happen. */
default:
printf("? ");
}
}
/* Print two newlines after each row. */
printf("\n\n");
}
/* Print a newline after world is shown/updated. */
printf("\n");
}发布于 2018-01-13 20:11:20
将所有这些代码剥离到相关的:
AGENT agent_grid[WORLD_X][WORLD_Y];
int nagents = populate_grid(agent_grid, WORLD_X, WORLD_Y, 10);
shuffle(agent_grid, nagents);在这里,我删除了my_world以关注网格,并创建了一个网格初始化函数,而不是进行内联初始化。假设的初始化函数int populate_grid(AGENT *grid, int rows, int cols, int percent)用代理填充网格的一个样本(其余的填充类型为NONE`的AGENT对象)。然后,它返回创建的样本大小。
然后,使用您对shuffle的调用对网格进行混洗,该调用采用一个AGENT对象数组并对它们进行混洗。
问题不是很明显吗?agent_grid并不是shuffle所期望的大小为nagents的数组。它是一个大小为WORLD_X * WORLD_Y的二维数组。在实践中,这意味着您正在混洗前40个(或更多)网格插槽,而其他360个网格插槽保持不变;我们可以预期这些网格插槽中的90%是空的,这似乎与您所描述的结果(“许多许多0”)相匹配。
发布于 2018-01-13 15:56:26
这是大量的代码,但我首先要查找的是边界错误。请确保数组索引一致,并且不要访问数组中有效范围之外的项。
下一个问题是你的洗牌。Jeff Atwood wrote an entire blog about it.
祝好运!
https://stackoverflow.com/questions/48236807
复制相似问题