171230 编程-井字棋(逆)的先手必胜策略
2018-01-01 19:41
274 查看
1625-5 王子昂 总结《2017年12月30日》 【连续第456天总结】
A. bambooctf-toddler-notakto-revenge
B.
========== Welcome to the Notakto Game ==========
Notakto is tic-tac-toe with both players playing the same piece ( an ‘X’ )
The player who end the game will LOSE THE GAME
0 | 1 | 2
—+—+—
3 | 4 | 5
—+—+—
6 | 7 | 8
========== 1 Round ==========
Your move:
说人话就是轮流执子,以井字棋的方式进行,但是胜利条件反过来,结束游戏的人判负
玩家先手,也就是寻找该游戏的先手必胜策略
在这个九子棋盘中,很容易发现六子共存的情况只有一种
此时先手输
观察它的特征,可以发现破解这种局势的方法就是邻角下子或者中心点下子
也就是说,当邻角或中心点有子时,后手第六子是必输的
那么后手翻盘的机会在哪儿?
分别对应两种情况
中心点有子
邻角有子
此时第五子无处可放,先手输
那么先手必胜的策略就是杜绝这两种情况的出现
第一子无论下在哪里,第二子都要根据对方的反应来调整:
对方下在边/中心点上,我方就要下在邻角上
对方下在角上,我方就要下在中心点/边上
三子定下来以后局势就稳定了,只要不送后手就不可能赢
我选择的是第一子下中心点的策略
落子思路为
第一子下中心点,此时每一子都会使得对称点不可落子
因此只需要记录4对点即可排除与中心点有关的结束线
之后每一子都下在对手落子对角/边
如
当对手下在“1”时,可选x的位置下
作用在于
1. 与该落子无邻边关系。
除了4个过中心点的结束线以外,还有4个邻边的结束线。
当第三子落下时,排除玩家第一子(中心点)、对手第二子(无关)以外,只有玩家第二子和对手第一子可能形成邻边结束。但是由于下子策略,玩家第二子与对手第一子也不相邻,因此可排除邻边结束。
2. 避免形成4子封死的局面
在两个x中选取对称点空白的点下即可
代码如下:
值得一提的是nc连接只有1分钟左右的时间,要通过50关才能拿到flag
这样就杜绝了手动操作的可能性
由于每次最后消息收到都没有EOF,因此刚开始我只能通过timeout来接收
试了一下timeout=1时完全来不及,只能下调到0.3左右
此时就可能造成某一次延迟稍大,消息没收到就结束了
最后找到recvuntil函数,可以自主规定结束符,并且能接到所有内容
这样可以根据延迟自己决定接受时间,轻松完成
PS:
这题50分,后面还有一题进阶的500分,棋盘增加到5个,任意落子,规则相同,“结束游戏”(五个棋盘都结束时,每个棋盘独立结束)的最后一子判负(:з」∠)
PPS:
思考的时候感觉这种
C. 明日计划
看书╮(╯_╰)╭
A. bambooctf-toddler-notakto-revenge
B.
========== Welcome to the Notakto Game ==========
Notakto is tic-tac-toe with both players playing the same piece ( an ‘X’ )
The player who end the game will LOSE THE GAME
0 | 1 | 2
—+—+—
3 | 4 | 5
—+—+—
6 | 7 | 8
========== 1 Round ==========
Your move:
说人话就是轮流执子,以井字棋的方式进行,但是胜利条件反过来,结束游戏的人判负
玩家先手,也就是寻找该游戏的先手必胜策略
在这个九子棋盘中,很容易发现六子共存的情况只有一种
1 | 1 | 0 |
---|---|---|
1 | 0 | 1 |
0 | 1 | 1 |
观察它的特征,可以发现破解这种局势的方法就是邻角下子或者中心点下子
也就是说,当邻角或中心点有子时,后手第六子是必输的
那么后手翻盘的机会在哪儿?
分别对应两种情况
中心点有子
1 | 1 | 0 |
---|---|---|
1 | 1 | 0 |
0 | 0 | 0 |
1 | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
那么先手必胜的策略就是杜绝这两种情况的出现
第一子无论下在哪里,第二子都要根据对方的反应来调整:
对方下在边/中心点上,我方就要下在邻角上
对方下在角上,我方就要下在中心点/边上
三子定下来以后局势就稳定了,只要不送后手就不可能赢
我选择的是第一子下中心点的策略
落子思路为
第一子下中心点,此时每一子都会使得对称点不可落子
因此只需要记录4对点即可排除与中心点有关的结束线
之后每一子都下在对手落子对角/边
如
当对手下在“1”时,可选x的位置下
x | 0 | x |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1. 与该落子无邻边关系。
除了4个过中心点的结束线以外,还有4个邻边的结束线。
当第三子落下时,排除玩家第一子(中心点)、对手第二子(无关)以外,只有玩家第二子和对手第一子可能形成邻边结束。但是由于下子策略,玩家第二子与对手第一子也不相邻,因此可排除邻边结束。
2. 避免形成4子封死的局面
在两个x中选取对称点空白的点下即可
代码如下:
from pwn import * pairs = {0: (0, 8),1: (1, 7), 2:(2, 6), 3:(3, 5)} def find(x): for i in range(4): if(x) in pairs[i]: return i def choose(x): global flag p = pairs[find(x)] if(x)==p[0]: p = p[1] else: p = p[0] # 以对称点为中心,选取4个点作为备选,遍历它们,满足在点棋盘上且对称点未被下时可取 k = [p-1, p+1, p-3, p+3] for i in k: if((i//3==p//3 or i%3 == p%3)and i<=8 and i>=0 and i!=4 and flag[find(i)]==0): return i def iswin(s): global flag if(s.find("Round") != -1): p = s.find("Round") print(s[p-12:p+15]) flag = [0 for x in range(4)] def recv(s): p = s.find("My move:") if(p==-1): return -1 for i in s: try: if(i[0] == 'M'): recv = int(i[9]) return recv except: pass else: return -1 r = remote("bamboofox.cs.nctu.edu.tw", 58793) s = r.recvuntil("Your move") flag = [0 for i in range(4)] while(1): iswin(s) k = s.find("My move") if(k==-1): r.sendline("4") print("send:", 4) else: k = int(s[k+9]) print("recv:", k) flag[int(find(k))] = 1 p = choose(k) print('send:', p) r.sendline(str(p)) flag[find(p)] = 1 try: s = r.recvu 4000 ntil("Your move") except: print(r.recvall(timeout=3)) break
值得一提的是nc连接只有1分钟左右的时间,要通过50关才能拿到flag
这样就杜绝了手动操作的可能性
由于每次最后消息收到都没有EOF,因此刚开始我只能通过timeout来接收
试了一下timeout=1时完全来不及,只能下调到0.3左右
此时就可能造成某一次延迟稍大,消息没收到就结束了
最后找到recvuntil函数,可以自主规定结束符,并且能接到所有内容
这样可以根据延迟自己决定接受时间,轻松完成
PS:
这题50分,后面还有一题进阶的500分,棋盘增加到5个,任意落子,规则相同,“结束游戏”(五个棋盘都结束时,每个棋盘独立结束)的最后一子判负(:з」∠)
PPS:
思考的时候感觉这种
C. 明日计划
看书╮(╯_╰)╭
相关文章推荐
- 博弈论:寻找先手必胜策略——Grundy值
- 井字棋先手必胜图解
- Three Man Morris(米字棋)先手的必胜策略
- PHP数据库编程之MySQL优化策略概述
- 并发编程(八):线程安全策略
- 小菜和大鸟的编程故事之八:初识"策略模式"
- ASPNET安全性高级编程 第五章 实现密码策略
- strcpy的使用--安全编程策略
- 编程之美4.7蚂蚁爬杆扩展问题附猎人抓狐狸(必胜策略)
- 老程序员推荐的 10 个编程策略
- Java设计模式编程中的状态模式和策略模式
- 编程学习之简单工厂模式与策略模式
- 老程序员推荐10个编程策略
- 【编程素质】设计模式-策略模式
- hdu 5229 必胜策略
- 新浪的动态策略灰度发布系统:ABTestingGateway - 让编程成为一种习惯 - 博客园
- 数论练习2:L - 取(m堆)石子游戏(用SG值来判断如果先手赢,求先手第一步的策略)
- POJ - 2975 NIM博弈的必胜策略方案数
- 编程设计模式—策略模式
- 《挑战程序设计竞赛》4.2.2 游戏必胜策略-Nim与Grundy数 POJ2975 1704 2311 3537 2315 CF138D(2)