⭕⭕❌❌回憶殺 python實現 井字遊戲 可線上玩+AI對戰

閱讀時間約 1 分鐘

井字遊戲(OOXX)的遊戲描述


Tic Tac Toe(井字遊戲)是經典的雙人棋盤遊戲,在一個3x3的方格中進行。

每回合兩個玩家輪流選一個位置,讓自己的符號( X 或 O)在
水平線、垂直線或對角線上連成一線的玩家宣告獲勝


上層思考邏輯與框架

  1. 棋盤設置:
    • 遊戲使用一個3x3的方格,總共有九個空格可供玩家選擇。
  2. 玩家:
    • 兩名玩家交替進行,X代表AI , O代表真人玩家。
  3. 遊戲進行:
    • 兩位玩家輪流在空格中放置自己的符號。每次放置後,
      檢查是否有任何一方的符號在橫向、縱向或對角線上連成一直線
  4. 勝利條件:
    • 若某位玩家成功將三個相同的符號連成一線,則該玩家獲勝
      如果所有九個格子都被填滿而沒有任何一方獲勝,則遊戲結束,結果為平局。

中層功能元件分析


1.怎麼建立井字遊戲的遊戲版?


透過list comprehension建立長度為9的陣列,並且標上1~9的數字,提示玩家每個位置所代表的數字。

| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |

1 對應到左上方的格子。2 對應到正上方的格子。3 對應到右上方的格子。

4 對應到正左方的格子。5 對應到正中央的格子。6 對應到正右方的格子。

7 對應到左下方的格子。8 對應到正下方的格子。9 對應到右下方的格子。

# 初始化棋盤
board = [str(i+1) for i in range(9)]

2.怎麼輸出遊戲狀態?


透過雙層迴圈,輸出3x3的遊戲版,並且以|當作間隔符號。

如圖所示

| 1 | 2 | 3 |
| 4 | X | 6 |
| 7 | 8 | 9 |


# 輸出棋盤
def print_board():
for row in [board[i*3:(i+1)*3] for i in range(3)]:
print('| ' + ' | '.join(row) + ' |')

3.人類玩家怎麼選擇位置?


從鍵盤接收1~9的數字,依照數字在遊戲版上對應的位置放置O的符號。


        # 玩家回合
player_move = int(input("選擇一個位置 (1-9): ")) - 1

if board[player_move].isnumeric():

board[player_move] = 'O'

4.AI玩家怎麼選擇位置?


AI根據board遊戲版當前的棋盤狀態,
透過mixMax演算法遞迴展開所有可能的分枝情況


最小化人類玩家勝率,最大化AI玩家勝率。

選擇對AI玩家最有利的位置,讓X連成一線的機會最大化


# minMax演算法
# O 代表玩家
# X 代表AI
# AI選擇位置時,會尋找勝率最大的位置
def minimax(board, depth, is_maximizing):
if check_winner(board, 'O'):
return -1
elif check_winner(board, 'X'):
return 1
elif is_draw(board):
return 0

if is_maximizing:
best_score = -math.inf
for i in range(9):
if board[i].isnumeric():
original = board[i]
board[i] = 'X'
score = minimax(board, depth + 1, False)
board[i] = original
best_score = max(score, best_score)
return best_score
else:
best_score = math.inf
for i in range(9):
if board[i].isnumeric():
original = board[i]
board[i] = 'O'
score = minimax(board, depth + 1, True)
board[i] = original
best_score = min(score, best_score)
return best_score


# AI透過mixMax演算法,選擇最好的位置
def best_move():
best_score = -math.inf
move = 0
for i in range(9):
#if board[i] == ' ':
if board[i].isnumeric():
original = board[i]
board[i] = 'X'
score = minimax(board, 0, False)
board[i] = original
if score > best_score:
best_score = score
move = i
return move

5.怎麼檢查是否已經有玩家連成一線,宣告獲勝?


