完成链表的学习后,作为一个小实践项目实现俄罗斯轮盘赌。
轮盘赌游戏基于单循环链表实现,使用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;
}