我正在尝试为连接4编写一个程序,但是在通过指示时遇到了很多麻烦。评论中的一切," #everything可以在这里发挥作用"有效,但后来爆炸,我甚至不知道从哪里开始修复它。
#connect 4
import random
#define global variables
X = "X"
O = "O"
EMPTY = "_"
TIE = "TIE"
NUM_ROWS = 6
NUM_COLS = 8
def display_instruct():
"""Display game instructions."""
print(
"""
Welcome to the second greatest intellectual challenge of all time: Connect4.
This will be a showdown between your human brain and my silicon processor.
You will make your move known by entering a column number, 1 - 7. Your move
(if that column isn't already filled) will move to the lowest available position.
Prepare yourself, human. May the Schwartz be with you! \n
"""
)
def ask_yes_no(question):
"""Ask a yes or no question."""
response = None
while response not in ("y", "n"):
response = input(question).lower()
return response
def ask_number(question,low,high):
"""Ask for a number within range."""
#using range in Python sense-i.e., to ask for
#a number between 1 and 7, call ask_number with low=1, high=8
low=1
high=NUM_COLS
response = None
while response not in range (low,high):
response=int(input(question))
return response
def pieces():
"""Determine if player or computer goes first."""
go_first = ask_yes_no("Do you require the first move? (y/n): ")
if go_first == "y":
print("\nThen take the first move. You will need it.")
human = X
computer = O
else:
print("\nYour bravery will be your undoing... I will go first.")
computer = X
human = O
return computer, human
def new_board():
board = []
for x in range (NUM_COLS):
board.append([" "]*NUM_ROWS)
return board
def display_board(board):
"""Display game board on screen."""
for r in range(NUM_ROWS):
print_row(board,r)
print("\n")
def print_row(board, num):
"""Print specified row from current board"""
this_row = board[num]
print("\n\t| ", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num],"|")
print("\t", "|---|---|---|---|---|---|---|")
# everything works up to here!
def legal_moves(board):
"""Create list of column numbers where a player can drop piece"""
legal=True
while not legal:
col = input("What column would you like to move into (1-7)?")
for row in range (6,0,1):
if (1 <= row <= 6) and (1 <= col <= 7) and (board[row][col]==" "):
board[row][col] = turn
legal = True
else:
print("Sorry, that is not a legal move.")
def human_move(board,human):
"""Get human move"""
try:
legals = legal_moves(board)
move = None
while move not in legals:
move = ask_number("Which column will you move to? (1-7):", 1, NUM_COLS)
if move not in legals:
print("\nThat column is already full, nerdling. Choose another.\n")
print("Human moving to column", move)
return move #return the column number chosen by user
except NameError:
print ("Only numbers are allowed.")
except IndexError:
print ("You can only select colums from 1-7.")
def get_move_row(turn,move):
for m in (NUM_COLS):
place_piece(turn,move)
display_board()
def computer_move ():
move= random.choice(legal)
return move
def place_piece(turn,move):
if this_row[m[move]]==" ":
this_row.append[m[move]]=turn
def winner(board):
# Check rows for winner
for row in range(6):
for col in range(3):
if (board[row][col] == board[row][col + 1] == board[row][col + 2] == board[row][col + 3]) and (board[row][col] != " "):
return [row][col]
# Check columns for winner
for col in range(6):
for row in range(3):
if (board[row][col] == board[row + 1][col] == board[row + 2][col] ==board[row + 3][col]) and (board[row][col] != " "):
return [row][col]
# Check diagonal (top-left to bottom-right) for winner
for row in range(3):
for col in range (4):
if (board[row][col] == board[row + 1][col + 1] == board[row + 2][col + 2] == board[row + 3][col + 3]) and (board[row][col] != " "):
return true
# Check diagonal (bottom-left to top-right) for winner
for row in range (5,2,-1):
for col in range (3):
if (board[row][col] == board[row - 1][col + 1] == board[row - 2][col + 2] == board[row - 3][col + 3]) and (board[row][col] != " "):
return [row][col]
# No winner
return False
def main():
display_instruct()
computer,human = pieces()
turn = X
board = new_board()
while not winner(board) and (" " not in board):
display_board(board)
if turn == human:
human_move(board,human)
get_move_row()
place_piece()
else:
computer_move(board,computer)
place_piece()
display_board(board)
turn = next_turn()
the_winner = winner(board)
congrat_winner(the_winner, computer, human)
#start the program
main ()
input ("\nPress the enter key to quit.")
答案 0 :(得分:-1)
为了好玩,这是一个面向对象的重构。它有点长,但记录良好,应该很容易理解。
我开始使用您的代码并将其拆分为Board,Player和Game类,然后从Player中派生出计算机和人类。
我对它并不百分之百满意 - Board有一个.board,它是一个字符串列表列表,但是Game有一个Board作为Board;一点点明智的重命名是一个好主意 - 但是对于一个小时的工作来说,这是非常可靠的。
希望你能找到这种教育:
# Connect-4
from itertools import cycle, groupby
from random import choice
from textwrap import dedent
import sys
# version compatibility shims
if sys.hexversion < 0x3000000:
# Python 2.x
inp = raw_input
rng = xrange
else:
# Python 3.x
inp = input
rng = range
def get_yn(prompt, default=None, truthy={"y", "yes"}, falsy={"n", "no"}):
"""
Prompt for yes-or-no input
Return default if answer is blank and default is set
Return True if answer is in truthy
Return False if answer is in falsy
"""
while True:
yn = inp(prompt).strip().lower()
if not yn and default is not None:
return default
elif yn in truthy:
return True
elif yn in falsy:
return False
def get_int(prompt, lo=None, hi=None):
"""
Prompt for integer input
If lo is set, result must be >= lo
If hi is set, result must be <= hi
"""
while True:
try:
value = int(inp(prompt))
if (lo is None or lo <= value) and (hi is None or value <= hi):
return value
except ValueError:
pass
def four_in_a_row(tokens):
"""
If there are four identical tokens in a row, return True
"""
for val,iterable in groupby(tokens):
if sum(1 for i in iterable) >= 4:
return True
return False
class Board:
class BoardWon (BaseException): pass
class BoardTied(BaseException): pass
EMPTY = " . "
HOR = "---"
P1 = " X "
P2 = " O "
VER = "|"
def __init__(self, width=8, height=6):
self.width = width
self.height = height
self.board = [[Board.EMPTY] * width for h in rng(height)]
self.tokens = cycle([Board.P1, Board.P2])
self.rowfmt = Board.VER + Board.VER.join("{}" for col in rng(width)) + Board.VER
self.rule = Board.VER + Board.VER.join(Board.HOR for col in rng(width)) + Board.VER
def __str__(self):
lines = []
for row in self.board:
lines.append(self.rowfmt.format(*row))
lines.append(self.rule)
lines.append(self.rowfmt.format(*("{:^3d}".format(i) for i in rng(1, self.width+1))))
lines.append("")
return "\n".join(lines)
def is_board_full(self):
return not any(cell == Board.EMPTY for cell in self.board[0])
def is_win_through(self, row, col):
"""
Check for any winning sequences which pass through self.board[row][col]
(This is called every time a move is made;
thus any win must involve the last move,
and it is faster to check just a few cells
instead of the entire board each time)
"""
# check vertical
down = min(3, row)
up = min(3, self.height - row - 1)
tokens = [self.board[r][col] for r in rng(row - down, row + up + 1)]
if four_in_a_row(tokens):
return True
# check horizontal
left = min(3, col)
right = min(3, self.width - col - 1)
tokens = [self.board[row][c] for c in rng(col - left, col + right + 1)]
if four_in_a_row(tokens):
return True
# check upward diagonal
down = left = min(3, row, col)
up = right = min(3, self.height - row - 1, self.width - col - 1)
tokens = [self.board[r][c] for r,c in zip(rng(row - down, row + up + 1), rng(col - left, col + right + 1))]
if four_in_a_row(tokens):
return True
# check downward diagonal
down = right = min(3, row, self.width - col - 1)
up = left = min(3, self.height - row - 1, col)
tokens = [self.board[r][c] for r,c in zip(rng(row - down, row + up + 1), rng(col + right, col - left - 1, -1))]
if four_in_a_row(tokens):
return True
# none of the above
return False
def legal_moves(self):
"""
Return a list of columns which are not full
"""
return [col for col,val in enumerate(self.board[0], 1) if val == Board.EMPTY]
def do_move(self, column):
token = next(self.tokens)
col = column - 1
# column is full?
if self.board[0][col] != Board.EMPTY:
next(self.move) # reset player token
raise ValueError
# find lowest empty cell (guaranteed to find one)
for row in rng(self.height-1, -1, -1): # go from bottom to top
if self.board[row][col] == Board.EMPTY: # find first empty cell
# take cell
self.board[row][col] = token
# did that result in a win?
if self.is_win_through(row, col):
raise Board.BoardWon
# if not, did it result in a full board?
if self.is_board_full():
raise Board.BoardTied
# done
break
class Player:
def __init__(self, name):
self.name = name
def get_move(self, board):
"""
Given the current board state, return the row to which you want to add a token
"""
# you should derive from this class instead of using it directly
raise NotImplemented
class Computer(Player):
def get_move(self, board):
return choice(board.legal_moves())
class Human(Player):
def get_move(self, board):
legal_moves = board.legal_moves()
while True:
move = get_int("Which column? (1-{}) ".format(board.width), lo=1, hi=board.width)
if move in legal_moves:
return move
else:
print("Please pick a column that is not already full!")
class Game:
welcome = dedent("""
Welcome to the second greatest intellectual challenge of all time: Connect4.
This will be a showdown between your human brain and my silicon processor.
You will make your move known by entering a column number, 1 - 7. Your move
(if that column isn't already filled) will move to the lowest available position.
Prepare yourself, human. May the Schwartz be with you!
""")
def __init__(self):
print(Game.welcome)
# set up new board
self.board = Board()
# set up players
self.players = cycle([Human("Dave"), Computer("HAL")])
# who moves first?
if get_yn("Do you want the first move? (Y/n) ", True):
print("You will need it...\n")
# default order is correct
else:
print("Your rashness will be your downfall...\n")
next(self.players)
def play(self):
for player in self.players:
print(self.board)
while True:
col = player.get_move(self.board) # get desired column
try:
print("{} picked Column {}".format(player.name, col))
self.board.do_move(col) # make the move
break
except ValueError:
print("Bad column choice - you can't move there")
# try again
except Board.BoardWon:
print("{} won the game!".format(player.name))
return
except Board.BoardTied:
print("The game ended in a stalemate")
return
def main():
while True:
Game().play()
if not get_yn("Do you want to play again? (Y/n) ", True):
break
if __name__=="__main__":
main()