檢查遊戲盤上所有水平線、垂直線、大對角線的位置,
看看是否已經有O連成一線或者X連成一線的情況。

如果O連成一線,代表人類玩家宣告獲勝。

如果X連成一線,代表AI玩家宣告獲勝。


# 檢查是否有玩家獲勝
def check_winner(board, player):
win_conditions = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
return any(board[a] == board[b] == board[c] == player for a, b, c in win_conditions)


while 遊戲循環:

...

if check_winner(board, 'O'):
print_board()
print("你贏了!")
break

if check_winner(board, 'X'):
print_board()
print("你輸了!")
break

6.如何判斷雙方平手?


檢查是有所有位置都已經被填滿O或X的符號?

如果已經沒有剩餘的空位,代表雙方平手。

如果還有空位,則井字遊戲繼續進行。


# 檢查是否平局
def is_draw(board):

space_count = 0
for row in board:
for cell in row:
if cell.isnumeric() == True:
return False

return True

7.怎麼建立遊戲循環機制?


外層以while True迴圈建立遊戲循環機制。

每回合玩家和AI輪流選一個位置放下O或X。


在每回合的末端,判斷是否已經有玩家獲勝或者平手?

如果是,則遊戲結束,break離開遊戲循環機制的while迴圈


		# AI先手
# AI在正中央位置放一個X
ai_move = 4
board[ai_move] = 'X'

print_board()
while True:

# 玩家回合
player_move = int(input("選擇一個位置 (1-9): ")) - 1

if board[player_move].isnumeric():

board[player_move] = 'O'
if check_winner(board, 'O'):
print_board()
print("你贏了!")
break
elif is_draw(board):
print_board()
print("平局!")
break

# AI回合
ai_move = best_move()
board[ai_move] = 'X'
if check_winner(board, 'X'):
print_board()
print("你輸了!")
break
elif is_draw(board):
print_board()
print("平局!")
break
else:
print("位置已被佔用,請選擇其他位置。")
print_board()

底層的完整實作: 井字遊戲(OOXX)

import math

# 初始化棋盤
board = [str(i+1) for i in range(9)]

# 輸出棋盤
def print_board():
for row in [board[i*3:(i+1)*3] for i in range(3)]:
print('| ' + ' | '.join(row) + ' |')

# 檢查是否有玩家獲勝
def check_winner(board, player):
win_conditions = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
return any(board[a] == board[b] == board[c] == player for a, b, c in win_conditions)


# 檢查是否平局
def is_draw(board):

space_count = 0
for row in board:
for cell in row:
if cell.isnumeric() == True:
return False

return True


# Minimax演算法
# O 代表玩家
# X 代表AI
# AI選擇位置時,會尋找勝率最大的位置
def minimax(board, depth, is_maximizing):
if check_winner(board, 'O'):
return -1
elif check_winner(board, 'X'):
return 1
elif is_draw(board):
return 0

if is_maximizing:
best_score = -math.inf
for i in range(9):
if board[i].isnumeric():
original = board[i]
board[i] = 'X'
score = minimax(board, depth + 1, False)
board[i] = original
best_score = max(score, best_score)
return best_score
else:
best_score = math.inf
for i in range(9):
if board[i].isnumeric():
original = board[i]
board[i] = 'O'
score = minimax(board, depth + 1, True)
board[i] = original
best_score = min(score, best_score)
return best_score


# AI透過mixMax演算法,選擇最好的位置
def best_move():
best_score = -math.inf
move = 0
for i in range(9):
#if board[i] == ' ':
if board[i].isnumeric():
original = board[i]
board[i] = 'X'
score = minimax(board, 0, False)
board[i] = original
if score > best_score:
best_score = score
move = i
return move


# 遊戲主體
def play_game():

# AI先手
# AI在正中央位置放一個X
ai_move = 4
board[ai_move] = 'X'

print_board()
while True:

# 玩家回合
player_move = int(input("選擇一個位置 (1-9): ")) - 1

