Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Input Replacement
#1
I am writing a tic-tac-toe style game code, where you use 3 variables to make 3 in a row instead of just X's and O's. I originally wrote a tic-tac-toe game, and tried to modify it from there.

The only thing I am stuck on is replacing variables like the game allows. For example: When I input 1, it outputs "G". When I try to input 1 again to input the replacement variable, "Y" my code currently does not allow that.
Link image

I am pretty sure that my problem lies with the make_move function, but I do not know how to edit it to allow the overwrite of inputs. Any help is appreciated, Thank you!
def play_game():

    def print_board():
        print(board[1], board[2], board[3])
        print(board[4], board[5], board[6])
        print(board[7], board[8], board[9])

    board = [None] + list(range(1, 10))
    combinations = [
       (1, 5, 9),
       (3, 5, 7),
       (1, 4, 7),
       (2, 5, 8),
       (3, 6, 9),
       (1, 2, 3),
       (4, 5, 6),
       (7, 8, 9),
    ]

    def make_move():
        while True:
            try:
                a = int(input())
                if a in board:
                    return a
                else:
                    print("\nCannot Overwrite")
            except ValueError:
               print("\nIncorrect Input")

    def check_winner():
        for a, b, c in combinations:
            if board[a] == board[b] == board[c]:
                print("\nGame Over\n")
                return True

#update_board
    for player in "GYR" * 9:
        print_board()
        if check_winner():
            break
        board[make_move()] = player

while True:
    play_game()
Reply
#2
I'm not sure what your question is or what you are shooting for. The first time you type one, player is 'G'. The make_move function returns 1, since is on the board. So board[make_move()] = player replaces the 1 with a 'G'. The second time you type 1, there is no 1 on the board, since you just replaced it with a 'G'. So the make_move prints cannot overwrite. Then I guess you get an error? That would have been helpful to point out.

You see, functions always return something. If you don't specify something else for it to return, it will return None. So board[make_move()] = player becomes board[None] = player, and that's an error, because only integers can be used as list indices. What you want to do is check the result of make_move() before trying to assign with it. If it's None (some error occurred), you want to get another move for the same player. Typically this is done with a while loop:

while True:
   move = make_move()
   if move is not None:
      board[move] = player
      break
BTW, your structure is really screwy. Yeah, you can define your functions inside another function, but generally you define all the functions at the module level and have them call each other. I would do that, and pass the board as a parameter to print_board and check_winner.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
I'm trying to ask how I can rework the program so that whenever I type in an int value, it will be replaced with the next variable when it turns into a string, whether it is G/Y/R.
Reply
#4
This still may have bugs and other issues ... I cranked it out pretty quickly and didn't thoroughly test.
the main purpose is to show different ways of writing the code;

from itertools import chain


class TicTacToe:
    def __init__(self):
        self.board = self.new_board()
        self.winners = [
            [0, 1, 2], [3, 4, 5], [6, 7, 8],  # rows
            [0, 3, 6], [1, 4, 7], [2, 5, 8],  # columns
            [0, 4, 8], [2, 4, 6]  # diags
        ]

    def new_board(self):
        return [['_'] * 3 for i in range(3)]

    def display_board(self):
        print('\n    1   2   3')
        for n, row in enumerate(self.board):
            print('{} | {} | {} | {} |'.format(n + 1, row[0], row[1], row[2]))
        print()

    def place_item(self, row, column, value):
        if self.board[row][column] == '_':
            self.board[row][column] = value
        else:
            print('Already occupied')

    def clear_board(self):
        for x in range(3):
            for y in range(3):
                self.place_item(x, y, '_')

    def check_winner(self):
        flat_board = list(chain.from_iterable(self.board))
        for winner in self.winners:
            if flat_board[winner[0]] == flat_board[winner[1]] == flat_board[winner[2]]:
                if flat_board[winner[0]] != '_':
                    return flat_board[winner[0]]
        return None


def rungame() -> object:
    game = TicTacToe()
    game.display_board()
    turn = 'X'

    while True:
        # game.make_move()
        row = column = value = None
        while True:
            try:
                ttext = "{}'s Turn -- 'Q' to quit: ".format(turn)
                row, column = input(ttext).split()
                if row == 'Q':
                    break

                row = int(row) - 1
                column = int(column) - 1
                if (row < 0 or row > 2) or (column < 0 or column > 2):
                    raise ValueError from ValueError
                value = turn
                break
            except:
                print('Value error, enter row, column or Q to Quit) please')

        if row == 'Q':
            break
        game.place_item(row, column, value)
        game.display_board()
        winner = game.check_winner()
        if winner:
            print('The winner is {}'.format(winner))
            break
        if turn == 'X':
            turn = 'Y'
        else:
            turn = 'X'


if __name__ == '__main__':
    rungame()
Reply
#5
Is there a way for me to edit my existing code to be able to overwrite the string variable once it is inputted? Because the int is still there in the list after it is transitioned to a string variable, I just need to be able to continuously change that string variable in a position with each input of an int
Reply
#6
(Nov-01-2016, 06:33 PM)palmtrees Wrote: Is there a way for me to edit my existing code to be able to overwrite the string variable once it is inputted? Because the int is still there in the list after it is transitioned to a string variable, I just need to be able to continuously change that string variable in a position with each input of an int

Then you probably want to change this check:

if a in board:
That is what is preventing the second character being written in the same space. If you want to rewrite spaces, you should just check that a is in the range of allow indices for the board:

if 0 < a < len(board):
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#7
That worked perfectly, thank you so much! Sorry for being difficult, I wasn't sure how to exactly word my question.
Reply
#8
That's honestly the #1 problem beginners have. It isn't enough that you're learning something entirely new, but it's so different from everything you know that you don't even know how to phrase your questions to ask for help. I promise it gets better the more you learn :)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Multiple Replacement millpond 5 2,548 Sep-10-2019, 02:11 AM
Last Post: millpond

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020