完成链表的学习后,作为一个小实践项目实现俄罗斯轮盘赌。

轮盘赌游戏基于单循环链表实现,使用C语言的rand函数生成随机数,注意要不断更新随机数种子
俄罗斯轮盘赌,想必很多人都听说过,一种残忍的赌博游戏。游戏的道具是一把左轮手枪,
其规则也很简单:在左轮手枪中的 6 个弹槽中随意放入一颗或者多颗子弹,在任意旋转转轮之后,关上转轮。
游戏的参加者轮流把手枪对着自己,扣动扳机:中枪或是怯场,即为输的一方;坚持到最后的即为胜者。

实践项目同轮盘赌类似,游戏规则:n 个参加者排成一个环,每次由主持向左轮手枪中装一颗子弹,并随机转动关上转轮,游戏从第一个人开始,轮流拿枪;中枪者退出赌桌,退出者的下一个人作为第一人开始下一轮游戏。直至最后剩余一个人,即为胜者。要求:模拟轮盘赌的游戏规则,找到游戏的最终胜者。

c语言代码实现:注意这里使用的delete节点函数参数用pos(位置)而不是ele(元素值)比较恰当

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>  //signal()
#include<string.h>
#include<sys/stat.h>
#include<time.h>
#include<stdarg.h>

#if 1
#define INFO_DEBUG    "%d lines in "__FILE__", complie time is "__TIME__" "__DATE__" \n",__LINE__
#define ADI_RUN_ERROR      1
#define ADI_NULL_POINTER  -1
#define ADI_OK             0
#define ADI_PRINT         printf("[%s][%d]:",__FUNCTION__,__LINE__);printf
#define ADI_ASSERT(c,prt,ret)       if(c) {printf(prt);return ret;}
#endif

/*
俄罗斯轮盘赌,想必很多人都听说过,一种残忍的赌博游戏。游戏的道具是一把左轮手枪,
其规则也很简单:在左轮手枪中的 6 个弹槽中随意放入一颗或者多颗子弹,在任意旋转转轮之后,关上转轮。
游戏的参加者轮流把手枪对着自己,扣动扳机:中枪或是怯场,即为输的一方;坚持到最后的即为胜者。
本节实践项目同轮盘赌类似,游戏规则:n 个参加者排成一个环,每次由主持向左轮手枪中装一颗子弹,并随机转动关上转轮,游戏从第一个人开始,轮流拿枪;
中枪者退出赌桌,退出者的下一个人作为第一人开始下一轮游戏。直至最后剩余一个人,即为胜者。要求:模拟轮盘赌的游戏规则,找到游戏的最终胜者。
*/

typedef struct list{
    int elem;
    struct list *next;
}list;

#define PARAM_FAIL -1
#define P_NULL -2
#define SUCCESS 0
#define SIZE_GUN 6 //弹容量6发

/*初始化:只创建头结点*/
list* initList()
{
    list *head = (list*)malloc(sizeof(list));
    if(NULL==head) {printf("NULL");return head;}
    head->next = head;
    return head;
}

/*pos从0开始,pos=0为第一个*/
/*如果循环链表插入操作指定插入位置pos,会麻烦些,如下,如果不指定位置,默认插入到最后,会比较简单*/
int insertList(list *list_insert,int elem,int pos)
{
    int i=0;
    if(NULL == list_insert)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }

    list *head = list_insert;//取头指针
    while(i<pos && list_insert != head->next)
    {
        head = head->next;
        i++;
        //i比head快一个,i=1时head指向的是第0个元素
    }

    if((list_insert==head->next)&&(i<pos))//已经到链表尾部,但是pos>i,说明指定的插入位置超过了链表的末尾位置
    {
	ADI_PRINT("pos = %d, list's last = %d,pos>i,insert err!\n",pos,i);
	return PARAM_FAIL;
    }
    else
    {
	list *node = (list*)malloc(sizeof(list));
	if(NULL==node) {printf("NULL");return P_NULL;}
	node->next = head->next;
	node->elem = elem;
	head->next = node;
	ADI_PRINT("insert elem = %d\n",elem);
    }

    return SUCCESS;
}