if board[player_move].isnumeric():

board[player_move] = 'O'
if check_winner(board, 'O'):
print_board()
print("你贏了!")
break
elif is_draw(board):
print_board()
print("平局!")
break

# AI回合
ai_move = best_move()
board[ai_move] = 'X'
if check_winner(board, 'X'):
print_board()
print("你輸了!")
break
elif is_draw(board):
print_board()
print("平局!")
break
else:
print("位置已被佔用,請選擇其他位置。")
print_board()


if __name__ == '__main__':
play_game()

試玩畫面

raw-image



點這行 線上執行 與 試玩(在新的頁面按Run開始玩)


延伸思考:


如果對程式或者演算法有興趣的同學,

可以試著觀察OOXX井字遊戲的規律,

開發更強的連線演算法,嘗試讓兩個AI玩家對戰。

很有趣喔~

83會員
425內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
發表第一個留言支持創作者!
深入探討圖(Graph)的基本概念 及 最短路徑Shortest Path的尋找。 我們專注於廣度優先搜尋(BFS)演算法,以等權圖的最短路徑為例, 詳細說明如何利用BFS從起點擴散到終點,並且提供詳細的程式碼範例。 透過實作,讀者能夠更清楚理解圖論及BFS的應用,並體會水波紋擴散模型的重要性。
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。 節點Vertex: 節點
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。
Min-Heap 最小堆是一種特殊的樹狀資料結構, 其中每個節點的值都小於或等於其子節點的值。這意味著最小值總是位於根節點。 Min-Heap 常用於實作優先權佇列 (Priority Queue)、Dijkstra 演算法、 排序以及尋找中位數等應用。
Prefix Sum(前綴和)是一種用於計算陣列中任意區間和的高效方法。 前綴和算是一種犧牲空間換取時間效能提升的策略。 這在需要頻繁查詢區間和的情況下特別有用。 一開始,初始化時花費O(n)時間,掃描每個元素累加,建立一個prefix sum table, 接著,提供query介面查詢區間和
二元搜尋樹(Binary Search Tree,簡稱 BST)是一種特殊的二元樹結構, 具有以下特性: 左子樹:左子樹上所有節點的值均小於該節點的值。 右子樹:右子樹上所有節點的值均大於該節點的值。 無重複值:每個節點的值都是唯一的。 這些特性使得二元搜尋樹在搜尋、插入和刪除操作具有較佳的效能。
深入探討圖(Graph)的基本概念 及 最短路徑Shortest Path的尋找。 我們專注於廣度優先搜尋(BFS)演算法,以等權圖的最短路徑為例, 詳細說明如何利用BFS從起點擴散到終點,並且提供詳細的程式碼範例。 透過實作,讀者能夠更清楚理解圖論及BFS的應用,並體會水波紋擴散模型的重要性。
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。 節點Vertex: 節點
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。
Min-Heap 最小堆是一種特殊的樹狀資料結構, 其中每個節點的值都小於或等於其子節點的值。這意味著最小值總是位於根節點。 Min-Heap 常用於實作優先權佇列 (Priority Queue)、Dijkstra 演算法、 排序以及尋找中位數等應用。
Prefix Sum(前綴和)是一種用於計算陣列中任意區間和的高效方法。 前綴和算是一種犧牲空間換取時間效能提升的策略。 這在需要頻繁查詢區間和的情況下特別有用。 一開始,初始化時花費O(n)時間,掃描每個元素累加,建立一個prefix sum table, 接著,提供query介面查詢區間和
二元搜尋樹(Binary Search Tree,簡稱 BST)是一種特殊的二元樹結構, 具有以下特性: 左子樹:左子樹上所有節點的值均小於該節點的值。 右子樹:右子樹上所有節點的值均大於該節點的值。 無重複值:每個節點的值都是唯一的。 這些特性使得二元搜尋樹在搜尋、插入和刪除操作具有較佳的效能。
你可能也想看
Google News 追蹤
Thumbnail
本專欄將提供給您最新的市場資訊、產業研究、交易心法、優質公司介紹,以上內容並非個股分析,還請各位依據自身狀況作出交易決策。歡迎訂閱支持我,獲得相關內容,也祝您的投資之路順遂! 每年 $990 訂閱方案👉 https://reurl.cc/VNYVxZ 每月 $99 訂閱方案👉https://re
Thumbnail
本篇介紹單人遊戲的核心架構與邏輯,涵蓋發牌、抽牌、出牌及遊戲結算等重要步驟。文章也詳細介紹了使用 socket.io 建立連線的過程,並說明如何利用 React Hooks 管理遊戲狀態,提及後端伺服器如何處理玩家加入房間的事件,並簡要介紹了房間資訊的管理,此文將分為多篇進一步介紹遊戲事件部分。
Thumbnail
平時下棋是一對一進行,完全是倚賴個人的實力一較高下,而圍棋也是可以分隊比賽,在外課上課時,為了增進大家的向心力,舉辦了「隊際賽」,分成兩隊輪流上台落子,也在交換棒次的間隔可以讓大家討論,讓棋力強的同學帶領大家,也讓大家感受不一樣的下棋方式!
Thumbnail
探索圍棋的無限魅力 —— 提升智慧與人文素養的最佳選擇 圍棋,這一源自中國的古老智力遊戲,已有數千年的歷史。它不僅是一種極富挑戰性的策略遊戲,更是一門深具文化內涵的藝術。來到中央棋院,讓我們一起探索圍棋的無限魅力!
Thumbnail
中國跳棋的棋盤有6個角,最多可供6人進行遊戲,每個人把各自同顏色的棋子擺滿一個角,按照規則輪流走棋,以最早全部抵達並擺滿對角為優勝。 若是2人或4人對局,那麼將棋子放在相對的角上;3人對局則將棋子互相間隔一個角擺放以平均分布;6人對局為將所有角擺滿。因為平衡性要求,不宜進行5人遊戲。 每方棋
Thumbnail
24點數學遊戲是一款適合小朋友與想動動腦的朋友們的小遊戲,遊戲規則簡單易懂,可訓練邏輯能力。遊戲分為單人與多人模式,可以讓玩家自行挑戰高分或是與其他玩家競爭。算式中不同的數學符號會對應不同的加分機制。遊戲網站連結與專案 repo 也都提供在文章中。
Thumbnail
原版的官方規則導入記分機制,但因為計算過於繁複,所以一般遊玩時較少採用。本變體規則旨在還原原規則的策略性,並保留平常的遊玩樂趣。 1. 配件準備 4枚不同顏色的棋子(紅、藍、黃、綠),以及一張標記0~15的場地。 2. 記分方式 一開始所有棋子都在0的位置。每一局結束時,贏家以外的所有人拿出
圍棋有個特別的別稱,叫做「手談」,因對局時,是用手拿著棋子下,雙方並不會有太多言語上的交談,而根據對局者的下棋節奏快慢及下棋的力量,可以反映出雙方心態上的變化,利用著棋子進行棋局上的交流,故稱做「手談」。 中央棋院官網連結 : https://www.centralgo.com.tw/
Thumbnail
【一】座標與陣地 【二】棋駒的走法 【三】勝敗的細節 【四】最後的補充
圍棋,是一種古老棋類遊戲,兩位玩家輪流在棋盤上放置黑白兩色的圓形石子,目標是在棋盤上形成多個區域,以擴大自己的領地並同時圍堵對手的石子。儘管規則簡單,但卻擁有極其豐富的戰術和戰略,每一步都是挑戰與機遇的交錯。加入我們,一同探索、學習、成長,讓圍棋成為你生活中不可或缺的一部分!
在這個充滿挑戰和樂趣的課程中,我們將教導小朋友們如何通過下圍棋來提升他們的穩定性和數理邏輯!
Thumbnail
本專欄將提供給您最新的市場資訊、產業研究、交易心法、優質公司介紹,以上內容並非個股分析,還請各位依據自身狀況作出交易決策。歡迎訂閱支持我,獲得相關內容,也祝您的投資之路順遂! 每年 $990 訂閱方案👉 https://reurl.cc/VNYVxZ 每月 $99 訂閱方案👉https://re
Thumbnail
本篇介紹單人遊戲的核心架構與邏輯,涵蓋發牌、抽牌、出牌及遊戲結算等重要步驟。文章也詳細介紹了使用 socket.io 建立連線的過程,並說明如何利用 React Hooks 管理遊戲狀態,提及後端伺服器如何處理玩家加入房間的事件,並簡要介紹了房間資訊的管理,此文將分為多篇進一步介紹遊戲事件部分。
Thumbnail
平時下棋是一對一進行,完全是倚賴個人的實力一較高下,而圍棋也是可以分隊比賽,在外課上課時,為了增進大家的向心力,舉辦了「隊際賽」,分成兩隊輪流上台落子,也在交換棒次的間隔可以讓大家討論,讓棋力強的同學帶領大家,也讓大家感受不一樣的下棋方式!
Thumbnail
探索圍棋的無限魅力 —— 提升智慧與人文素養的最佳選擇 圍棋,這一源自中國的古老智力遊戲,已有數千年的歷史。它不僅是一種極富挑戰性的策略遊戲,更是一門深具文化內涵的藝術。來到中央棋院,讓我們一起探索圍棋的無限魅力!
Thumbnail
中國跳棋的棋盤有6個角,最多可供6人進行遊戲,每個人把各自同顏色的棋子擺滿一個角,按照規則輪流走棋,以最早全部抵達並擺滿對角為優勝。 若是2人或4人對局,那麼將棋子放在相對的角上;3人對局則將棋子互相間隔一個角擺放以平均分布;6人對局為將所有角擺滿。因為平衡性要求,不宜進行5人遊戲。 每方棋
Thumbnail
24點數學遊戲是一款適合小朋友與想動動腦的朋友們的小遊戲,遊戲規則簡單易懂,可訓練邏輯能力。遊戲分為單人與多人模式,可以讓玩家自行挑戰高分或是與其他玩家競爭。算式中不同的數學符號會對應不同的加分機制。遊戲網站連結與專案 repo 也都提供在文章中。
Thumbnail
原版的官方規則導入記分機制,但因為計算過於繁複,所以一般遊玩時較少採用。本變體規則旨在還原原規則的策略性,並保留平常的遊玩樂趣。 1. 配件準備 4枚不同顏色的棋子(紅、藍、黃、綠),以及一張標記0~15的場地。 2. 記分方式 一開始所有棋子都在0的位置。每一局結束時,贏家以外的所有人拿出
圍棋有個特別的別稱,叫做「手談」,因對局時,是用手拿著棋子下,雙方並不會有太多言語上的交談,而根據對局者的下棋節奏快慢及下棋的力量,可以反映出雙方心態上的變化,利用著棋子進行棋局上的交流,故稱做「手談」。 中央棋院官網連結 : https://www.centralgo.com.tw/
Thumbnail
【一】座標與陣地 【二】棋駒的走法 【三】勝敗的細節 【四】最後的補充
圍棋,是一種古老棋類遊戲,兩位玩家輪流在棋盤上放置黑白兩色的圓形石子,目標是在棋盤上形成多個區域,以擴大自己的領地並同時圍堵對手的石子。儘管規則簡單,但卻擁有極其豐富的戰術和戰略,每一步都是挑戰與機遇的交錯。加入我們,一同探索、學習、成長,讓圍棋成為你生活中不可或缺的一部分!
在這個充滿挑戰和樂趣的課程中,我們將教導小朋友們如何通過下圍棋來提升他們的穩定性和數理邏輯!