不确定 tic_tac_toe 换板
Unsure about tic_tac_toe changing board
我正在编写井字棋游戏 Python 3. 我已经将棋盘制作成二维数组,并具有将棋盘打印为网格、教程以及拿取和放置的功能输入。
它具有正确显示板、处理输入以及处理的基本能力,但我的算法有两个主要问题。他们是:
- 正在检测是否中奖。 (之后,它应该询问玩家是否想再玩一次,并据此采取行动。)
2.(可选,但值得赞赏)如何创建 CPU 与单个玩家一起玩。
我对使用 "for loop" 的回合开关和游戏获胜机制有一些粗略的概念,但如果不实施,游戏可能会在平局时中断。
如果有人对以下问题有任何解决方案或一般建议,
请 post 他们在这里。
from array import *
class board:
def __init__(self, row_1, row_2, row_3):
self.row_1 = row_1
self.row_2 = row_2
self.row_3 = row_3
# full_board is two-dimensional array
self.full_board = row_1, row_2, row_3
dash = "-"
main_board = board([dash, dash, dash], [dash, dash, dash], [dash, dash,
dash,])
def board_print(board):
for row in board:
for item in row:
print(item, end = " ")
print()
def take_input():
player = input("What space would you like to mark?(From 1 through 9):")
input_process(player)
# Algorithm for player input
# Make a dictionary of player inputs as keys, and 2d array coordinates as values
# if player's input equals a dictionary value:
# take the string and split it at ":"
# assign the two numbers of the 2d dictionary value as part_1 and part_2
# change the value of the matching coordinate to a "X" or "O", on the player(sorry, I can't make good CPU.)
# else:
# print a notification that their input was invalid and recall the function
def input_process(pl_choice):
possible_inputs = {"1" : "0:0", "2" : "0:1", "3" : "0:2", "4" : "1:0", "5" : "1:1", "6" : "1:2", "7": "2:0", "8" : "2:1", "9" : "2:2"}
if pl_choice in possible_inputs:
confirm = input("Are you sure you want to select %s? y/n: "%pl_choice)
if confirm == "y":
choice = possible_inputs[pl_choice].split(":")
answer_p1 = choice[0]
answer_p2 = choice[1]
choice_parts = [answer_p1, answer_p2]
elif confirm == "n":
print("Oh. Well you can try again.\n")
take_input()
elif pl_choice not in possible_inputs or not pl_choice.isdigit():
print("Your choice was invalid. Please try again.")
take_input()
def change_board(play_board, player_id, input_p1, input_p2):
if player_id == 1:
play_board[input_p1][input_p2] = "X"
elif player_id == 2:
play_board[input_p1][input_p2] = "O"
def tutorial():
print("Welcome to the Tic-Tac-Toe tutorial.\n")
print("This version of Tic-Tac-Toe is two-player only, although CPU may be added in the future. To play, \nYou input a number, 1-9. The numbers bind like so: ")
tutorial_board = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(board_print(tutorial_board))
print("Otherwise, this plays like on paper; get 3 in a row vertically, horizontally, or diagonally before your opponent, and you win.")
# Placeholder for main game
def main_game():
print("Hello, and welcome to Tic-Tac-Toe.\nWould you like to see the tutorial? y/n:")
tutorial_needed = input
if tutorial_needed == "y":
tutorial()
elif tutorial_needed == "n":
print("Okay. Let's start!")
game_end = False
actual_board = main_board.full_board
board_print(actual_board)
take_input()
1。检测是否中奖。
我们为玩家 X 定义 "win" 为以下情况之一为真:
- 一行包含 X
- 一列由X组成
- 从左上角到右下角的对角线由 X
- 左下角到右上角的对角线由 X
我们如何将其转换为 Python?
一行只是元组中的一个子列表(这是您使用的类型),所以我们可以只写 board[row]
来获取一行。要检查 any
(注意代码格式) 行是否由 "X" 组成,我们必须检查 all
其值是否等于 "X"。所以,我们可以写成 any(all(field == 'X' for field in row) for row in board)
.
列更复杂,因为我们必须使用索引。但是,基本上,它只是一回事,只是反过来:any
列和 all
字段 "X":
any(all(board[row][column] == 'X' for row in range(3)) for column in range(3))
对角线:我们只有一根线,所以我们只需要一个环。
对于 TL->BR,两个索引相等。因此,我们希望具有相同索引的字段中的 all
等于 "X"。 all(board[i][i] == 'X' for i in range(3))
对于 BL->TR,一个索引是 2-other_index
( 而不是 3,因为序列是零索引的)。我们希望具有两个索引的 all
字段等于 "X" all(board[i][2-i] for i in range(3))
问题:如果反转 i
和 2-i
会发生什么?不知道就打印出来吧
您可能想要编写一个 check_win(board, player)
函数来为通用 player
执行上述所有操作 - 这里 "X" 或 "O",但是,如果您决定稍后在更大的棋盘上加入三名球员...
2。创建 a CPU AI:
如果你真的想创建一个CPU,这是问错的地方。
如果您想创建一个(简单的)AI,请继续阅读。如果你想让它变得复杂,请问一个新问题。
想想它应该做什么:
- 它是否应该因为位置而更喜欢某些字段?
- 是不是应该尽量快点挡住对方?
- 它应该尝试创造多种获胜的可能性还是专注于一种?
- 应该...?
虽然在这种情况下,只模拟几个回合并选择最有可能获胜的回合可能更简单,问自己上面的问题并写一些也适用于(更多)更大的棋盘的东西,将会很有趣。
3。开关转动。
一种可能是:
你有一个球员序列(str、列表或元组),如下所示:"XO"
和一个总是增加的 round_counter
变量。然后使用 PLAYERS[round_counter % len(PLAYERS)]
获取当前播放器。使用取模运算符 %
始终获得有效索引。
选择:
cycle('ABCD') --> A B C D A B C D A B C D ...
这更容易 (for current_player in itertools.cycle("XO"):
),但是对于第一个替代方案,您可以使用必须调用 enumerate(itertools.cycle("XO"))
的号码并限制库的使用(如果此代码用于向某人展示,您可能想解释它是如何工作的)。
4。如何检测平局:
当 all
字段为 not
空时(在您的情况下为 !=
破折号),将进行平局;这相当于说 not
any
字段带有破折号。
看list comprehension把板子弄平:
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
--倒数第二个例子
我正在编写井字棋游戏 Python 3. 我已经将棋盘制作成二维数组,并具有将棋盘打印为网格、教程以及拿取和放置的功能输入。
它具有正确显示板、处理输入以及处理的基本能力,但我的算法有两个主要问题。他们是:
- 正在检测是否中奖。 (之后,它应该询问玩家是否想再玩一次,并据此采取行动。) 2.(可选,但值得赞赏)如何创建 CPU 与单个玩家一起玩。
我对使用 "for loop" 的回合开关和游戏获胜机制有一些粗略的概念,但如果不实施,游戏可能会在平局时中断。
如果有人对以下问题有任何解决方案或一般建议, 请 post 他们在这里。
from array import *
class board:
def __init__(self, row_1, row_2, row_3):
self.row_1 = row_1
self.row_2 = row_2
self.row_3 = row_3
# full_board is two-dimensional array
self.full_board = row_1, row_2, row_3
dash = "-"
main_board = board([dash, dash, dash], [dash, dash, dash], [dash, dash,
dash,])
def board_print(board):
for row in board:
for item in row:
print(item, end = " ")
print()
def take_input():
player = input("What space would you like to mark?(From 1 through 9):")
input_process(player)
# Algorithm for player input
# Make a dictionary of player inputs as keys, and 2d array coordinates as values
# if player's input equals a dictionary value:
# take the string and split it at ":"
# assign the two numbers of the 2d dictionary value as part_1 and part_2
# change the value of the matching coordinate to a "X" or "O", on the player(sorry, I can't make good CPU.)
# else:
# print a notification that their input was invalid and recall the function
def input_process(pl_choice):
possible_inputs = {"1" : "0:0", "2" : "0:1", "3" : "0:2", "4" : "1:0", "5" : "1:1", "6" : "1:2", "7": "2:0", "8" : "2:1", "9" : "2:2"}
if pl_choice in possible_inputs:
confirm = input("Are you sure you want to select %s? y/n: "%pl_choice)
if confirm == "y":
choice = possible_inputs[pl_choice].split(":")
answer_p1 = choice[0]
answer_p2 = choice[1]
choice_parts = [answer_p1, answer_p2]
elif confirm == "n":
print("Oh. Well you can try again.\n")
take_input()
elif pl_choice not in possible_inputs or not pl_choice.isdigit():
print("Your choice was invalid. Please try again.")
take_input()
def change_board(play_board, player_id, input_p1, input_p2):
if player_id == 1:
play_board[input_p1][input_p2] = "X"
elif player_id == 2:
play_board[input_p1][input_p2] = "O"
def tutorial():
print("Welcome to the Tic-Tac-Toe tutorial.\n")
print("This version of Tic-Tac-Toe is two-player only, although CPU may be added in the future. To play, \nYou input a number, 1-9. The numbers bind like so: ")
tutorial_board = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(board_print(tutorial_board))
print("Otherwise, this plays like on paper; get 3 in a row vertically, horizontally, or diagonally before your opponent, and you win.")
# Placeholder for main game
def main_game():
print("Hello, and welcome to Tic-Tac-Toe.\nWould you like to see the tutorial? y/n:")
tutorial_needed = input
if tutorial_needed == "y":
tutorial()
elif tutorial_needed == "n":
print("Okay. Let's start!")
game_end = False
actual_board = main_board.full_board
board_print(actual_board)
take_input()
1。检测是否中奖。
我们为玩家 X 定义 "win" 为以下情况之一为真:
- 一行包含 X
- 一列由X组成
- 从左上角到右下角的对角线由 X
- 左下角到右上角的对角线由 X
我们如何将其转换为 Python?
一行只是元组中的一个子列表(这是您使用的类型),所以我们可以只写 board[row]
来获取一行。要检查 any
(注意代码格式) 行是否由 "X" 组成,我们必须检查 all
其值是否等于 "X"。所以,我们可以写成 any(all(field == 'X' for field in row) for row in board)
.
列更复杂,因为我们必须使用索引。但是,基本上,它只是一回事,只是反过来:any
列和 all
字段 "X":
any(all(board[row][column] == 'X' for row in range(3)) for column in range(3))
对角线:我们只有一根线,所以我们只需要一个环。
对于 TL->BR,两个索引相等。因此,我们希望具有相同索引的字段中的 all
等于 "X"。 all(board[i][i] == 'X' for i in range(3))
对于 BL->TR,一个索引是 2-other_index
( 而不是 3,因为序列是零索引的)。我们希望具有两个索引的 all
字段等于 "X" all(board[i][2-i] for i in range(3))
问题:如果反转 i
和 2-i
会发生什么?不知道就打印出来吧
您可能想要编写一个 check_win(board, player)
函数来为通用 player
执行上述所有操作 - 这里 "X" 或 "O",但是,如果您决定稍后在更大的棋盘上加入三名球员...
2。创建 a CPU AI:
如果你真的想创建一个CPU,这是问错的地方。 如果您想创建一个(简单的)AI,请继续阅读。如果你想让它变得复杂,请问一个新问题。
想想它应该做什么:
- 它是否应该因为位置而更喜欢某些字段?
- 是不是应该尽量快点挡住对方?
- 它应该尝试创造多种获胜的可能性还是专注于一种?
- 应该...?
虽然在这种情况下,只模拟几个回合并选择最有可能获胜的回合可能更简单,问自己上面的问题并写一些也适用于(更多)更大的棋盘的东西,将会很有趣。
3。开关转动。
一种可能是:
你有一个球员序列(str、列表或元组),如下所示:"XO"
和一个总是增加的 round_counter
变量。然后使用 PLAYERS[round_counter % len(PLAYERS)]
获取当前播放器。使用取模运算符 %
始终获得有效索引。
选择:
cycle('ABCD') --> A B C D A B C D A B C D ...
这更容易 (for current_player in itertools.cycle("XO"):
),但是对于第一个替代方案,您可以使用必须调用 enumerate(itertools.cycle("XO"))
的号码并限制库的使用(如果此代码用于向某人展示,您可能想解释它是如何工作的)。
4。如何检测平局:
当 all
字段为 not
空时(在您的情况下为 !=
破折号),将进行平局;这相当于说 not
any
字段带有破折号。
看list comprehension把板子弄平:
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
--倒数第二个例子