2013-05-10 105 views
4

我是一名初級程序員,我知道pascal和C++的基礎知識。我用玩家電腦製作了一個Tic Tac Toe遊戲,遊戲全部結束。解決TicTacToe引擎

計算機生成一個隨機的地方,Os在桌子上,這是不好的。

我以爲我應該檢查每個獲勝位置的多個程序,並且計算機應該嘗試阻止玩家的X或獲得勝利的位置,但是如果是這樣的話,這將會浪費很多時間。

然後我想到了一個更簡單的版本,但它仍然需要很多時間來完成。

然後我想到更深入的瞭解:如何找到四個遊戲?如何在地球上有人會設法檢查每個可用的空間,以及如何有可能做出一個功能,絕對檢查任何獲勝或進步的球員/計算機的位置,哦,等待,這不是全部,如果玩家正在做一些技巧,所以他阻止了電腦?計算機如何知道?!?當然,這需要很長時間才能編程。我不是在談論更不可能的事情:國際象棋。

所以我在這裏問自己,應該有一種更簡單的方式來讓計算機搜索和解決一些問題,而不是噸的ifs。在這種情況下,如果你們中的任何一個知道解決這個問題的方法,我怎樣才能使最簡單的程序在TicTacToe遊戲中阻止和擊敗玩家?

如果有人想檢查我的代碼或使用它:http://pastebin.com/jhyUn7d1

+0

有* *許多技巧。對於像TTT這樣的簡單遊戲,您應該搜索「深度優先搜索」。對於更復雜的遊戲,您可以開始研究「alpha-beta修剪」。對於*真正*複雜的遊戲,您可以閱讀,比如說,「蒙特卡洛樹搜索」。 – 2013-05-10 18:54:05

+2

http://imgs.xkcd.com/comics/tic_tac_toe.png:P – BlackBear 2013-05-10 18:59:22

+0

[Simple tic-tac-toe AI]的可能重複(http://stackoverflow.com/questions/15753572/simple-tic-tac-腳趾愛) – 2013-05-10 19:29:00

回答

1

井字算法是這樣的:

  1. 採取現貨,如果要贏
  2. 採取現貨,如果要輸
  3. 帶角
  4. 帶非角落非中心
  5. 帶中心
+0

我相信你應該移動5到3. – 2013-05-10 19:01:42

+0

有更好的技術。角落並不總是最好的舉措。有些情況下,移動可能會產生兩個可能的勝利,而這兩個勝利都不能被阻止。 – 2013-05-10 19:12:10

0

我最近處理了這個,雖然我的代碼是在C#中。

我想出了一個評分每個候選人移動的方法。我採取的方法根據勝出所需的移動次數創建一個分數(需要的移動次數越少,得分越高)。

我的算法還考慮多個方塊的組合移動數。因此,該算法傾向於產生多個潛在勝利的移動(我知道的唯一真正的策略是Tic Tac Toe)。舉例來說,有時候可能會產生兩個必須被阻止的潛在勝利。由於對手只能阻擋一個,所以會贏得勝利。

我在文章A Tic-Tac-Toe Game Engine上發佈了我的整個代碼和說明。

0

簡短的回答是「嘗試所有不同的動作,直到贏得比賽,並記錄哪些將導致計算機獲勝」。

朗answerÖ

在有限的尺寸TTT遊戲,可能的移動遊戲贏之前的數量,並不算多,所以索性嘗試了每一種可能的舉動,然後遞歸嘗試所有可能的對手的動作,並繼續前進,直到比賽結束。給每一個動作一個「得分」,說明它有多好(例如,你有多少種不同的解決方案取得了成功的電腦,有多少成功的對手,並選擇「最好」的結果)。要小心,如果你做得好,你可能會得到一些近乎不可能勝出的東西。

3

你要尋找的是Minimax

使用這種算法的計算機將贏得每一個井字遊戲或者你可以調整計算機進行分析,以達到某種中等難度的動作的深度。

這並不難實現,你應該熟悉遞歸性和你設置,當然根據執行你的代碼不同,但維基百科頁面提供了一個很好的起點。

+1

這是完全正確的。最小極大值將用於在任何2人遊戲中確定最佳移動,確定性遊戲具有完美的遊戲狀態知識。所以它也適用於連接4,跳棋,甚至國際象棋。(儘管對於象棋這樣的狀態空間極其複雜的遊戲,該算法在實踐中是難以處理的)。另外,對於n個玩家遊戲,具有隱藏信息的遊戲,具有隨機元素的遊戲等,存在該算法的擴展。 – 2013-05-10 19:28:00

0

我這樣做一次,很久以前。我不知道我是否仍然有代碼躺在...

無論如何,我創建了一個函數,返回類型int,這是計算機應該放置其塊的方形(假設0是左上角, 8是右下方)。你的使用二維數組,所以會有所不同。

無論如何,對於每一行,列和對角線,檢查是否在該行任意兩件屬於球員。如果他們沒有,檢查相同但屬於計算機。在第一行,這是真實的,檢查剩下的一塊 - 如果它可用,把那塊作爲勝利。如果你有一個以玩家爲主的行,請檢查你是否已經有一個零件,然後將其粘住。

const int PlayerPiece = 1; 
const int CPiece = 2; 
const int Empty = 0; 

int board[3][3]; 
if(board[0][0] == PlayerPiece && board[0][1] == PlayerPiece && board [0][2] == Empty) 
{ 
    //Put_Your_Piece_In_[0][2] 
} 

然後,您可以去改變它,以便它可以檢查每一行即

int numRows = 3; 

for(int i = 0; i < numRows; i++) 
{ 
if(board[i][0] == PlayerPiece && board[i][1] == PlayerPiece && board[i][2] == Empty) 
    { 
    //Put_Piece_In_[i][2] 
    } 
} 

然後,做同樣的行。

你總是可以考慮井字棋本質上只是一個幻方,還算描述以及這裏:http://www.sciforums.com/showthread.php?134281-An-isomorphism-Tic-Tac-Toe-on-Magic-Square

0

沒有爲井字棋available on wikipedia一個完美的策略。這非常簡單。由於網格尺寸較小,因此需要測試的案例數量(例如,測試連續有兩個塊)是非常小的。