井字棋(Tic-Tac-Toe)
井字棋介绍:https://en.wikipedia.org/wiki/Tic-tac-toe
井字棋简单,但是获胜策略却和直觉不同,四角比中间重要性要高,而且先手有很大的获胜概率获胜(先手胜:91, 后手胜:44,平局:3),所以当你陷入劣势时,怎么选择打平就是一个不那么简单的事情。不过无聊大抵孤单,没有人一起玩就只能和电脑PK,就写了个弱智AI,没事就偷着乐!
AI的获胜策略也很简单,先遍历检测棋盘副本的空格子看下一步能否获胜,如果有机会获胜,返回格子的下标,然后再棋盘上移动,其次,检测对手能否下一步获胜,提前封堵,如果前面两步都没返回的话,就说明双方都没有一步必胜的招式,这时候就得依次抢占四个角落,中间和剩余的位置。

import random def draw_board(board):
"""board is a 3X3 list containing the moves either ' ' representing
no moves there or 'x' or 'o' representing actual moves"""
for i in range(7):
if i%2 == 0:
print '+'.join(['---']*3)
else:
col = []
for j in range(11):
if j%2 == 0:
col.append(' ')
elif j==3 or j==7:
col.append('|')
else:
col.append(board[i/2][j/4])
print ''.join(col) def who_goes_first():
if random.randint(0, 1):
return 'AI'
else:
return 'P' def play_again():
print "Once Again?(y for Yes, n for No)"
return raw_input().lower().startswith('y') def make_move(board, letter, move):
seq = move-1
board[2-seq/3][seq%3] = letter def is_winner(bo, le):
# Given a board and a player’s letter, this function returns True if that player has won.
# We use bo instead of board and le instead of letter so we don’t have to type as much.
return ((bo[0][0] == le and bo[0][1] == le and bo[0][2] == le) or # across the top
(bo[1][0] == le and bo[1][1] == le and bo[1][2] == le) or # across the middle
(bo[2][0] == le and bo[2][1] == le and bo[2][2] == le) or # across the bottom
(bo[0][0] == le and bo[1][0] == le and bo[2][0] == le) or # down the left side
(bo[0][1] == le and bo[1][1] == le and bo[2][1] == le) or # down the middle
(bo[0][2] == le and bo[1][2] == le and bo[2][2] == le) or # down the right side
(bo[0][0] == le and bo[1][1] == le and bo[2][2] == le) or # diagonal
(bo[0][2] == le and bo[1][1] == le and bo[2][0] == le)) # diagonal def get_board_copy(board):
dup = [[' ']*3 for i in range(3)]
for i in range(3):
for j in range(3):
dup[i][j] = board[i][j]
return dup def is_move_avail(board, move):
seq = move-1
return board[2-seq/3][seq%3] == ' ' def get_P_moves(board):
move = ''
while move not in [1, 2, 3, 4, 5, 6, 7, 8, 9] or not is_move_avail(board, move):
print "Please input your next move('1-9')"
move = input()
return move def is_board_full(board):
for i in range(3):
for j in range(3):
if board[i][j] == ' ':
return False
return True def choose_randomly(board, avail):
possible_moves = []
for i in avail:
if is_move_avail(board, i):
possible_moves.append(i)
if len(possible_moves) != 0:
return random.choice(possible_moves)
else:
return None def get_AI_moves(board, AI, P):
#check if AI can win in the next move
for i in range(1, 10):
copy = get_board_copy(board)
if is_move_avail(board, i):
make_move(copy, AI, i)
if is_winner(copy, AI):
return i #else check if P can win in the next move and block the first found move
for i in range(1, 10):
copy = get_board_copy(board)
if is_move_avail(board, i):
make_move(copy, P, i)
if is_winner(copy, P):
return i #The key to win is to occupy the corners, so move there if available
move = choose_randomly(board, [1, 3, 7, 9])
print move
if move != None:
return move #of second priority is the center element
if is_move_avail(board, 5):
return 5 #Then the rest
return choose_randomly(board, [2, 4, 6, 8]) if __name__ == '__main__': while True:
Board = [[' ']*3 for i in range(3)]
P, AI = 'x', 'o'
turn = who_goes_first()
print "{0} will go first".format(turn)
GameOn = True while GameOn:
if turn == 'P':
move = get_P_moves(Board)
make_move(Board, P, move)
draw_board(Board) if is_winner(Board, P):
draw_board(Board)
print "GameOver You've Won!"
GameOn = False
else:
if is_board_full(Board):
draw_board(Board)
print "Tie"
break
else:
turn = 'AI' else:
move = get_AI_moves(Board, AI, P)
make_move(Board, AI, move)
draw_board(Board) if is_winner(Board, AI):
draw_board(Board)
print "GameOver AI has Won!"
GameOn = False
else:
if is_board_full(Board):
draw_board(Board)
print "Tie"
break
else:
turn = 'P' if not play_again():
break ##---+---+---
## x | o | x
##---+---+---
## o | x | o
##---+---+---
## x | o |
##---+---+---
注:
- python 2.7中input和raw_input的区别,python3中合并了
- 数据结构很简单,3X3的list of lists来表示棋盘。井字棋位置和小键盘一致。
- 参考文献: http://www.guokr.com/article/4754/
井字棋(Tic-Tac-Toe)的更多相关文章
- [CareerCup] 17.2 Tic Tac Toe 井字棋游戏
17.2 Design an algorithm to figure out if someone has won a game oftic-tac-toe. 这道题让我们判断玩家是否能赢井字棋游戏, ...
- python 井字棋(Tic Tac Toe)
说明 用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意.另外,90%+的代码也是本人逐字逐句敲的. minimax算法还没完全理解,所以参考了这里的代码,并作了修改. 特点 可以选 ...
- LeetCode 5275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game
地址 https://www.acwing.com/solution/LeetCode/content/6670/ 题目描述A 和 B 在一个 3 x 3 的网格上玩井字棋. 井字棋游戏的规则如下: ...
- POJ 2361 Tic Tac Toe
题目:给定一个3*3的矩阵,是一个井字过三关游戏.开始为X先走,问你这个是不是一个合法的游戏.也就是,现在这种情况,能不能出现.如果有人赢了,那应该立即停止.那么可以知道X的步数和O的步数应该满足x= ...
- [LeetCode] 348. Design Tic-Tac-Toe 设计井字棋游戏
Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the fol ...
- [LeetCode] Design Tic-Tac-Toe 设计井字棋游戏
Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the fol ...
- quick cocos2d-x 入门---井字棋
学习quick cocos2d-x 第二天 ,使用quick-x 做了一个井字棋游戏 . 我假设读者已经 http://wiki.quick-x.com/doku.php?id=zh_cn阅读了这个链 ...
- 程序设计入门—Java语言 第五周编程题 2井字棋(5分)
2 井字棋(5分) 题目内容: 嗯,就是视频里说的那个井字棋.视频里说了它的基本思路,现在,需要你把它全部实现出来啦. 你的程序先要读入一个整数n,范围是[3,100],这表示井字棋棋盘的边长.比如n ...
- [C++] 井字棋游戏源码
TicTac.h #define EX 1 //该点左鼠标 #define OH 2 //该点右鼠标 class CMyApp : public CWinApp { public: virtual B ...
- [游戏学习22] MFC 井字棋 双人对战
>_<:太多啦,感觉用英语说的太慢啦,没想到一年做的东西竟然这么多.....接下来要加速啦! >_<:注意这里必须用MFC和前面的Win32不一样啦! >_<:这也 ...
随机推荐
- sublime 前端开发工具
http://code.kpman.cc/2014/10/14/sublime-text-3-mac-%E6%8C%87%E5%8D%97/ gif 屏幕录制:http://recordit.co/ ...
- github教程--廖雪峰的官方网站
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
- 基于vue2.0的一个分页组件
分页组件在项目中经常要用到之前一直都是在网上找些jq的控件来用(逃..),最近几个项目用上vue了项目又刚好需要一个分页的功能.于是百度发现几篇文章介绍的实在方式有点复杂, 没耐心看自己动手造轮子写了 ...
- Android进程
android进程等级 1.前台进程 2.可视进程 3.服务进程 4.后台进程 5.空进程 让应用退出方式 finish();让应用成为空进程 Process.killProcess();杀进程 sy ...
- 学习笔记 css3--选择器&新增颜色模式&文本相关
Css3 选择器 --属性选择器 E[attr]只使用属性名,但没有确定任何属性值,E[attr="value"]指定属性名,并指定了该属性的属性值E[attr~="va ...
- Android 有用的快捷键
The powerful Android Studio 08 Jun 2016 Android Studio is the official tool for Android development ...
- html5属性placeholder的js 向下兼容支持(jquery版)
placeholder是html5表单特性中比较好用的一条,但是苦于其向下兼容性,所以一般要做向下兼容的站点都不敢用,如果有用到的地方,也是用js简单模拟而实现的,那么有没有一个一劳永逸的方法去解决这 ...
- Unix环境下PS1变量的设置
我的ps1命令提示符: export PS1="\[\e[31;1m\]\u @ \[\e[34;1m\]\h \[\e[36;1m\]\w \[\e[33;1m\]\t $ \[\e[37 ...
- FatMouse' Trade(hdoj1009)
Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats guarding th ...
- Tortoise-SVN 出现“unable to connect to a repository at url no element found”解决办法
安装要SVN server服务器后,建立自己的Repositories,创建自己的项目文件夹 如,https://xxxxxxxxxx.com:8443/ 安装Tortoise-svn进行设置目标链接 ...