可执行程序下载:

  链接:https://pan.baidu.com/s/1n1lPpsI_y53wp6vONWbF-A
  提取码:nxgy

  Nim游戏是博弈论中最经典的模型(之一),它又有着十分简单的规则和无比优美的结论 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”(以下简称ICG)。

条件

  满足以下条件的游戏是ICG(可能不太严谨):1、有两名选手;2、两名选手交替对游戏进行移动(move),每次一步,选手可以在(一般而言)有限的合法移动集合中任选一种进行移动;3、对于游戏的任何一种可能的局面,合法的移动集合只取决于这个局面本身,不取决于轮到哪名选手操作、以前的任何操作、骰子的点数或者其它什么因素; 4、如果轮到某名选手移动,且这个局面的合法的移动集合为空(也就是说此时无法进行移动),则这名选手负。根据这个定义,很多日常的游戏并非ICG。例如象棋就不满足条件3,因为红方只能移动红子,黑方只能移动黑子,合法的移动集合取决于轮到哪名选手操作。

定义

  通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。
 
实现
  我用Pygame实现了一个简单的NIM游戏(这也是我编写的第一个游戏/小有成就感)
#NIM
import pygame
import random
import time
#pygame的初始化#######################################
pygame.init()
screen = pygame.display.set_mode([815,600])
pygame.display.set_caption("NIM V1.1 2020/2/27") #变量的声明##########################################
WHITE = (255,255,255)
PINK = (255,146,154)
BLUE = (180,209,217)
BLACK = (10,10,10)
width = 120
lengh = 50
num = [random.randint(1,10),random.randint(1,10),random.randint(1,10)]
LEFT = [10-num[0],10-num[1],10-num[2]] #字样的声明###########################################
font = pygame.font.SysFont("Times",24)
text1 = font.render("Congratulaton! You win!",True,BLACK)
text1_rect=text1.get_rect()
text1_rect.centerx=screen.get_rect().centerx
text1_rect.y=550
text2 = font.render("GAME OVER!",True,BLACK)
text2_rect=text2.get_rect()
text2_rect.centerx=screen.get_rect().centerx
text2_rect.y=550
text3 = font.render("Press F1 to play again",True,BLACK)
text3_rect=text3.get_rect()
text3_rect.x=50
text3_rect.y=550 #初始化地图#################################
def draw_the_map():
screen.fill((255,255,255))
for y in range(3):
for i in range(num[y]):
pygame.draw.rect(screen,BLACK,((9-i)*85,y*200,lengh,width))
pic = pygame.image.load("exit.png")
screen.blit(pic,(750,540))
pygame.display.update() #更新地图####################################
def refresh_the_map(a,b,color):
global LEFT,num
for i in range(a-LEFT[b]+1):
pygame.draw.rect(screen,color,((LEFT[b]+i)*85,b*200,lengh,width))
pygame.display.update()
time.sleep(0.05)
LEFT[b]=a+1
if(LEFT[b]>10):
LEFT[b]=10
num[b]=9-a
# if(num[b]<0):
# num[b]=0
# print(num) #玩家取子####################################
def player_draw():
global LEFT,num
player_done = True
while(player_done):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = event.pos
if(x>=760 and y>=550):
pygame.quit()
exit()
a=x//85
b=y//200
if(x>=LEFT[b]*85):
if(x<=(a*85+50) and y<=(b*200+120)):
refresh_the_map(a,b,PINK)
return #获取二进制下的最高位################################
def get_high(a):
flag = True
k=1
while(flag):
if(a>>1==0):
break
a=a>>1
k=k+1
return k #检测二进制下a在b位上是否为1##########################
def check_high(b,a):
if(len(bin(a))<b):
return False
if (bin(a)[len(bin(a))-b]==''):
return True
else:
return False #电脑取子#############################################
def machine_draw():
global LEFT,num
k=random.randint(0,2)
while(num[k]==0):
k=random.randint(0,2)
result = num[0]^num[1]^num[2]
if(result==0):
refresh_the_map(LEFT[k]-1+random.randint(1,num[k]),k,BLUE)
return
high=get_high(result)
if(check_high(high,num[0])):
k=0
elif(check_high(high,num[1])):
k=1
else:
k=2
answer=num[k]-(num[k]^result)
refresh_the_map(LEFT[k]+answer-1,k,BLUE) def win_judge():
if(num[0]==0 and num[1]==0 and num[2]==0):
return True
else:return False def replay():
global LEFT,num
flag = True
while(flag):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = event.pos
if(x>=760 and y>=550):
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_F1:
num = [random.randint(1,10),random.randint(1,10),random.randint(1,10)]
LEFT = [10-num[0],10-num[1],10-num[2]]
draw_the_map()
flag= False
return def main():
draw_the_map()
keep_going =True
while(keep_going):
player_draw()
if(win_judge()):
screen.blit(text1,text1_rect)
screen.blit(text3,text3_rect)
pygame.display.update()
break
machine_draw()
if(win_judge()):
screen.blit(text2,text2_rect)
screen.blit(text3,text3_rect)
pygame.display.update()
break
replay() if __name__ == '__main__':
while(1):
main()
 