/*pos从0开始,pos=0为第一个*/
int replaceList(list *list_insert,int elem,int pos)
{
    int i=0;
    if(NULL == list_insert)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }

    list *head = list_insert;//取头指针
    while(i<pos && list_insert != head->next)
    {
        head = head->next;
        i++;
        //i比head快一个,i=1时head指向的是第0个元素
    }

    if(list_insert==head->next)//已经到链表尾部,说明指定的修改位置超过了链表原有大小
    {
	ADI_PRINT("pos = %d, list's last = %d,change err!\n",pos,i);
	return PARAM_FAIL;
    }
    else
    {
	head->next->elem = elem;
	ADI_PRINT("change elem = %d,pos = %d\n",elem,pos);
    }

    return SUCCESS;
}

/*指定删除元素的值*/
/*
int delList(list *list_insert,int elem)
{
    if(NULL == list_insert)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }

    list *head = list_insert;
    while(list_insert != head->next)
    {
    	if(elem == head->next->elem)
	{
	    list *del = head->next;
            head->next = head->next->next;
            free(del);
            ADI_PRINT("del ele = %d\n",elem);
            return SUCCESS;
	}
	head = head->next;
    }

	ADI_PRINT("can not find ele = %d\n",elem);
    return PARAM_FAIL;
}
*/

/*指定删除元素的位置*/
int delList(list *list_insert,int pos)
{
    if(NULL == list_insert)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }

    list *head = list_insert;
    int i = 0;
    while(list_insert != head->next)
    {
        if(pos == i)
        {
	    list *del = head->next;
            head->next = head->next->next;
            ADI_PRINT("del pos = %d,ele = %d\n",pos,del->elem);
            free(del);
            return SUCCESS;
        }
        head = head->next;
        i++;
    }

	ADI_PRINT("can not find pos = %d\n",pos);
    return PARAM_FAIL;
}


/*pos为在链表中的位置,ele为待查找的元素*/
int findList(list *listFind,int ele,int *pos)
{
    if(NULL == listFind)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }

    int i = 0;
    list *head = listFind;
    while(listFind != head->next)
    {
	if(ele == head->next->elem)
	{
            *pos = i;
            return SUCCESS;
	}
	i++;
	head = head->next;
    }

	ADI_PRINT("can not find ele = %d\n",ele);
    return PARAM_FAIL;
}

int printList(list *list_prt)
{
    if(NULL == list_prt)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }
    int i = 0;

    list *head = list_prt;
    while(head != list_prt->next)
    { 
        list_prt = list_prt->next;
        ADI_PRINT("list[%d] = %d\n",i,list_prt->elem);
        i++;
    }


    return SUCCESS;
}

/*return 队列的大小*/
int sizeList(list *list_size)
{
    if(NULL == list_size)
    {
        ADI_PRINT("err NULL\n");
        return P_NULL;
    }
    int i = 0;

    list *head = list_size;
    while(head != list_size->next)
    { 
        list_size = list_size->next;
        i++;
    }
    return i;
}

int main()
{
    int ret = 0;
    int rand_gun = 0;//子弹在弹夹中的位置
    int kill_id = 0; //本次要被kill的人在队列中的位置
    list *list_test = initList();
    if(NULL == list_test)
    {
        ADI_PRINT("err \n");
        return P_NULL;
    }

    /*初始化一个20人的队列*/
    for(int i=0;i<20;i++)
    {
	ret = insertList(list_test,i,i);
	if(SUCCESS != ret) {ADI_PRINT("insert err\n");return PARAM_FAIL;}
    }
    printList(list_test);

    int size_man = sizeList(list_test);//还活着的人数
    while(1 != sizeList(list_test))//剩最后一个人
    {
        srand((int)time(0));//time函数得到的时间只能精确到秒,循环处理太快,秒没有发生变化,导致随机数都是一样的,所以每次产生随机数要在后面进行sleep
	rand_gun = rand()%(SIZE_GUN-1);//生成0-5的随机数对应子弹位置,弹容量6发
	kill_id += rand_gun;
	if(kill_id >=size_man) {kill_id = kill_id-size_man;}
	ADI_PRINT("rand_gun = %d,size_man=%d,kill_id = %d\n",rand_gun,size_man,kill_id);
	ret = delList(list_test,kill_id);
	sleep(1);
	size_man--;
    }

    ADI_PRINT("FINAL IS %d\n",list_test->next->elem);
    return SUCCESS;
}