五子棋第二章
游戏菜单和玩家信息操作部分
前言
本篇文章为完整工程实践五子棋项目的第二章。
如未看过前面的章节:
五子棋第一章
本篇文章我们将讲解游戏菜单部分和玩家信息操作部分的实现。
一、游戏菜单部分
在上一章我们实现了玩家注册登录功能,当我们登录成功之后,我们就调用game()函数,正式进入游戏内容部分。进入game()函数里面开头又是一个do…while语句嵌套switch语句作为一个游戏菜单。
game()函数
void game(player* p, player* head, int num)
{
assert(p);
assert(head);
int sc = 0;
do
{
enum
{
toexit,
tologin,
tocoputer,
towatch,
torank,
tomodify,
};
printf("-------------------------------------\n");
printf("----------欢迎来到五子棋游戏---------\n");
printf("--------------游戏目录---------------\n");
printf("-------------1.玩家对战--------------\n");
printf("-------------2.人机对战--------------\n");
printf("-------------3.查看信息--------------\n");
printf("-------------4.查看排名--------------\n");
printf("-------------5.修改信息--------------\n");
printf("-------------0.退出登录--------------\n");
printf("-------------------------------------\n");
scanf("%d", &sc);
switch (sc)
{
case tologin:
{
player* q = log_in2(head);
if (q == NULL)
{
break;
}
if (q == p)
{
printf("重复登录\n");
break;
}
system("cls");
//gameprocess(p, q);
break;
}
case tocoputer:
system("cls");
//coputerprocess(p);
break;
case towatch:
watch(p);
break;
case torank:
rank(head, num);
break;
case tomodify:
modify(p);
break;
case toexit:
system("cls");
break;
default:
printf("输入错误,请重新输入!\n");
}
} while (sc);
}
我们在上面的游戏菜单部分预计了需要实现的功能–如玩家对战,人机对战,查看、修改个人信息等功能。这里当我们选择玩家对战功能时,就需要调用二号玩家登录的函数log_in2(player* head)函数并判断是否会发生重复登录等错误。当都正确后,才正式进入游戏具体进程的gameprocess(p, q)函数。这里开始p代表1号玩家(当前登录玩家),q代表2号玩家。
log_in2(player* head)函数,进行二号玩家的登录操作。
player* log_in2(player* head)
{
assert(head);
printf("请二号玩家登录\n");
printf("请输入您的账号:\n");
char a[15] = { 0 };
char b[15] = { 0 };
scanf("%s", a);
printf("请输入您的密码:\n");
scanf("%s", b);
player* cur = head->next;
while (cur != head)
{
if (strcmp(cur->account, a) == 0 && strcmp(cur->password, b) == 0)
{
return cur;
}
cur = cur->next;
}
printf("账号或密码错误,返回前页\n");
return NULL;
}
二、玩家信息操作部分
watch(player* p)函数,传入当前登录玩家信息的指针,通过打印指针指向的具体内容实现玩家信息的查询。
void watch(player* p)
{
assert(p);
printf("玩家昵称:%s 胜场:%d 负场:%d 平局:%d 得分:%d\n", p->id, p->win, p->lose, p->tie, p->score);
}
modify(player* p)函数,传入当前登录玩家信息的指针,然后进行玩家信息的修改逻辑,这里我只编写了修改密码和昵称的逻辑,如需增加修改内容,可照葫芦画瓢地增加相似的逻辑。
void modify(player* p)
{
assert(p);
int n = 0;
do
{
printf("-------------------------------------\n");
printf("-------------请选择修改内容----------\n");
printf("---------------1.修改密码------------\n");
printf("---------------2.修改昵称------------\n");
printf("---------------0.修改完成------------\n");
printf("-------------------------------------\n");
scanf("%d", &n);
if (n == 1)
{
char a[15] = { 0 };
printf("请输入您之前的密码:");
scanf("%s", a);
if (strcmp(p->password, a) == 0)
{
printf("请输入您的新密码(15个字符以内):");
scanf("%s", p->password);
printf("修改密码成功\n");
break;
}
else
{
printf("密码错误,请重新选择!\n");
}
}
else if (n == 2)
{
char a[15] = { 0 };
printf("请输入您的密码:");
scanf("%s", a);
if (strcmp(p->password, a) == 0)
{
printf("请输入新的昵称(10个字符以内):");
scanf("%s", p->id);
printf("修改昵称成功\n");
break;
}
else
{
printf("密码错误,请重新选择!\n");
}
}
else if (n == 0)
{
break;
}
else
{
printf("输入错误,请重新选择!\n");
}
} while (n);
}
rank(player* head, int num)函数,传入head头结点和当前存储玩家数量num来实现查看玩家排名的功能。需要注意的是,查看排名就需要先进行排序,所以这里我们就涉及到了对链表的内容进行排序。我们这里就调用实现排序方法的sort(player* head, int num)函数。
void rank(player* head, int num)
{
assert(head);
if (num == 0)
{
printf("暂无玩家数据\n");
return;
}
sort(head, num);
player* p = head->next;
int i = 0;
for (i = 0; i < num; i++)
{
printf("第%d名: 玩家昵称:%s 胜场:%d 负场:%d 平局:%d 得分:%d\n", i + 1, p->id, p->win, p->lose, p->tie, p->score);
p = p->next;
}
}
sort(player* head, int num)函数,实现对链表的内容进行排序的功能。在这里为了降低难度,我们在这里就使用冒泡排序作为排序方法,但是这种排序方法的效率并不高,有能力的可以把这一段换成归并排序,可以提高很多效率。
但如果连冒泡排序的思想都不知道的话,建议先去补一下,这里我也提供一个常规版的对数组进行冒泡排序的BubbleSort(int arr[],int sz)函数,对链表进行冒泡排序和对数组进行冒泡排序的思想是完全一样的。
BubbleSort(int arr[],int sz)函数
void BubbleSort(int arr[],int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int b = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = b;
}
}
}
}
sort(player* head, int num)函数
void sort(player* head, int num)
{
assert(head);
int i = 0;
for (i = 0; i < num - 1; i++)
{
player* p = head->next;
int j = 0;
for (j = 0; j < num - 1 - i; j++)
{
player* tmp = p->next;
if (p->score < tmp->score)
{
p->next = tmp->next;
tmp->next->prev = p;
p->prev->next = tmp;
tmp->prev = p->prev;
tmp->next = p;
p->prev = tmp;
}
else
{
p = p->next;
}
}
}
}
其实这一段代码最麻烦的地方就是中间的交换两个结点位置的部分,所以如果搞不清楚的话,可以通过画图或者多设几个变量来帮助我们更好地完成这个功能。
总结
本次五子棋项目的第二章就先到这里了,我们在这一章完成了游戏菜单和玩家信息操作部分,实现了游戏菜单和对玩家信息进行修改、查看、排序等功能,到这里玩家信息部分的所有功能应该都算完成了,下一章预计将讲解五子棋游戏内容逻辑的具体实现。
如需源码,可在我的gitee上找到,下面是链接。
五子棋源码
每文推荐
王力宏–天地龙鳞
庄心妍–念
萨吉–玄鸟