简单游戏场景用户模拟

帮朋友写的, 很简单...

还是贴出来, 希望能对看客有所帮助, 也希望看客能对我有所帮助...


谢谢.


#include <stdio.h>
#include <stdlib.h>
/**
 * author: selfimpr
 * blog: http://blog.csdn.net/lgg201
 * mail: lgg860911@yahoo.com.cn
 */

struct UserPool {
	struct User *head;			/* 所分配存储空间首指针 */
	struct User *useable;		/* 当前未使用的存储空间首指针 */
	struct User *free;			/* 空闲链表首指针 */
	int			used;			/* 内存池中已在线的用户数 */
	int			alloced;		/* 分配的内存池大小 */
};	/* 用户内存池 */

struct User {
	int				uid;		/* 用户标识 */
	int				fd;			/* 文件描述符 */
	struct Map		*map_p;		/* 所在地图 */
	int				map_i;		/* 在所在地图用户数组中的下标 */
	struct User		*next;		/* 作为内存池空闲链表时的构造指针 */
	struct UserPool	*pool;		/* 所在内存池 */
	int				isfree;		/* 是否空闲(1表示用户已离线, 空间可重用) */
	int				pool_i;		/* 在内存池中的下标 */
};	/* 用户 */

struct Map {
	struct User	**users;	/* 用户数组 */
	int			alloced;	/* 已分配用户数组大小 */
	int			used;		/* 已使用用户数组大小 */
};	/* 地图 */

struct HashTableElement {
	unsigned int				key;		/* 键 */
	void						*value;		/* 值 */
	struct HashTableElement		*next;		/* 下一个节点 */
};	/* 哈希表元素 */

struct HashTable {
	struct HashTableElement		*elements;		/* 存储数据的链表数组 */
	unsigned int				size;			/* 哈希表大小 */
};	/* 哈希表 */

/* 创建哈希表 */
struct HashTable *hash_table_create(unsigned int size) {
	struct HashTable	*ht;

	ht				= (struct HashTable *)malloc(sizeof(struct HashTable));
	if ( ht == NULL ) 
		goto failed;
	
	ht->size		= size;
	ht->elements	= (struct HashTableElement *)calloc(size, sizeof(struct HashTableElement));
	if ( ht->elements == NULL )
		goto failed;

	return ht;

failed:
	printf("hash_table_create failed\n");
	if ( ht != NULL ) {
		if ( ht->elements != NULL )
			free(ht->elements);
		free(ht);
	}
	return NULL;
}

/* 向哈希表中写入或更新数据 */
int hash_table_add_or_update(struct HashTable *ht, unsigned int k, void *value) {
	struct HashTableElement		*h, *e, *n;

	h	= &(ht->elements[k % ht->size]);
	e	= h->next;

	if ( e == NULL ) {
		e	= h;
		goto insert;
	}

	do {
		if ( e->key == k )
			goto update;
		else
			e	= e->next;
	} while ( e->next != NULL );
	
insert:
	n			= (struct HashTableElement *)calloc(1, sizeof(struct HashTableElement));
	n->key		= k;
	n->value	= value;
	e->next		= n;

	return (0);

update:
	e->value	= value;
	return (0);
}

/* 在哈希表中查找数据 */
struct HashTableElement *hash_table_find(struct HashTable *ht, unsigned int k) {
	struct HashTableElement	*h, *e;

	h	= &(ht->elements[k % ht->size]);
	e	= h->next;

	if ( e == NULL )
		goto failed;
	
	do {
		if ( e->key == k )
			return e;
		else 
			e	= e->next;
	} while ( e != NULL );
	
failed:
	return NULL;
}

/* 从哈希表中删除数据 */
int hash_table_delete(struct HashTable *ht, unsigned int k) {
	struct HashTableElement	*p, *e;

	p	= &(ht->elements[k % ht->size]);
	e	= p->next;

	if ( e == NULL )
		goto failed;
	
	do {
		if ( e->key == k ) {
			p->next	= e->next;
			free(e);
			return (0);
		} else {
			p	= e;
			e	= e->next;
		}
	} while ( e != NULL );

failed:
	return (-1);
}

/* 输出哈希表数据 */
void hash_table_dump(struct HashTable *ht, char *(*to_string)(void *)) {
	int						i;
	struct HashTableElement	*h, *e;

	for ( i = 0; i < ht->size; i ++ ) {
		h	= &(ht->elements[i]);
		e	= h->next;
		while ( e != NULL ) {
			printf("%d: %s\n", e->key, to_string(e->value));
			e	= e->next;
		}
	}
}

/* 用于哈希表测试用例的字符串转换函数 */
char *empty_to_string(void *v) {
	return (char *)v;
}

/* 哈希表测试用例 */
void hash_table_test() {
	struct HashTable	*ht;

	ht	= hash_table_create((unsigned int)30);

	hash_table_add_or_update(ht, 1, (void *)"one");
	hash_table_add_or_update(ht, 2, (void *)"two");
	hash_table_add_or_update(ht, 3, (void *)"three");
	hash_table_add_or_update(ht, 4, (void *)"four");
	hash_table_add_or_update(ht, 1, (void *)"first-one");
	hash_table_add_or_update(ht, 2, (void *)"second-two");
	hash_table_add_or_update(ht, 3, (void *)"third-three");
	hash_table_add_or_update(ht, 4, (void *)"forth-four");
	hash_table_delete(ht, 3);

	hash_table_dump(ht, empty_to_string);
}

