Nim概述
再强调一遍结论:
对于一个Nim游戏的局面(a1,a2,…,an),它是P-position当且仅当a1^ a2^ … ^ an=0,其中“^”指抑或(xor)运算。
这便是整个程序的基础。
话不多说,直接上代码:
代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
int main() {
// 变量定义及随机数种子的创建
const short max = 50;
short k, j, m, a, d, turn;
short i, sum, or_, dif, n_, beg, re;
short n[9] = { 0 };
time_t ts;
unsigned int t = time(&ts);
sum = 0, beg = 1;
srand(t);
// 简介及设置
puts(" Welcome to NIM:\n \n (作者筱霖恋,欢迎交流学习)\n 现有k(1<=k<=9)堆石子,");
puts(" 每堆所包含的石子数{n1,n2,...nk}均为50以内的随机正整数。\n 玩家与NPC进行游戏,");
puts(" 双方轮流从任选的第j堆中拿去m(1<=m<=a,1<a<=50)个石子,\n 拿完最后一个石子者获胜 >_<\n");
while (1) {
putchar(' ');
for (i = 0; i < 60; i++) {
putchar('-');
}
printf("\n 请输入难度d(0<=d<=5):\n d:");
A1:scanf_s("%hd", &d);
if (d < 0 || d > 5) {
printf(" 诶呀,粗错了,请重新输入~\n d:");
goto A1;
}
printf
(" 请分别输入k和a,数额请不要过大,中间用空格连接:\n O0:");
A2:scanf_s("%hd %hd", &k, &a);
if (a > 1 && a < max && k >= 1 && k <= 9) {
for (i = 0; i < k; i++) {
n[i] = rand() % (max - a) + (a + 1);
sum += n[i];
}
}
else if (a == max && k >= 1 && k <= 9) {
for (i = 0; i < k; i++) {
n[i] = max;
sum += n[i];
}
}
else if (a <= 1 || a > max || k < 1 || k > 9) {
printf(" 诶呀,粗错了,请重新输入~\n O0:");
goto A2;
}
while (sum) {
if (beg == 0)
printf("\n C :");
else
printf(" P :");
// 玩家局面
for (i = 0; i < k; i++) {
printf("%2d ", n[i]);
}
if (beg) {
if (beg == 1) {
printf
("\n 请决定先后手,若您先手,请输入1,否则,请输入0:\n turn:");
A3:scanf_s("%hd", &turn);
if (turn == 0) {
beg = 2;
goto A5;
}
else if (turn != 1) {
printf(" 诶呀,粗错了,请重新输入~\n turn:");
goto A3;
}
}
puts("\n (以下内容中,O1代表玩家操作,O2代表NPC操作,P代表操作后局面。)");
printf(" 请分别输入j和m,中间用空格连接(下同):\n ");
for (i = 0; i < 60; i++) {
putchar('-');
}
beg = 0;
}
// 人机交互
puts("\n ");
printf(" O1:");
A4:scanf_s("%hd %hd", &j, &m);
j--;
if (m >= 1 && m <= a && j >= 0 && j < k && n[j] >= m) {
sum -= m;
if (sum == 0) {
printf("\n You win!!!\n ");
putchar('\n ');
break;
}
n[j] -= m;
printf(" P :");
for (i = 0; i < k; i++) {
printf("%2d ", n[i]);
}
or_ = n[0] % (a + 1);
for (i = 1; i < k; i++) {
or_ = or_ ^ (n[i] % (a + 1));
}
// 竞争模式
A5:if (or_ != 0) {
or_ = rand() % 5;
if (or_ >= 0 && or_ < 5 - d) {
goto A6;
}
j = 0;
for (i = 1; i < k; i++) {
if (n[j] < n[i]) {
j = i;
}
}
dif = 0, n_ = n[j];
while (or_ != 0) {
n[j]--;
dif++;
or_ = n[0] % (a + 1);
for (i = 1; i < k; i++) {
or_ = or_ ^ (n[i] % (a + 1));
}
if (dif == a + 1 || n[j] == -1) {
n[j] = n_;
dif = 0;
j = (j + 1) % k;
while (n[j] == 0) {
j = (j + 1) % k;
}
n_ = n[j];
}
}
sum -= dif;
}
// 随机模式
else {
A6:j = rand() % k;
while (n[j] == 0) {
j = (j + 1) % k;
}
dif = rand() % a + 1;
while (n[j] < dif) {
dif--;
}
n[j] -= dif;
sum -= dif;
}
printf("\n O2:%hd %hd", j + 1, dif);
if (sum == 0) {
printf("\n \n NPC wins!!!\n ");
}
putchar('\n ');
}
else {
printf(" 诶呀,粗错了,请重新输入~\n O1:\n ");
goto A4;
}
}
getchar();
printf("\n 请问您还要继续游戏吗?\n 再来一局请输入0,退出请输入其他任意字符:");
scanf_s("%hd", &re);
switch (re)
{
case 0:
putchar('\n');
continue;
default:
exit(0);
}
}
system("pause");
return 0;
}