约瑟夫环遍历,遍历到1时出错

问题相关描述

N为1时,可以完美遍历并输出
N不为1时,在弹出1时,会输出错误数字,并且停止运行

问题相关代码
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct List
{
    int num;
    struct    List* next;
    int n;
    int N;
}List;

List* creatlist(int n, int N)
{
    int i;
    List* p, * r, * head;
    p= r= head = (List*)malloc(sizeof(List));
    head->next = p;
    head->n = n;
    head->N = N;
    for (i = 1; i <= head->n; i++)
    {
        p->next = NULL;
        p = (List*)malloc(sizeof(List));
        p->num = i;
        r->next = p;
        r = p;
    }
    p->next = head->next;
    return head;
}
List* input()
{
    List* head;
    int n, N;
    printf("请输入演示总人数(<=10):\n");
    scanf("%d", &n);
    printf("请输入指定的数N(<=10):\n");
    scanf("%d", &N);
    head = creatlist(n, N);
    return head;
}

void output(List* head)
{
    List* q;
    q = head->next;
    printf("当前循环链表节点信息:");
    for (int i = 0; i < head->n; i++)
    {
        printf("%d ", q->num);
        q = q->next;
    }
    printf("\n");
}

void ysf(List* head, int n, int m)
{
    int j = 0;
    List* o, * u;
    o = u = head;
    if (m == 1)
    {
        getchar();
        for (int i = 1; i <= n; i++)
        {
            u = o->next;
            printf("弹出%d ", u->num);
            o->next = u->next;
            free(u);
            head->n--;
            output(head);
            getchar();

        }
    }
    else
    {
        getchar();
        while (o->next != NULL)
        {
            ++j;
            o = o->next;
            if (j == m - 1)
            {
                u = o->next;
                printf("弹出%d ", u->num);
                o->next = u->next;
                free(u);
                head->n--;
                output(head);
                j = 0;
                getchar();

            }
        }
    }
}
int main()
{
    List* p;
    p = input();
    output(p);
    ysf(p, p->n, p->N);
    return 0;
}

运行结果及报错内容

img

我想要达到的结果

在N不为1时,可以完整输出每个阶段的当前的约瑟夫环的结点信息


#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
typedef struct Person {
    int id, pwd;                //数字域:id用来存储人的序号,pwd用来存储人的密码
    struct Person* next;         //指针域:指向下一个的指针 
};
struct Person* head, * p, * pd;

/*创建单向循环链表*/
int createCLinkList(int n) {
    int i;
    head = (struct Person*)malloc(sizeof(struct Person));   //创建一个带头结点的链表
    if (!head) return 0;   //创建不成功,返回0
    p = head;
    for (i = 1; i < n; i++) {
        pd = (struct Person*)malloc(sizeof(struct Person));
        if (!pd) return 0;
        p->next = pd;
        p = pd;
    }
    p->next = head;
    pd = head;
    return 0;
}

/*输入密码*/
int inputPwd(int n) {
    int a, b;
    printf("请输入每个人的密码:");
    for (a = 1;a <= n;a++) {
        scanf_s("%d", &b);
        pd->id = a;
        pd->pwd = b;
        pd = pd->next;
    }
    pd = p;
    return b;
}

/*输出出列序号*/
int outList(int m, int n) {
    int q, r;
    for (q = 1;q <= n;q++) {
        for (r = 1;r < m;r++) {
            pd = pd->next;
        }
        p = pd->next;
        m = p->pwd;//新的密码作为m值
        printf("第%d号出列\n", p->id);
        pd->next = p->next;
        free(p);
    }
    return 0;
}
void menu() {
    printf("\t\t************约瑟夫环杀人游戏************\n");
    printf("\t\t          1.游戏开始\n");
    printf("\t\t          2.继续游戏\n");
    printf("\t\t          0.游戏结束\n");
}
/*约瑟夫环游戏菜单*/
int main() {
    int m, n, a;//定义密码m,总人数n,游戏选项a
    setvbuf(stdout, NULL, _IONBF, 0);//这是因为Eclipse环境下写C语言控制台需设置为无缓冲立即回显
    menu();//杀人游戏菜单
    do {
        printf("约瑟夫环杀人游戏开始,请输入您的选择:");
        scanf_s("%d", &a);
        switch (a) {

        case 1:
        case 2: {
            printf("输入总人数n:");
            scanf_s("%d", &n);
            createCLinkList(n);//创建循环链表
            inputPwd(n);//输入密码
            printf("数到m的人出列:");
            scanf_s("%d", &m);
            outList(m, n);//打印出列顺序
        }
        case 0:
            printf("\t\t感谢使用!!!\n");
            break;
        default:
            printf("\t输入错误!!!\n");
            break;
        }
    } while (a != 0);

    return 0;
}

img