井字棋演算法
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等。