Coding
Coding

Reputation: 59

Making a game in python called Othello its a real game. Cannot change specific values in a array

This is a 8 by 8 array the problem is when I set the variable player_2_move to the row and column which is input we get from the user the value of that variable stays at 0 when its meant to go to the two inputs we get. And from there I don't know how to change the value which Is Player 2 move this only happens when a function which checks for a winning move is checked. The two inputs work when I call the drop piece function which is most confusing. And also I'm still drafting with arrays which is why the numbers are 1 and 2. The game I'm making is called Othello.

import pygame, sys
import math

pygame.init()
ROW_COUNT = 8
COLUMN_COUNT = 8
PLAYER_COUNT = 2

RED = (255, 0, 0)
BEIGE = (255, 200, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

SQUARESIZE = 100

width = COLUMN_COUNT * SQUARESIZE
height = ROW_COUNT * SQUARESIZE

size = (width, height)

screen = pygame.display.set_mode(size)
screen.fill(RED)

# Vertical
one_x_1 = 100
one_y_1 = 0

one_end_x = 100
one_end_y = 800

# Horizontal
two_x_1 = 0
two_y_1 = 100

two_end_x = 800
two_end_y = 100

RADIUS = int(SQUARESIZE/2 - 5)


def draw_board(board):
    global one_x_1, one_y_1, one_end_x, one_end_y, two_x_1, two_y_1, two_end_x, two_end_y
    for c in range(COLUMN_COUNT):
        for r in range(ROW_COUNT):
            pygame.draw.line(screen, BLACK, (one_x_1, one_y_1), (one_end_x, one_end_y), 3)
            one_x_1 += 100
            one_end_x += 100
        pygame.draw.line(screen, BLACK, (two_x_1, two_y_1), (two_end_x, two_end_y), 3)
        two_y_1 += 100
        two_end_y += 100
    for c in range(COLUMN_COUNT):
        for r in range(ROW_COUNT):
            if board[r][c] == 1:
                pygame.draw.circle(screen, WHITE, (int(c*SQUARESIZE+SQUARESIZE/2), height - int(r*SQUARESIZE + SQUARESIZE/2)), RADIUS)
            elif board[r][c] == 2:
                pygame.draw.circle(screen, BLACK, (int(c*SQUARESIZE+SQUARESIZE/2), height - int(r*SQUARESIZE + SQUARESIZE/2)), RADIUS)
    pygame.display.update()


class Player(object):
    def __init__(self, number):
        self.remaining_pieces = 32
        self.number = number


board = np.zeros((ROW_COUNT, COLUMN_COUNT), dtype=np.uint8)
board[3][3] = 1
board[4][4] = 1
board[3][4] = 2
board[4][3] = 2

print(board)

draw_board(board)
pygame.display.update()

players = [Player(i) for i in range(1, PLAYER_COUNT + 1)]
print(len(players))

game_over = False

while not game_over:
    # Event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        for p in players:
            if event.type == pygame.MOUSEBUTTONDOWN:
                posx = event.pos[0]
                posy = event.pos[1]
                column = int(math.floor(posx/SQUARESIZE))
                row = int(math.floor(posy/SQUARESIZE))

                if board[row][column] == 0:
                    board[row][column] = p.number
                    p.remaining_pieces = p.remaining_pieces - 1

                    # The eight directions in which we will go
                    directions = [(-1, -1), (-1, 0), (-1, 1), (1, 1), (1, 0), (1, -1), (0, 1), (0, -1)]

                    for d in directions:
                        x = row
                        y = column
                        while True:
                            x = x + d[0]  # Assign x to the first value in the tuple
                            y = y + d[1]  # Assign y to the second value in the tuple

                            # check if we are still on the board
                            if (x in range(8)) and (y in range(8)):

                                print(f'checking y = {x + 1}, x = {y + 1}')
                                # if the file is empty there are no pieces to capture
                                if board[x][y] == 0:
                                        break
                                """
                                If we find a number around our move we run the same procedure for it and change it 
                                if we have to
                                """
                                if p.number == board[x][y]:  # Here p.number is the players move we find it on the board
                                    print(f'found {p.number}: y = {x + 1}, x = {y + 1}')
                                    i = row
                                    j = column
                                    while i != x or j != y:
                                        i = i + d[0]
                                        j = j + d[1]
                                        print(f'changed : y = {i + 1}, x = {j + 1} to {p.number}')
                                        board[i][j] = p.number
                            else:
                                # We are outside the board
                                break
                draw_board(board)
                print(board)```

Upvotes: 1

Views: 1303

Answers (1)

Abrogans
Abrogans

Reputation: 189

I will go step by step through your program and improve it. First of all creating arrays like this:

player1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
player2 = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

Is always a bad practice. Since you already use numpy in your project it's easy to create them like this:

player1 = np.ones(32, dtype=np.uint8)
player2 = np.full(32, 2, dtype=np.uint8)

However you don't really need those arrays anyway. You can just have an integer which keeps track of the remaining pieces. reamining_pieces = 32 To make the whole think easier I created a Player class which contains a Player number and the remaining Pieces.

class Player(object):
    def __init__(self, number):
        self.remaining_pieces = 32
        self.number = number

Now after this you have a lot of functions which aren't really necessary. They are so simple that there is no advantage of writing a function for them. So for example instead of writing

def create_board():
    board = np.zeros((ROW_COUNT, COLUMN_COUNT))
    return board
board = create_board()

It's a lot simpler and easier to read if you just write

board = np.zeros((ROW_COUNT, COLUMN_COUNT))

Same goes for def drop_piece(board, row, col, piece) and def is_valid_location(board, row, col) which both just add unnecessary complexity to it.

Step by step explanation

First, we start with a tuple of all directions:

directions = [(-1, -1), (-1, 0), (-1, 1), (1, 1), (1, 0), (1, -1), (0, 1), (0, -1)]

All eight directions two dimensions

And we now want to go in all directions and every time we start at row, column which is where the newly placed piece is located.

for d in directions:
    x = row
    y = column

And since we don't know how far we have to go we use a while loop and take the first step in the direction. Because We don't want to go outside of the board we immediately check if we are still on the board. If we are, we can continue.

while True:
    x = x + d[0]
    y = y + d[1]

    # check if we are still on the board
    if (x in range(8)) and (y in range(8)):

For the following steps let's use this as an example:

[[0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 1 2 0 0 0]
 [0 0 * 2 1 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]]

The star is where has just been placed a one. If we go one step to the left, we will encounter a 0 and know that we don't have to go any further. That's what

if board[x][y] == 0:
    break

Does.
If we now go to the right. We will first encounter a two and it just get's ignored and we go one step further to the right. Here we finally find a one. So we know that between row, column and x, y every number can be converted to a one. To do that we start at row, column and move once again until we reach x, y. On the way we convert every number to a one:

if p.number == board[x][y]:
    print(f'found {p.number}: x = {x + 1}, y = {y + 1}')
    i = row
    j = column
    while i != x or j != y:
        i = i + d[0]
        j = j + d[1]
        print(f'changed : x = {i + 1}, y = {j + 1} to {p.number}')
        board[i][j] = p.number

Whole Code

import pygame, sys
import math
import numpy as np

pygame.init()
ROW_COUNT = 8
COLUMN_COUNT = 8
PLAYER_COUNT = 2

RED = (255, 0, 0)
BEIGE = (255, 200, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

SQUARESIZE = 100

width = COLUMN_COUNT * SQUARESIZE
height = ROW_COUNT * SQUARESIZE

size = (width, height)

screen = pygame.display.set_mode(size)
screen.fill(RED)

# Vertical
one_x_1 = 100
one_y_1 = 0

one_end_x = 100
one_end_y = 800

# Horizontal
two_x_1 = 0
two_y_1 = 100

two_end_x = 800
two_end_y = 100

RADIUS = int(SQUARESIZE / 2 - 5)


def draw_board(board):
    global one_x_1, one_y_1, one_end_x, one_end_y, two_x_1, two_y_1, two_end_x, two_end_y
    for c in range(COLUMN_COUNT):
        for r in range(ROW_COUNT):
            pygame.draw.line(screen, BLACK, (one_x_1, one_y_1), (one_end_x, one_end_y), 3)
            one_x_1 += 100
            one_end_x += 100
        pygame.draw.line(screen, BLACK, (two_x_1, two_y_1), (two_end_x, two_end_y), 3)
        two_y_1 += 100
        two_end_y += 100
    for c in range(COLUMN_COUNT):
        for r in range(ROW_COUNT):
            if board[r][c] == 1:
                pygame.draw.circle(screen, WHITE, (
                int(c * SQUARESIZE + SQUARESIZE / 2), height - int(r * SQUARESIZE + SQUARESIZE / 2)), RADIUS)
            elif board[r][c] == 2:
                pygame.draw.circle(screen, BLACK, (
                int(c * SQUARESIZE + SQUARESIZE / 2), height - int(r * SQUARESIZE + SQUARESIZE / 2)), RADIUS)
    pygame.display.update()


class Player(object):
    def __init__(self, number):
        self.remaining_pieces = 32
        self.number = number


board = np.zeros((ROW_COUNT, COLUMN_COUNT), dtype=np.uint8)
board[3][3] = 1
board[4][4] = 1
board[3][4] = 2
board[4][3] = 2

print(board)

draw_board(board)
pygame.display.update()

players = [Player(i) for i in range(1, PLAYER_COUNT + 1)]
print(len(players))


def next_player():
    while True:
        for player in players:
            yield player


player_generator = next_player()

game_over = False

while not game_over:
    # Event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            posx = event.pos[0]
            posy = event.pos[1]
            column = int(math.floor(posx / SQUARESIZE))
            row = int(math.floor(posy / SQUARESIZE))

            p = player_generator.__next__()

            if board[row][column] == 0:
                board[row][column] = p.number
                p.remaining_pieces = p.remaining_pieces - 1

                # The eight directions in which we will go
                directions = [(-1, -1), (-1, 0), (-1, 1), (1, 1), (1, 0), (1, -1), (0, 1), (0, -1)]

                for d in directions:
                    x = row
                    y = column
                    while True:
                        x = x + d[0]  # Assign x to the first value in the tuple
                        y = y + d[1]  # Assign y to the second value in the tuple

                        # check if we are still on the board
                        if (x in range(8)) and (y in range(8)):

                            print(f'checking y = {x + 1}, x = {y + 1}')
                            # if the file is empty there are no pieces to capture
                            if board[x][y] == 0:
                                break
                            """
                            If we find a number around our move we run the same procedure for it and change it 
                            if we have to
                            """
                            if p.number == board[x][y]:  # Here p.number is the players move we find it on the board
                                print(f'found {p.number}: y = {x + 1}, x = {y + 1}')
                                i = row
                                j = column
                                while i != x or j != y:
                                    i = i + d[0]
                                    j = j + d[1]
                                    print(f'changed : y = {i + 1}, x = {j + 1} to {p.number}')
                                    board[i][j] = p.number
                        else:
                            # We are outside the board
                            break
            draw_board(board)
            print(board)

Upvotes: 2

Related Questions