NIM游戏的Python实现的更多相关文章

  1. leetcode 292. Nim游戏(python)

    你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头. 拿掉最后一块石头的人就是获胜者.你作为先手. 你们是聪明人,每一步都是最优解. 编写一个函数,来判断 ...

  2. Nim游戏

    目前有3堆石子,每堆石子个数也是任意的,双方轮流从中取出石子,规则如下:1)每一步应取走至少一枚石子:每一步只能从某一堆中取走部分或全部石子:2)如果谁不能取谁就失败. Bouton定理: 必败状态当 ...

  3. BZOJ 3105 [CQOI2013]新Nim游戏 ——线性基

    [题目分析] 神奇的题目,两人都可以第一次取走足够多堆的石子. nim游戏的规则是,如果异或和为0,那么就先手必输,否则先手有必胜策略. 所以只需要剩下一群异或和为0就可以了. 先排序,线性基扫一遍即 ...

  4. 【BZOJ-2460&3105】元素&新Nim游戏 动态维护线性基 + 贪心

    3105: [cqoi2013]新Nim游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 839  Solved: 490[Submit][Stat ...

  5. 【BZOJ】3105: [cqoi2013]新Nim游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=3105 题意:k堆火柴,先手和后手在第一次拿的时候都能拿若干整堆火柴(但不能拿完),之后和nim游戏规 ...

  6. BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基

    一个原来写的题. 既然最后是nim游戏,且玩家是先手,则希望第二回合结束后是一个异或和不为0的局面,这样才能必胜. 所以思考一下我们要在第一回合留下线性基 然后就是求线性基,因为要取走的最少,所以排一 ...

  7. 编程之美----NIM游戏

    : 博弈游戏·Nim游戏 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 今天我们要认识一对新朋友,Alice与Bob.Alice与Bob总是在进行各种各样的比试,今天他 ...

  8. Nim游戏变种——取纽扣游戏

    (2017腾讯实习生校招笔试题)Calvin和David正在玩取纽扣游戏,桌上一共有16个纽扣,两人轮流来取纽扣,每人每次可以选择取1个或3个或6个(不允许不取),谁取完最后的纽扣谁赢.Cavin和D ...

  9. 2014 网选 5011 Game(Nim游戏,数学题)

    /* 题意:Nim游戏! 思路:通过异或,判断将n个数表示成二进制的形式之后,是否对应位的数字1 的个数是偶数! */ #include<iostream> using namespace ...

随机推荐

  1. nginx的进程结构实例演示

    nginx父子进程之间是使用信号进行管理的. nginx -s reload 会使之前的nginx子进程退出,生成新的nginx子进程 或者kill -SIGHUP 9170 kill -SIGTER ...

  2. WeChall_Training: Programming 1 (Training, Coding)

    When you visit this link you receive a message.Submit the same message back to http://www.wechall.ne ...

  3. ARTS Week 3

    Nov 11,2019 ~ Nov 17,2019 Algorithm 本周来介绍快速求一个数字n次方的余数. 理论基础 我们先定义运算$ x \bmod p = r \(与\) x \equiv r ...

  4. Codeforces Round #470 (Div. 2) A Protect Sheep (基础)输入输出的警示、边界处理

    Bob is a farmer. He has a large pasture with many sheep. Recently, he has lost some of them due to w ...

  5. EMC NW disaster and recovery simulation 2

    scanner -ivp can help your new networker server recongize that only clone pool has data

  6. 阿里云服务器ECS Ubuntu18.04 安装mysql

    ubuntu系统好了,这下我应该安装MySQL数据库了.在安装过程中,遇到好多坑,下面是我的安装过程. 1.在阿里云控制台,用vnc登录到服务器. 用新的用户登录到Ubuntu用户系统. 打开终端: ...

  7. Java开发最佳实践(二) ——《Java开发手册》之"异常处理、MySQL 数据库"

    二.异常日志 (一) 异常处理 (二) 日志规约 三.单元测试 四.安全规约 五.MySQL数据库 (一) 建表规约 (二) 索引规约 (三) SQL语句 (四) ORM映射 六.工程结构 七.设计规 ...

  8. sparc v8 汇编语言语法

    1.3.1 Labeling Format Symbol names beginning with a dot (.) are assumed to be local symbols. Names b ...

  9. 学习CSS之如何改变CSS伪元素的样式

    一.CSS伪元素 CSS 伪元素用于向某些选择器设置特殊效果. 伪元素的用法如下: selector:pseudo-element {property:value;} CSS 类也可以和伪元素搭配使用 ...

  10. 用c语言实现简单的五子棋

    用c语言实现简单的五子棋 这个小游戏是从零开始的实现的,框架灵感来自于小游戏<走迷宫>. 游戏代码配置: 二维数组+简单逻辑+getch读取键盘+windows函数(刷屏,改颜色,改窗口大 ...