/* 地图创建 */
struct Map *map_create(int num) {
	struct Map	*map;

	map				= (struct Map *) malloc(sizeof(struct Map));
	if ( map == NULL )
		goto failed;

	map->users		= (struct User **) calloc(num, sizeof(struct User *));
	map->alloced	= num;
	map->used		= 0;

	return map;
failed:
	if ( map != NULL )
		free(map);
	return NULL;
}

/* 用户进入地图 */
int map_user_enter(struct Map *map, struct User *user) {
	int		i;

	for ( i = 0; i < map->alloced; i ++ ) {
		if ( map->users[i] == NULL ) {
			map->users[i]	= user;
			user->map_p		= map;
			user->map_i		= i;
			map->used ++;
			return (0);
		}
	}
	return (-1);
}

/* 用户离开地图 */
int map_user_leave(struct User *user) {
	user->map_p->users[user->map_i]	= NULL;
	user->map_p->used --;
	user->map_i		= 0;
	user->map_p		= NULL;
}

/* 创建用户内存池 */
struct UserPool *user_pool_create(int size) {
	struct UserPool	*pool;

	pool	= (struct UserPool *)malloc(sizeof(struct UserPool));

	pool->head		= (struct User *)calloc(size, sizeof(struct User));
	pool->useable	= pool->head;
	pool->free		= NULL;
	pool->alloced	= size;
	pool->used		= 0;

	return (pool);
failed:
	if ( pool != NULL ) {
		if ( pool->head != NULL ) 
			free(pool->head);
		free(pool);
	}
	return (NULL);
}

/* 从内存池分配一个用户的空间 */
struct User *user_pool_alloc_user(struct UserPool *pool) {
	struct User	*u;
	/* TODO 此处应该是内存池扩展逻辑, 比较复杂, 未实现 */
	
	/* 从空闲链表中分配 */
	if ( pool->free != NULL ) {
		u			= pool->free;
		u->isfree	= 0;
		pool->free	= pool->free->next;
		pool->used ++;
		return u;
	}

	/* 从未使用空间中分配 */
	u			= pool->useable;
	u->pool		= pool;
	u->pool_i	= pool->useable - pool->head;
	pool->useable ++;
	pool->used ++;
	return u;
}

/* 从内存池中释放一个用户 */
void user_pool_free_user(struct User *user) {
	struct UserPool	*pool;

	pool			= user->pool;
	user->isfree	= 1;
	/* 将被释放的空间放入空闲链表 */
	user->next		= pool->free;
	pool->free		= user;
	/* 更新用户计数 */
	pool->used --;
}

struct Map			**maps;		/* 所有的地图 */
struct HashTable	*user_ht;	/* 用户哈希表 */
struct UserPool		*user_pool;	/* 用户内存池 */

/* 地图数量 */
int map_num = 1;
/* 地图最大人数 */
int map_user_num = 10;
/* 总人数上限 */
int user_num = 100;

/* 游戏初始化 */
int game_init() {
	int		i;

	/* 地图初始化 */
	maps	= (struct Map **)calloc(map_num, sizeof(struct Map *));

	for ( i = 0; i < map_num; i ++ ) {
		maps[i]	= map_create(map_user_num);
	}

	/* 用户存储初始化 */
	user_pool	= user_pool_create(user_num);

	/* 用户哈希表初始化 */

	user_ht		= hash_table_create(user_num);
}

/* 用户登入 */
void user_login(int uid, int fd) {
	struct User	*user;

	/* 在内存池中为用户分配空间 */
	user		= user_pool_alloc_user(user_pool);

	/* 初始化用户基本信息 */
	user->uid	= uid;
	user->fd	= fd;

	/* 用户进入地图 */
	map_user_enter(maps[0], user);

	/* 将用户放入哈希表便于查找 */
	hash_table_add_or_update(user_ht, uid, (void *)user);
}

/* 用户登出 */
void user_logout(int uid) {
	struct HashTableElement	*e;
	struct User 			*user;

	/* 从哈希表中查找用户 */
	e		= (struct HashTableElement *)hash_table_find(user_ht, uid);
	user	= (struct User *)e->value;

	/* 用户离开地图 */
	map_user_leave(user);

	/* 从内存池中释放用户 */
	user_pool_free_user(user);

	/* 从哈希表中移除用户 */
	hash_table_delete(user_ht, uid);
}

/* 将用户转换为字符串 */
char *user_to_string(void *value) {
	static char	buffer[1024];
	struct User	*user;

	user	= (struct User *)value;
	sprintf(buffer, "uid: %d, fd: %d, map_p: %p, map_i: %d, pool: %p, pool_i: %d, ptr: %p, next: %p", 
		user->uid, user->fd, user->map_p, user->map_i, user->pool, user->pool_i, user, user->next);
	return buffer;
}

int main(int argc, char *argv[]) {
	/* 初始化游戏 */
	game_init();

	int				i;
	struct User 	*tmp;

	/* 登入十个用户 */
	for ( i = 1; i <= 10; i ++ ) 
		user_login(i, i);

	/* 登出三个用户 */
	user_logout(2);
	user_logout(3);
	user_logout(4);

	/* 打印在线用户信息 */
	hash_table_dump(user_ht, user_to_string);

	/* 打印用户内存池的空闲链表 */
	printf("\nfree elements:\n");
	for ( tmp = user_pool->free; tmp != NULL; tmp = tmp->next )
		printf("%s\n", user_to_string((void *)tmp));
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值