井字棋算法
1. 写象棋 AI 很厉害的人,下象棋也很厉害吗
先说结论,不会。百分之99的人不会,百分之1的人可能会。
写象棋 AI 牛和 下象棋牛没有半毛钱关系
什么井字棋,五子棋,中国象棋,国际象棋,最基本的算法就是这个,电脑可以看10步,20步,30步,甚至跟多步,太多了也看不了,计算的次数太多了,
比如我用极大极小算法写了个井字棋,总共有 9*8*7*6*5*4*3*2*1 种情况,电脑1秒都不要,就算出来了,永远下不赢,可以去b站看下 阿尔法狗 的纪录片解说,
2. 什么是极小化极大算法
楼主算是问对人啦。我是做计算机博弈游戏开发的。
1、提出这个问题是为了解决象棋,五子棋这样的二人全息零和博弈
二人:游戏是2个人玩的
全息:双方的棋面信息都可以看到。(扑克牌就不同了)
零和:双方的利益和是0.如果你胜利积1分。我就是输-1分。相加就是0
2、极大极小的概念是相对的
我走棋,希望对我的利益帮助是最大的。对你的利益帮主是最小的
3、经典的例子很多。井字棋,五子棋,中国象棋,国际象棋等
象棋为例:
我和楼主对弈,某一步,我有N中走法,期中一种走法x后。我还要评估楼主针对我的X走法的所有应付策略。如果对2个人的局面做一个评判。我肯定希望选择者N种走法中,即时你应对了,对我利益也是最大的那种走法。
4、这个概念我就贴个地址吧。后面的负极大极小算法,alphabeta剪枝算法都很经典的
希望你早日写一个属于你自己的极大较小值算法的游戏
http://www.xqbase.com/computer.htm【一定要通读10遍以上】
好运!
3. 可视化编程中,象棋的智能系统是怎么编出来的呢
其实就是通过if,switch等判断所有可能的走法,再通过优化算法,找出最好的走法,建议看看AI方面的书就知道了,其实没那么玄
4. python 井字棋 ALPHA-BETA剪枝算法和暴力算法 具体代码
#!/usr/bin/env python
'''Tic tac toe in python, Minimax with alpha-beta pruning.'''
import sys
import random
import getopt
# Board: array of 9 int, positionally numbered like this:
# 0 1 2
# 3 4 5
# 6 7 8
# Well-known board positions
WINNING_TRIADS = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7),
(2, 5, 8), (0, 4, 8), (2, 4, 6))
PRINTING_TRIADS = ((0, 1, 2), (3, 4, 5), (6, 7, 8))
# The order in which slots get checked for absence of a player's token:
SLOTS = (0, 1, 2, 3, 4, 5, 6, 7, 8)
# Internal-use values. Chosen so that the "winner" of a finished
# game has an appropriate value, as X minimizes and O maximizes
# the board's value (function board_valuation() defines "value")
# Internally, the computer always plays Os, even though the markers[]
# array can change based on -r command line flag.
X_token = -1
Open_token = 0
O_token = 1
# Strings for output: player's markers, phrase for end-of-game
MARKERS = ['_', 'O', 'X']
END_PHRASE = ('draw', 'win', 'loss')
HUMAN = 1
COMPUTER = 0
def board_valuation(board, player, next_player, alpha, beta):
'''Dynamic and static evaluation of board position.'''
# Static evaluation - value for next_player
wnnr = winner(board)
if wnnr != Open_token:
# Not a draw or a move left: someone won
return wnnr
elif not legal_move_left(board):
# Draw - no moves left
return 0 # Cat
# If flow-of-control gets here, no winner yet, not a draw.
# Check all legal moves for "player"
for move in SLOTS:
if board[move] == Open_token:
board[move] = player
val = board_valuation(board, next_player, player, alpha, beta)
board[move] = Open_token
if player == O_token: # Maximizing player
if val > alpha:
alpha = val
if alpha >= beta:
return beta
else: # X_token player, minimizing
if val < beta:
beta = val
if beta <= alpha:
return alpha
if player == O_token:
retval = alpha
else:
retval = beta
return retval
def print_board(board):
'''Print the board in human-readable format.
Called with current board (array of 9 ints).
'''
for row in PRINTING_TRIADS:
for hole in row:
print MARKERS[board[hole]],
print
def legal_move_left(board):
''' Returns True if a legal move remains, False if not. '''
for slot in SLOTS:
if board[slot] == Open_token:
return True
return False
def winner(board):
''' Returns -1 if X wins, 1 if O wins, 0 for a cat game,
0 for an unfinished game.
Returns the first "win" it finds, so check after each move.
Note that clever choices of X_token, O_token, Open_token
make this work better.
'''
for triad in WINNING_TRIADS:
triad_sum = board[triad[0]] + board[triad[1]] + board[triad[2]]
if triad_sum == 3 or triad_sum == -3:
return board[triad[0]] # Take advantage of "_token" values
return 0
def determine_move(board):
''' Determine Os next move. Check that a legal move remains before calling.
Randomly picks a single move from any group of moves with the same value.
'''
best_val = -2 # 1 less than min of O_token, X_token
my_moves = []
for move in SLOTS:
if board[move] == Open_token:
board[move] = O_token
val = board_valuation(board, X_token, O_token, -2, 2)
board[move] = Open_token
print "My move", move, "causes a", END_PHRASE[val]
if val > best_val:
best_val = val
my_moves = [move]
if val == best_val:
my_moves.append(move)
return random.choice(my_moves)
def recv_human_move(board):
''' Encapsulate human's input reception and validation.
Call with current board configuration. Returns
an int of value 0..8, the Human's move.
'''
looping = True
while looping:
try:
inp = input("Your move: ")
yrmv = int(inp)
if 0 <= yrmv <= 8:
if board[yrmv] == Open_token:
looping = False
else:
print "Spot already filled."
else:
print "Bad move, no donut."
except EOFError:
print
sys.exit(0)
except NameError:
print "Not 0-9, try again."
except SyntaxError:
print "Not 0-9, try again."
if looping:
print_board(board)
return yrmv
def usage(progname):
'''Call with name of program, to explain its usage.'''
print progname + ": Tic Tac Toe in python"
print "Usage:", progname, "[-h] [-c] [-r] [-x] [-X]"
print "Flags:"
print "-x, -X: print this usage message, then exit."
print "-h: human goes first (default)"
print "-c: computer goes first"
print "-r: computer is X, human is O"
print "The computer O and the human plays X by default."
def main():
'''Call without arguments from __main__ context.'''
try:
opts, args = getopt.getopt(sys.argv[1:], "chrxX",
["human", "computer", "help"])
except getopt.GetoptError:
# print help information and exit:
usage(sys.argv[0])
sys.exit(2)
next_move = HUMAN # Human goes first by default
for opt, arg in opts:
if opt == "-h":
next_move = HUMAN
if opt == "-c":
next_move = COMPUTER
if opt == "-r":
MARKERS[-1] = 'O'
MARKERS[1] = 'X'
if opt in ("-x", "-X", "--help"):
usage(sys.argv[0])
sys.exit(1)
# Initial state of board: all open spots.
board = [Open_token, Open_token, Open_token, Open_token, Open_token,
Open_token, Open_token, Open_token, Open_token]
# State machine to decide who goes next, and when the game ends.
# This allows letting computer or human go first.
while legal_move_left(board) and winner(board) == Open_token:
print
print_board(board)
if next_move == HUMAN and legal_move_left(board):
humanmv = recv_human_move(board)
board[humanmv] = X_token
next_move = COMPUTER
if next_move == COMPUTER and legal_move_left(board):
mymv = determine_move(board)
print "I choose", mymv
board[mymv] = O_token
next_move = HUMAN
print_board(board)
# Final board state/winner and congratulatory output.
try:
# "You won" should never appear on output: the program
# should always at least draw.
print ["Cat got the game", "I won", "You won"][winner(board)]
except IndexError:
print "Really bad error, winner is", winner(board)
sys.exit(0)
#-------
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print
sys.exit(1)
5. 极大极小算法有些不明白
先来说极小极大算法主要应用于什么样的游戏:
1. 零和游戏(Zero-sum Game):意思就是你死我活,一方的胜利代表另一方的失败,比如,象棋,五子棋等。
2. 完全信息(Perfect Information):玩家知道之前所有的步骤。象棋就是完全信息,因为玩家是交替着落子,且之前的步骤都能在棋盘上体现,但是石头剪子布就不是。
这样的游戏通常可以把他们看作一个树状图,把每一种可能性列出来。比如下面这个井字棋游戏,Max代表你自己,Min代表你的对手。
这个时候我们需要给每一种结果一个分数,就是这里的Utility。这个分数是站在我自己(也就是Max)的角度评估的,比如上图中我赢了就是+1,输了是-1,平局时0。所以,我希望最大化这个分数,而我的对手希望最小化这个分数。(在游戏中,这个分数被称为static value。)这里要说一下,井字棋是个比较简单的游戏,所以可以列出所有可能的结果。但是,大部分游戏是不太可能把所有结果都列出来的。根据计算机运算量,我们可能只能往前推7,8步,所以这个时候分数就不只-1,1,0这么简单了,会有专门的算法来根据当前结果给不同的分数。
假设我们有如下图的游戏,我是先手,我应该如何利用Minmax算法来选出第一步怎么走呢?
当然对于一个复杂的游戏来说,比如象棋,肯定是需要非常多步才能完成的。这就导致结果的数量是成几何增长的,也就是说,如果这个游戏每一步都有n个选择,那么在x步以后,将会有n^x个选择。这个时候,我们就需要采取剪枝算法(Alpha-Beta)来减少运算量。从剪枝算法这个名字我们就能看出,这个算法能让我们剪掉树状图中的一些分支,从而减少运算量。在这里也说一下剪枝算法,因为这并不是个不同于极小极大的算法,而是极小极大算法的升级版。
我们将游戏简化成如下图,使用Minimax算法,我们可以得出这样的结果
6. 关于编写井字棋的问题
用坐标判断,比如说是0,0 0,1 0,2 1,0 1,1
如果两个点的x或y坐标相等,则在一条直线上,需要封堵。
或者|x1-x2|=|y1-y2|,刚在一条斜线上,需要封堵。
7. 井字棋如何让电脑防守,编程算法,求具体循环代码
这样你看怎么样,假设你的棋盘是个3*3数组如下
0 0 0
0 0 0
0 0 0
1代表黑棋,2代表白棋,0代表未填写
我们要判断是否防守,和判断输赢其实都一样--检查可能构成同色棋子3连的8个方向
1 1 1
0 0 0
0 0 0
0 0 0
1 1 1
0 0 0
0 0 0
0 0 0
1 1 1
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 1 0
0 0 1
0 0 1
0 0 1
0 0 1
0 1 0
1 0 0
1 0 0
0 1 0
0 0 1
以上是获胜的八种可能咯
那么,怎么防守呢,当出现以上8种方向的雏形时,也就是说其中一个方向上已经有两个同色的棋子而另一个位置为0,这时候说明如果再不防守就输啦
e.g.
1 2 0
0 1 1
0 0 2
这时候轮到白棋走,发现第二行,已经有两个黑棋,而第二行第一个元素为0,所以应该这样走
1 2 0
2 1 1
0 0 2
算法实现很简单,一个FOR循环8次,做上述检查便可得知是否需要防守,一起具体坐标
至于你的第二个问题:画棋盘,你可以网上找些棋盘和棋子图片,自己做贴图,鼠标点击的响应
8. 井字棋一字棋三字棋现在才搞懂是同一种 谁能给我找点文字介绍 多谢
“井字棋”游戏(又叫“三子棋”),是一款十分经典的益智小游戏,想必很多玩家都有玩过。“井字棋”的棋盘很简单,是一个3×3的格子,很像中国文字中的“井”字,所以得名“井字棋”。“井字棋”游戏的规则与“五子棋”十分类似,“五子棋”的规则是一方首先五子连成一线就胜利;“井字棋”是一方首先三子连成一线就胜利。
井字棋(英文名Tic-Tac-Toe)
井字棋的出现年代估计已不可考,西方人认为这是由古罗马人发明的;但我们中国人认为,既然咱们都发明了围棋、五子棋,那发明个把井字棋自然是不在话下。这些纯粹是口舌之争了,暂且不提。
想起小时候上课喜欢玩井字棋,只要一张草稿纸、一支笔、同桌两人就可以玩了。上体育课,也可以拿着树枝在沙坑里玩。但一直感觉这游戏太简单了,后来接触了五子棋,着迷了一阵,但水平总是很差,便也不玩了。
一字棋游戏极小极大分析法
设有九个空格,由MAX,MIN二人对弈,轮到谁走棋谁就往空格上放一只自己的棋子,谁先使自己的棋子构成“三子成一线”(同一行或列或对角线全是某人的棋子),谁就取得了胜利。
用叉号表示MAX,用圆圈代表MIN。
比如右图中就是MIN取胜的棋局。
为了不致于生成太大的博弈树,假设每次仅扩展两层。估价函数定义如下:
设棋局为P,估价函数为e(P)。
(1) 若P对任何一方来说都不是获胜的位置,则e(P)=e(那些仍为MAX空着的完全的行、列或对角线的总数)-e(那些仍为MIN空着的完全的行、列或对角线的总数)
(2) 若P是MAX必胜的棋局,则e(P)=+∞。
(3) 若P是B必胜的棋局,则e(P)=-∞。
比如P如右图示,则e(P)=6-4=2
要注意利用棋盘位置的对称性,在生成后继节点的位置时,下列博弈结局
都是相同的棋局(在博弈中,一宇棋的分枝系数比较小起初是由于对称性,而后是由于棋盘上未布子的空格减少所致)。图3.15画出了经过两层搜索生成的博弈树,静态估值记在端节点下面,倒推值记在圆圈内。
由于右图所示位置具有最大的倒推值,它应当选取为MAX的第一步(正好是MAX的最好的优先走步)。
现在我们假设MAX走了这一步,而MIN的回步是直接在X上方的空格里放上一个圆圈(对MAX来说这是一步坏棋,他一定没有采用好的搜索策略)。下一步,MAX又在新的格局下搜索两层,产生如图3.16所示的搜索图。
现在图中MAX有两个可能“最好的”优先走步,假设MAX走了图上指明的那一步。而MIN为了避免立即败北被迫走了另一步,从而产生如下棋局:MAX再次搜索,产生如图3.17所示的树。
在这棵树中某些端节点(例如其中一个标记着A)代表MIN获胜,因此它们的估值为—∞。当这些估值被倒推回去时,可看到MAX的最好的也是唯一能使他避免立即失败的一个走步。现在,MIN可以看出MAX必然在他的下一走步中获胜,因此,MIN只好认输。
按极大极小算法编程下一字棋的演示(右图,可以点击操作)...
我们就利用Visual Basic编写一个“井字棋”的小游戏。
【设计思路】
首先,我们要知道,“井字棋”游戏是一款典型的棋类游戏,游戏时一方式是电脑,另一方是玩家。所以,这类游戏在开始时有两种方式:一种是玩家先走;另一种是电脑先走。这是我们要考虑的第一个问题。
其次,由于与玩家对战的是计算机,所以我们要编写一个过程(Chuqi),它可以使程序模拟人的思维与人下棋(其实就是“人工智能”的体现),这个Chuqi过程也是本游戏软件的关键。此外,我们还要编写两个过程(Lianxian和Shuying),Lianxian过程用来时刻判断棋盘中是否有三个棋子连成一线;Shuying过程用来判断如果有三个棋子连成一线,是哪一方连成一线的,即判断哪一方获胜。
以上几个问题就是该“井字棋”游戏实现的关键思路。....
http://family.chinaok.com/2005-12/15745.htm
9. C语言 怎么编程井字棋
简单来说,定义数据结构(比如棋盘数组,棋盘格子以及棋子,双方玩家等相关的数据结构表示),定义规则(比如同一个位置不能放两颗棋子,三颗棋子连线放胜利)。
具体取决于需求,比如图形表示和AI(人工智能)等等。如果你只是想要简单的用命令行和文字输出表示,那么编写一个控制台应用程序就可以。如果需要图形等控制,需要借助一些图形以及UI库等。但是这些外部表示可以跟核心数据结构和规则,算法等分离开来。所以刚开始先用文字表示写出核心代码,后续可以逐渐加上UI图形,AI等。