井字棋介绍: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)的更多相关文章

  1. [CareerCup] 17.2 Tic Tac Toe 井字棋游戏

    17.2 Design an algorithm to figure out if someone has won a game oftic-tac-toe. 这道题让我们判断玩家是否能赢井字棋游戏, ...

  2. python 井字棋(Tic Tac Toe)

    说明 用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意.另外,90%+的代码也是本人逐字逐句敲的. minimax算法还没完全理解,所以参考了这里的代码,并作了修改. 特点 可以选 ...

  3. LeetCode 5275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game

    地址 https://www.acwing.com/solution/LeetCode/content/6670/ 题目描述A 和 B 在一个 3 x 3 的网格上玩井字棋. 井字棋游戏的规则如下: ...

  4. POJ 2361 Tic Tac Toe

    题目:给定一个3*3的矩阵,是一个井字过三关游戏.开始为X先走,问你这个是不是一个合法的游戏.也就是,现在这种情况,能不能出现.如果有人赢了,那应该立即停止.那么可以知道X的步数和O的步数应该满足x= ...

  5. [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 ...

  6. [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 ...

  7. quick cocos2d-x 入门---井字棋

    学习quick cocos2d-x 第二天 ,使用quick-x 做了一个井字棋游戏 . 我假设读者已经 http://wiki.quick-x.com/doku.php?id=zh_cn阅读了这个链 ...

  8. 程序设计入门—Java语言 第五周编程题 2井字棋(5分)

    2 井字棋(5分) 题目内容: 嗯,就是视频里说的那个井字棋.视频里说了它的基本思路,现在,需要你把它全部实现出来啦. 你的程序先要读入一个整数n,范围是[3,100],这表示井字棋棋盘的边长.比如n ...

  9. [C++] 井字棋游戏源码

    TicTac.h #define EX 1 //该点左鼠标 #define OH 2 //该点右鼠标 class CMyApp : public CWinApp { public: virtual B ...

  10. [游戏学习22] MFC 井字棋 双人对战

    >_<:太多啦,感觉用英语说的太慢啦,没想到一年做的东西竟然这么多.....接下来要加速啦! >_<:注意这里必须用MFC和前面的Win32不一样啦! >_<:这也 ...

随机推荐

  1. AspnetPager放在UpdatePanel中,回到顶部。

    最近在做一个项目时,使用了AspNetPager分页控件进行分页,为了防止点击下一页时搜索条件消失掉,使用了UpdatePanel来进行局部刷新. 由此引发了一个问题,即点击某一页时,页面没有返回到顶 ...

  2. 定时排程刷新微信access-token

    微信公众号开发中最常遇到的就是调用接口时候需要有API的access-token(非网页授权的access-token),有了这个token之后,才可以发生模板消息等.这里的做法主要是用nodejs的 ...

  3. 地图:CLGeocoder地址解析与反地址解析

    1.导入系统框架

  4. (转)Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds

    仰天长啸 Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds... 当启动tomcat时候出现 S ...

  5. CSS 四个样式表格

    1. 单像素边框CSS表格 这是一个很常用的表格样式. 源代码: <!-- CSS goes in the document HEAD or added to your external sty ...

  6. android的reference table的问题

    写得android程序总是崩溃,感觉像是内存泄露,但是检查代码发现该释放的都释放了.最终无奈,删除了接口函数中的调用,只使用下面的测试代码. JNIEXPORT jboolean JNICALL Ja ...

  7. python核心编程-第四章-个人笔记

    1.所有的python对象都拥有三个特性: ①身份:每个对象都有唯一的身份标识自己,可用内建函数id()来得到.基本不会用到,不用太关心 >>> a = 2 >>> ...

  8. 【转载】深入浅出http请求

    转载链接:http://www.cnblogs.com/yin-jingyu/archive/2011/08/01/2123548.html HTTP(HyperText Transfer Proto ...

  9. 定制样式插入到ueditor

    AngularJs定制样式插入到ueditor中的问题总结 总结一下自己给编辑器定制样式的过程中所遇到的问题,主要是编辑器的二次开发接口,以及用angular定制样式,问题不少,终于在**的帮助下,完 ...

  10. PHP数组排序函数array_multisort()函数详解

    这个函数因为用到了,并且在网上找了半天终于找到了一个写的通俗易懂的文章,在这里分享给大家. 原文链接:http://blog.163.com/lgh_2002/blog/static/44017526 ...