```c++
#include<iostream>
#include<assert.h>
#include<string>
#include<stdio.h>
#include<math.h>
#include<random>
#include <fstream> //完成文件读写
using namespace std;
struct Players { //自定义结构体变量
long int ID; // 规定玩家ID为八位数字
int points;
};
class player {
public:
long int ID; // 规定玩家ID为八位数字
string name;
string telenumber;
string email;
string IDcard; //规定玩家IDcard为18位数字
long int password; //规定玩家密码为八位
int points;
string status; //身份分为两级:菜鸟,王者
void privilege(); //特权
player* next;
player* play_front; //游戏指针
player* play_next;
player() { //cl
ID = 0;
name = '\0';
telenumber = '\0';
IDcard = '\0';
password = 0;
points = 0;
status = '\0';
next = (player*)malloc(sizeof(player));
play_next = (player*)malloc(sizeof(player));
play_front = (player*)malloc(sizeof(player));
play_front = NULL;
play_next = NULL;
next = NULL;
}
~player() { //cl
delete next;
delete play_front;
delete play_next;
}
};
class Josephus {
protected:
player* head; //头指针
player* rear;//尾指针
int length; //链表长度
public:
player* Gethead() { return head; }
player* Getrear() { return rear; }
```c++
player* Loacting(long int id) {
player* p = head->next;
int i = 1;
while (i++ <= length && p->ID != id) {
p = p->next;
}
if (p->ID == id) return p;
else return NULL;
}
bool enroll(player& Player) {//开户,尾插//debug——zxr
printf("请输入您的游戏8位数ID");
cin >> Player.ID;
while (Player.ID >= 10000000 && Player.ID <= 99999999) {
break;
cout << "该ID无效,请重新输入您的游戏8位数ID(ID应由8个数字组成)";
cin >> Player.ID;
}
cout << "您的游戏ID创建成功" << endl;
printf("请输入您的姓名");
int name1 = 1;//一个标志,判断是否合法
cin >> Player.name;
while (name1 != 0) {
break;
int name2 = 0;
for (int k = 0; k < Player.name.length(); k++) {
if (Player.name[k] < 'A' || (Player.name[k] > 'Z' && Player.name[k] < 'a') || Player.name>"z")
name2++;
}
if (name2 == 0)name1 = 0;
else cout << "该姓名无效,请重新输入您的姓名(姓名应由大小字母组成)";
}
cout << "您的姓名输入成功" << endl;
printf("请输入您的18位身份证号码");
int idcard1 = 1;
cin >> Player.IDcard;
while (idcard1 != 0) {
if (Player.IDcard.length() == 18) {
int idcard2 = 0;
for (int k = 0; k < 16; k++) {
if (Player.IDcard[k] > '9' || Player.IDcard[k] < '0')idcard2++;
}
if ((Player.IDcard[17] > '9' && Player.IDcard[17] < 'X') || Player.IDcard[17] < '0' || Player.IDcard[17]>'X')idcard2++;
if (idcard2 == 0)idcard1 = 0;
}
if (idcard1 != 0)
{
cout << "该身份证号无效,请重新输入您的身份证号";
cin >> Player.IDcard;
}
}
cout << "您的身份证号输入成功" << endl;
printf("请输入您的电话号码");
cin >> Player.telenumber;
int tele1 = 1;
while (tele1 != 0) {
int tele2 = 0;
if (Player.telenumber.length() == 11) {
if (Player.telenumber[0] != '1')
{
tele2++;
}
//if (Player.telenumber[1] <= '2' || (Player.telenumber[1] >= '6' || Player.telenumber[1] <= '7') || Player.telenumber[1] > '9')tele2++;
//for (int k = 1; k < 11; k++) {
//if (Player.telenumber[k] < '0' || Player.telenumber[k]> '9' )tele2++;
//}
if (tele2 == 0)tele1 = 0;
}
if (tele1 != 0)
{
cout << "该电话号码无效,请重新输入您的电话号码";
cin >> Player.telenumber;
}
}
cout << "您的电话号码输入成功" << endl;
printf("请输入您的邮箱");
cin >> Player.email;
cout << "您的邮箱输入成功" << endl;
printf("已为您自动生成8位密码,请牢记!");
long int min = 0, max = 99999999;
random_device seed;//硬件生成随机数种子
ranlux48 engine(seed());//利用种子生成随机数引擎
uniform_int_distribution<> distrib(min, max);//设置随机数范围,并为均匀分布
Player.password = distrib(engine);
if (Player.password % 2 == 0) { //偶数自动设为负值
Player.password = -Player.password;
}
cout << "您的密码是:" << Player.password;
rear->next = &Player;
rear->play_next = &Player;
Player.play_front = rear;
rear = rear->next;
head->play_front = &Player;
Player.play_next = head;
Player.next = head;
length++;
assert(head->next != NULL);
assert(rear->next != NULL);
assert(head->play_front != NULL);
assert(head->play_next != NULL);
assert(rear->play_front != NULL);
assert(rear->play_next != NULL);
assert(Player.next != NULL);
assert(Player.play_next != NULL);
if (Player.next == NULL || Player.play_next == NULL || head->next == NULL || rear->next == NULL || head->play_front == NULL || head->play_next == NULL || rear->play_front == NULL || rear->play_next == NULL)
{
cout << "cuowu" << endl;
exit(1);
}
return true;
};
bool Dead(player* Player) {
//(Player->play_front)->play_next = Player->play_next;
//(Player->play_next)->play_front = Player->play_front;
//Player->play_front = NULL;
//Player->play_next = NULL;
return true;
};
void Game(player* p) { //正为顺,负为逆
int j = 1; int m = 4; int flag = 1;
player* play = head->next;
if (Difficulty()) {
while (play->play_front != NULL && play->play_next != NULL) {
if (j == m) {
Dead(play);
j = 1;
m = play->password;
if (m < 0) {
flag = 0;
}
}
else {
if (flag == 1) {
play = play->play_next;
++j;
}
else {
play = play->play_front;
++j;
}
}
}
}
else {
while (play->play_front != NULL && play->play_next != NULL) {
if (j == 4) {
Dead(play);
j = 1;
}
else {
play = play->play_next;
++j;
}
}
}
if (play == p) {
p->points += 10;
}
play = head->next;
while (play->next != NULL) {
play->play_next = play->next;
(play->next)->play_front = play;
++play;
}
};
player* login(long int n)//登录,定位//debug——zxr
{
player* P = new player;
P = Josephus::Loacting(n);
cout << "请输入密码: ";
long int se;
cin >> se;
if (P != NULL && se == P->password) {
cout << length;
return P;
}
else {
cout << "密码错误,请再次输入密码(您还有两次机会): ";
cin >> se;
if (P != NULL && se == P->password) {
return P;
}
else {
cout << "密码错误,请再次输入密码(您还有一次机会): ";
cin >> se;
if (P != NULL && se == P->password) {
return P;
}
else {
return NULL;
}
}
}
};
bool Delete(player* player)//销户 debugcl?
{
if (head == player) {
head = player->next;
(player->play_next)->play_front = NULL;
return true;
}
else {
(player->play_front)->next = (player->play_next);
(player->play_front)->play_next = (player->play_next);
(player->play_next)->play_front = (player->play_front);
return true;
}
delete player;
};
bool Correct(player& Player) {
int n;
cout << "您想修改的是(请选择一个数字)" << endl;
cout << "1.电话号码" << endl;
cout << "2.电子邮箱" << endl;
cout << "请输入一个数字";
cin >> n;
if (n != 1 && n != 2)cout << "该选择无效,请重新输入一个数字(数字应为1或2)";
else if (n == 1) {
cout << "请输入您的新电话号码";
cin >> Player.telenumber;
int tele1 = 1;
while (tele1 != 0) {
int tele2 = 0;
if (Player.telenumber.length() == 11) {
if (Player.telenumber[0] != 1)tele2++;
if (Player.telenumber[1] <= '2' || (Player.telenumber[1] >= '6' || Player.telenumber[1] <= '7') || Player.telenumber[1] > '9')tele2++;
for (int k = 2; k < 11; k++) {
if (Player.telenumber[k] < '0' || Player.telenumber[k]>'9')tele2++;
}
if (tele2 == 0)tele1 = 0;
}
if (tele1 != 0)cout << "该电话号码无效,请重新输入您的电话号码";
}
cout << "您的电话号码输入成功" << endl;
}
else if (n == 2) {
cout << "请输入您的新电子邮箱";
cin >> Player.email;
cout << "您的邮箱输入成功" << endl;
}
return true;
};//修改,定位!!!!//zxr
bool Browse(player& Player) {//浏览,排序(直接内置) cl
cout << "当前账户数量:" << length << endl;
cout << "您的账户是" << Player.ID << endl;
cout << "您的积分是" << Player.points << endl;
Players a[100];
Players m;
int i = 0;
player* p = new player;
p = head->next;
for (i = 1; i <= length; i++)
{
a[i - 1].ID = p->ID;
a[i - 1].points = p->points;
}
int j = 0;
for (j = 1; j <= length - 1; j++)
{
for (i = 0; i < length - j; j++)
{
if (a[i].points < a[i + 1].points)
{
m = a[i];
a[i] = a[i + 1];
a[i + 1] = m;
}
}
}
cout << "排行榜" << endl;
for (i = 0; i < length; i++)
{
cout << "第" << i + 1 << "名" << " " << a[i].ID << " POINTS:" << a[i].points << endl;
}
return true;
};
bool Searching() {
long int n;
cout << "您想查找的ID是" << endl;
cin >> n;
player* P = Josephus::Loacting(n);
cout << "该玩家的电话号码是" << P->telenumber << endl;
cout << "该玩家的电子邮箱是" << P->email << endl;
return true;
};//查找,定位//zxr
bool Difficulty()
{
return 0;
}
bool If_challenge() //挑战模式,只能在Game()中调用
{
}
bool status_upgrade() //升级,定位,只能在Game()中调用
{
}
void Main_interface() {//主界面 cl
cout << " * " << endl;
cout << " * * " << endl;
cout << " * * " << endl;
cout << " * * " << endl;
cout << "* 约瑟夫环游戏模拟器 *" << endl;
cout << " * * " << endl;
cout << " * 开户(1) 登录(2) * " << endl;
cout << " * * " << endl;
cout << " * " << endl;
};
void Function_Select(int a) {//Function_Select函数将主函数的switch和交互封装起来 cl
long int n; int b;
int mode;
player* Player = new player;
switch (a) {
case 1://开户
enroll(*Player);
cout << "请再次输入账号";
cin >> n;
login(n);
cout << "您想要做什么:" << endl;
cout << "1.查询 2.修改 3.销户 4.浏览 5.查找 6.游戏";
cin >> mode;
switch (mode) {
case 1:Searching(); break;
case 2:Correct(*Player); break;
case 3:Delete(Player); break;
case 4:Browse(*Player); break;
case 5:Loacting(Player->ID); break;
case 6:Game(Player); break;
default:cout << "您输入的模式不存在,请再输一次";
};
break;
case 2://登录
cout << "请输入账号";
cin >> n;
Player = login(n);
if (login(n) != 0) {
cout << "您想要做什么:" << endl;
cout << "1.查询 2.修改 3.销户 4.浏览 5.查找 6.游戏";
cin >> mode;
switch (mode) {
case 1:Searching(); break;
case 2:Correct(*Player); break;
case 3:Delete(Player); break;
case 4:Browse(*Player); break;
case 5:Loacting(Player->ID); break;
case 6:Game(Player); break;
default:cout << "您输入的模式不存在,请再输一次";
}
break;
}
else {
cout << "您输入的账户不存在,或密码错误" << endl;
}
}
};
void Mode_Select(); //Mode_Select函数将主函数的switch和交互封装起来
Josephus() {//构造 cl
head = new player;
rear = new player;
head->next = rear;
rear->next = head;
head->play_front = (player*)malloc(sizeof(player));
head->play_next = (player*)malloc(sizeof(player));
rear->play_front = (player*)malloc(sizeof(player));
rear->play_next = (player*)malloc(sizeof(player));
(rear->play_front)->next = head;
(head->play_front)->next = rear;
(rear->play_next)->next = head;
(head->play_next)->next = rear;
assert(head->next != NULL);
assert(rear->next != NULL);
assert(head->play_front != NULL);
assert(head->play_next != NULL);
assert(rear->play_front != NULL);
assert(rear->play_next != NULL);
if (head->next == NULL || rear->next == NULL || head->play_front == NULL || head->play_next == NULL || rear->play_front==NULL || rear->play_next==NULL)
{
cout << "cuowu" << endl;
exit(1);
}
length = 0;
while (1) {
Main_interface();
int a;
cin >> a;
Function_Select(a);
}
}
~Josephus() {//析构 cl
player* q = head->next;
int i = 1;
while (i++ <= length)
{
head->next = q->next;
delete q;
q = head->next;
}
length = 0;
delete head;
delete rear;
};
};
int main() {
Josephus game;
return 0;
}
```
来自NewBing和LP的编写:
在Game函数中,出现读取访问权限冲突的问题是因为play指针在函数开始时被定义为指向head->next,然后在后面的代码中进行了指针的移动,导致play指针指向了其他节点。而在函数末尾的返回结果需要使用play指针,但此时play指针已经不再指向head->next,因此出现了读取访问权限冲突的问题。
为了解决这个问题,可以在函数开头定义一个新的指针变量,例如player* current = head->next;
,然后在后面的代码中使用current
指针进行遍历和操作。这样在函数末尾就可以使用current
指针返回正确的结果,而不会出现读取访问权限冲突的问题。
在Game函数中,可以进行如下修改:
void Game(player* p) {
int j = 1;
int m = 4;
int flag = 1;
player* current = head->next; // 使用current指针进行遍历和操作
if (Difficulty()) {
while (current->play_front != NULL && current->play_next != NULL) {
if (j == m) {
Dead(current);
j = 1;
m = current->password;
if (m < 0) {
flag = 0;
}
} else {
if (flag == 1) {
current = current->play_next;
++j;
} else {
current = current->play_front;
++j;
}
}
}
} else {
while (current->play_front != NULL && current->play_next != NULL) {
if (j == 4) {
Dead(current);
j = 1;
} else {
current = current->play_next;
++j;
}
}
}
if (current == p) {
p->points += 10;
}
// 重新遍历链表,将指针连接起来
current = head->next;
while (current->next != NULL) {
current->play_next = current->next;
(current->next)->play_front = current;
current = current->next;
}
}
这样,在Game函数中使用了current
指针进行链表的遍历和操作,而保留了p
指针作为参数用于比较得分。通过重新遍历链表,将指针正确地连接起来,避免了读取访问权限冲突的问题。
在你的代码中,Game函数中的循环使用了一个名为play的指针,而该指针在每次循环迭代时被赋予一个新的值。问题出在你在循环内部对play指针进行了读取和写入操作,而这样的操作可能会导致读取访问权限冲突。
解决这个问题的方法是将play指针声明为每次循环迭代时的局部变量,而不是在循环之外声明。这样可以确保每次迭代都有一个新的指针,避免读取访问权限冲突。下面是修改后的Game函数代码:
void Game::play()
{
Player* current = head; // 指向头节点的指针
for (int i = 0; i < num_of_players; i++)
{
cout << "Player " << i + 1 << "'s information:" << endl;
current->privilege(); // 调用当前玩家的特权函数
current = current->next; // 指向下一个玩家
}
}