Making a draft of tic-tac-toe - python

import numpy as np
player1 = True
def create_board():
board = np.zeros((3,3), dtype=int)
return board
def place(board , player1 , position ):
if player1 == True:
player1 = False
if board[position] == 0:
board = position
elif board[position] != 0:
print("False , place taken 1")
else:
if player1 == False:
if board[position] == 0:
board = position
elif board[position] != [0, 0]:
print("False , place taken 2 ")
return board
Function call:
place(board=create_board() , player1=1 , position=(0,0))
Here is my code, in this code there is a lot going on however there is one part i could not get it right . In the bold section , i am trying to replace
([0,0,0],
[0,0,0],
[0,0,0])
to
([1,0,0],
[0,0,0],
[0,0,0])
May i know , how can I do this please ... Thank you !

you're mistakenly changing the board variable to position inside the if statements
if board[position] == 0:
board = position
you should change the value inside board at index position
board[position] = 1 # for player 1
board[position] = 2 # for player 2
i've also cleaned the code a little bit
def place(board , player1 , position ):
x = 1 if player1 else 2
if board[position] != 0:
print(f'False , place taken {x}')
else:
board[position] = x
return board

You are assigning your board to your position information with board = position and I think you mean board[position] == 1
def place(board , player, position ):
if board[position] == 0: #if the position is unclaimed
board[position] = player #claim it for the player
else:
print(f"place was already taken by player {board[position]}")
return board
#call using the player number
place(board=create_board() , player=1 , position=(0,0))
This function would give you what you are looking for.

When you try to update your board in board = position you are actually updating the whole board with your pair of coordinates.
What you really want is to pinpoint the exact position in your two-dimensional array that you have to update to store an occupied cell. You could archieve that changing that line with
board[position] = 1 # occupied cell
However, as Hammad said in another answer, it would be convienient to change your
0 for unoccupied
1 for occupied
and having to rely on knowing whose turn is ongoing at the moment, to
0 for unoccupied
1 for occupied by player one
2 for occupied by player two
so you always know who occupied that cell.

Related

List value being overwritten even though I am checking for it

I'm new to python and writing my first project. I'm trying to implement a check that if a space is already occupied, not to move there. I can't seem to figure out why my move_player method overwrites the index value of the board even though I am explicitly checking it (If it is O's turn and X has already been placed in the index O is trying to move to, it just overwrites it). I have tried hard coding the check for 'X' and 'O' instead of player.player as well but can't seem to figure it out. Does it have to do something with how Python works or am I implementing it wrong?
class Player:
def __init__(self, player):
self.player = player
class Board:
def __init__(self):
self.board = [[' ' for i in range(3)] for j in range(3)]
def display_board(self):
print('---------')
for row in self.board:
print('| ', end='')
for col in row:
print(f'{col} ', end='')
print('|')
print('---------')
def move_player(self, player):
try:
p1 = Player('X')
p2 = Player('O')
coordinates = [int(i) for i in input("Enter coordinates for move: ").split()]
xCoordinate = coordinates[0]
yCoordinate = coordinates[1]
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
print("That space is occupied, please choose another one.")
self.move_player(player)
else:
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
except (ValueError, IndexError):
print("Please only enter numbers between 1 and 3.")
self.move_player(player)
def has_won(self, player):
if self.check_diagonal(player):
return True
elif self.check_across(player):
return True
elif self.check_down(player):
return True
return False
if __name__ == '__main__':
board = Board()
player1 = Player('X')
player2 = Player('O')
player = player1
while True:
board.display_board()
board.move_player(player)
if board.has_won(player):
board.display_board()
print(f'{player.player} wins!!!')
break
if player == player1:
player = player2
else:
player = player1
The code is very convoluted but from what I can see:
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
...
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
You are checking [x,y] but assigning to [x-1,y-1].

I'm stuck in the creating of a Board game in python

I have an excercise to do and I'm stuck. It's the board game Alak, not much known, that I have to code in python. I can link the execrcise with the rules so you can help me better. The code has the main part and the library with all the procedures and function.
from Library_alak import *
n = 0
while n < 1:
n = int(input('Saisir nombre de case strictement positif : '))
loop = True
player = 1
player2 = 2
removed = [-1]
board = newboard(n)
display(board, n)
while loop:
i = select(board, n, player, removed)
print(i)
board = put(board, player, i)
display(board, n)
capture(board, n, player, player2)
loop = True if again(board, n, player, removed) is True else False
if player == 1 and loop:
player, player2 = 2, 1
elif player == 2 and loop:
player, player2 = 1, 2
win(board, n)
print(win(board, n))
And here is the library:
def newboard(n):
board = ([0] * n)
return board
def display(board, n):
for i in range(n):
if board[i] == 1:
print('X', end=' ')
elif board[i] == 2:
print('O', end=' ')
else:
print(' . ', end=' ')
def capture(board, n, player, player2):
for place in range(n):
if place == player:
place_beginning = place
while board[place] != player:
place_end = place
if board[place + x] == player:
return board
else:
return board
def again(board, n, player, removed):
for p in board(0):
if p == 0:
if p not in removed:
return True
else:
return False
def possible(n, removed, player, i, board):
for p in range(n + 1):
if p == 1:
if board[p-1] == 0:
if p not in removed:
return True
else:
return False
def win(board, n):
piecesp1 = 0
piecesp2 = 0
for i in board(0):
if i == 1:
piecesp1 += 1
else:
piecesp2 += 1
if piecesp1 > piecesp2:
print('Victory : Player 1')
elif piecesp2 > piecesp1:
print('Victory : Player 2')
else:
return 'Equality'
def select(board, n, player, removed):
loop = True
while loop:
print('player', player)
i = int(input('Enter number of boxes : '))
loop = False if possible(n, removed, player, i, board)is True else True
return i
def put(board, player, i):
i -= 1
if board[i] == 0:
if player == 1:
board[i] = 1
return board
else:
board[i] = 2
return board
else:
put(board, player, i)
So my problems here are that I have few errors, the first one is that when I enter the number '1' when asked to enter a number of boxes ( which is the place to play on ) nothing happens. Then when entering any other number, either the error is : if board[place + x] == player:
NameError: name 'x' is not defined
or there seems to be a problem with the : if board[place + x] == player:
NameError: name 'x' is not defined
I would appreciate a lot if anyone could help me. I'm conscious that it might not be as detailed as it should be and that you maybe don't get it all but you can contact me for more.
Rules of the Alak game:
Black and white take turns placing stones on the line. Unlike Go, this placement is compulsory if a move is available; if no move is possible, the game is over.
No stone may be placed in a location occupied by another stone, or in a location where a stone of your own colour has just been removed. The latter condition keeps the game from entering a neverending loop of stone placement and capture, known in Go as ko.
If placing a stone causes one or two groups of enemy stones to no longer have any adjacent empty spaces--liberties, as in Go--then those stones are removed. As the above rule states, the opponent may not play in those locations on their following turn.
If placing a stone causes one or two groups of your own colour to no longer have any liberties, the stones are not suicided, but instead are safe and not removed from play.
You shouldn't use "player2" as a variable, there's an easier way, just use "player" which take the value 1 or 2 according to the player. You know, something like that : player = 1 if x%2==0 else 2
and x is just a increasing int from 0 until the end of the game.

Store User Values in Python Game Using Class Methods

Python beginner here--working on a Battleship project for a class. My program will loop through the first player to place their ships. The grid does successfully print the visual ships on the board, but once i get to player two, the ships are overlapping with player one. (also note there is some validation work that still needs to be done).
I think the issue is that maybe I'm storing both coordinates for each player in the same list. So my question is how do I store the values for each player so that I can get the board to print ships only applicable to each player?
Here are my classes:
BOARD_SIZE = 10
class Ship:
def __init__(self, ship_name, size, coords, player, direction):
self.ship_name = ship_name
self.size = size
self.player = player
self.coords = coords
self.direction = direction
class Board:
def __init__(self):
self.board = []
self.guesses = []
board = [['O']*BOARD_SIZE for _ in range(BOARD_SIZE)]
def add_ship(self, name, size, player, coords, direction):
for coord in coords:
# convert string like "a1" to x,y coordinates
y = ord(coord[0])-ord('a')
x = int(coord[1:])-1
# update the board at this position
self.board = board[x][y]
print(" " + " ".join([chr(c) for c in range(ord('A'), ord('A') + BOARD_SIZE)]))
row_num = 1
for row in board:
print(str(row_num).rjust(2) + " " + (" ".join(row)))
row_num += 1
self.board.append(Ship(coords,player,name,size,direction))
def print_board_heading(self):
print(" " + " ".join([chr(c) for c in range(ord('A'), ord('A') + BOARD_SIZE)]))
def print_board(self):
board = [['O']*BOARD_SIZE for _ in range(BOARD_SIZE)]
print_board_heading()
row_num = 1
for row in board:
print(str(row_num).rjust(2) + " " + (" ".join(row)))
row_num += 1
def print_updated_board(coords, direction, board, player):
for coord in coords:
# convert string like "a1" to x,y coordinates
y = ord(coord[0])-ord('a')
x = int(coord[1:])-1
# update the board at this position
board[x][y] = '|' if direction == 'v' else '-'
print(" " + " ".join([chr(c) for c in range(ord('A'), ord('A') + BOARD_SIZE)]))
row_num = 1
for row in board:
print(str(row_num).rjust(2) + " " + (" ".join(row)))
row_num += 1
class Player():
def __init__(self,name):
self.name = name
self.board = Board()
self.ships = []
self.guesses = []
And the battleship game file:
from ship import Ship, Player, Board
SHIP_INFO = [
("Aircraft Carrier", 5),
("Battleship", 4),
("Submarine", 3),
("Cruiser", 3),
("Patrol Boat", 2)
]
BOARD_SIZE = 10
VERTICAL_SHIP = '|'
HORIZONTAL_SHIP = '-'
EMPTY = 'O'
MISS = '.'
HIT = '*'
SUNK = '#'
board = [['O']*BOARD_SIZE for _ in range(BOARD_SIZE)]
def print_board_heading():
print(" " + " ".join([chr(c) for c in range(ord('A'), ord('A') + BOARD_SIZE)]))
def print_board():
board = [['O']*BOARD_SIZE for _ in range(BOARD_SIZE)]
print_board_heading()
row_num = 1
for row in board:
print(str(row_num).rjust(2) + " " + (" ".join(row)))
row_num += 1
def print_updated_board(coords, direction,board):
# create an empty board
# board = [['O']*BOARD_SIZE for _ in range(BOARD_SIZE)]
# at each coordinate, draw a ship
for coord in coords:
# convert string like "a1" to x,y coordinates
y = ord(coord[0])-ord('a')
x = int(coord[1:])-1
# update the board at this position
board[x][y] = '|' if direction == 'v' else '-'
print_board_heading()
row_num = 1
for row in board:
print(str(row_num).rjust(2) + " " + (" ".join(row)))
row_num += 1
def clear_screen():
print("\033c", end="")
def get_coordinates(ship):
while True:
print("\n")
coordinate = input("Where do you want the " + ship + "(example: A1)?: ")
coords_strip = coordinate.strip()
coords_lower = coords_strip.lower()
x = coords_lower[0]
y = coords_lower[1:]
if (len(x)+len(y)) in range(2,4):
if x not in 'abcdefghij' or y not in '1,2,3,4,5,6,7,8,9,10':
print("Oops! That was not a valid entry. Try again...")
continue
else:
return x, y
else:
if len(coords_lower) < 2 or len(coords_lower) > 3:
print("Oops! That's too not the right amount of characters. Please try again...")
continue
def get_direction():
while True:
dir = input("[H]orizontal or [V]ertical?: ")
dir_strip = dir.strip()
direction = dir_strip.lower()
if direction not in 'hv':
print("Oops! That was not a valid entry. Try again...")
continue
else:
return direction
def create_ship_coordinates(x, y, size, direction):
ship_col = ord(x)
ship_row = int(y)
if direction == 'v':
# ship runs vertically DOWN from coordinate
coords = [chr(ship_col) + str(r) for r in range(ship_row, ship_row + size)]
return coords
else:
# ship runs horizontally RIGHT from coordinate
coords = [chr(col) + str(ship_row) for col in range(ship_col, ship_col + size)]
return coords
def place_user_ships(player):
ships = []
print_board()
print("\n")
print("Let's go " + player + " !")
for ship, size in SHIP_INFO:
while True:
# ask for starting coordinate
x, y = get_coordinates(ship)
# ask for vertical or horizontal direction
direction = get_direction()
# create the coordinates for the ship placement
coords = create_ship_coordinates(x, y, size, direction)
# validate the
# new_ship = Board().add_ship(ship, size, coords, direction, player)
# update = Board.print_updated_board(coords,direction,board,player)
break
# create ship from data
# add the ship from above to a player list
# player = Player(board)
# place the ship on the game board
# print out the board to reflect the shp placement
clear_screen()
print("\n")
input("All ships placed for {}. Please hit ENTER to continue....".format(player))
player1 = input("What's Player 1's Name? ")
player2 = input("What's Player 2's Name? ")
# define player one's fleet
place_user_ships(player1)
place_user_ships(player2)
IIRC, in battleship there are really four boards. One is managed by each player with their shots at the enemy, and the other is the player's own ships and incoming shots from the enemy.
The "shot" process is one of notifying the enemy where the shot was taken, the enemy responding with "hit" or "miss", and recording the result on the local player's outgoing-shots board.
The "notification" process is one of receiving a location where an enemy shot was made, looking up the result on the local-ships board, returning "hit" or "miss", and updating the local ships board to indicate the enemy shot.
So you have a Player, with a pair of Boards. You might also have a Game class to marry the two players.
Inputting the ships is going to depend a lot on your actual user interface. Are you doing graphics with a mouse? Are you doing text with a mouse? Text with arrow keys via curses or some such? Simple coordinate inputs?
If you're doing coordinates, you probably want something simple, like x,y,{up,down,left,right} to eliminate having to position every block of the ship.
Again, there is a Board method here - placing a ship. The board can enforce whatever rules you have about placement (ex: can two ships be directly adjacent? Or must there be a one-space gap between?) and reject the inappropriate attempts.
If you put all the wisdom in your Board class, then the Player classes can be simple, with just links to the boards. And the game can manage the players in turn:
def play(self):
p1 = self.player[0]
p2 = self.player[1]
try:
while True:
self.attack(p1, p2)
self.attack(p2, p1)
except Victory v:
print("The winner is", v.player.name)
I notice you doing things like player1 = input("What is player 1's name?"). This is something that should be pushed into the player classes.
Try to design from the top down: game, player, board. And try following the rule, "Tell, don't ask." That is, if something needs to be done, you tell a class to do it, instead of asking the class for data and doing it yourself.
Instead of this:
move = player1.get_move()
if valid_move(move):
...
Do this:
player1.make_move()
And push the logic downwards. Eventually, you get to the place where the knowledge "should be". The player "should" make moves. The board "should" know what is a valid move or not. And every method "should" be given enough data to do its job. ;-)

minimax function not generating all game states

Can anyone tell me why my code prints 1 and not 8? It seems to not be going through very single state. Why is that?
using the minimax algorithm find the best possible move to make based on a game state, a possible tic tac toe board. Usually, it would branch off into a large tree of game states, each new branch called when the game doesn't end on an ending state, repeated, then finding the best possible move by recursively going down the tree finding the best moves for each player.
I was following the "tutorial" at http://giocc.com/concise-implementation-of-minimax-through-higher-order-functions.html.
My code:
#!/usr/bin/env python3
'''Minimax finds the best possible moves by applying a set of rules.
A win = 1, tie = 0, loss = -1 (for us). Assuming that each player chooses the best move
(we choose 1 if possible, opponent chooses -1). Starting at the top of a 'game tree',
generate the possible moves we can make. If It reaches a terminal state, stop. Otherwise keep searching in depth.
We find max.
'''
#[0,1,2,3,4,5,6,7,8]
class GameState: #a game state is a certain state of the board
#http://stackoverflow.com/questions/1537202/variables-inside-and-outside-of-a-class-init-function
x_went_first = True
def __init__(self,board):
self.board = board
self.winning_combos = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,8]]
def is_gameover(self):
if self.board.count('X') + self.board.count('O') == 9:
return True
for combo in self.winning_combos:
if (self.board[combo[0]] == 'X' and self.board[combo[1]] == 'X' and self.board[combo[2]] == 'X') or (self.board[combo[0]] == 'O' and self.board[combo[1]] == 'O' and self.board[combo[2]] == 'O'):
return True
return False
def get_possible_moves(self):
squares = []
for square in self.board:
if square != 'X' and square != 'O':
squares.append(int(square))
return squares
def get_next_state(self, move):
copy = self.board
num_of_x = copy.count('X')
num_of_o = copy.count('O')
#x starts, o's turn 1 > 0 o's turn
#o starts, x's turn 1 < 0 x's turn
#x starts, x's turn 1 > 1
#o starts, o's turn 1 < 1
if (self.x_went_first and num_of_x > num_of_o) or (self.x_went_first is not True and num_of_o == num_of_x):
copy[move] = 'O'
else:
copy[move] = 'X'
return GameState(copy)
def evals(game_state):
for combo in [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,8]]:
if game_state.board[0] == 'X' and game_state.board[1] == 'X' and game_state.board[2] == 'X':
return 1
elif game_state.board[0] == 'O' and game_state.board[1] == 'O' and game_state.board[2] == 'O':
return -1
else:
return 0
def min_play(game_state):
if game_state.is_gameover():
return evals(game_state)
moves = game_state.get_possible_moves()
best_move = moves[0]
best_score = 2 #not possible, best score is -1
for move in moves:
clone = game_state.get_next_state(move)
score = max_play(clone)
if score < best_score:
best_move = move
best_score = score
return best_score
def max_play(game_state):
if game_state.is_gameover():
return evals(game_state)
moves = game_state.get_possible_moves()
best_score = -2 #not possible, best score is 1
for move in moves:
clone = game_state.get_next_state(move)
score = min_play(clone)
if score > best_score:
best_move = move
best_score = score
return best_score
def minimax(game_state):
moves = game_state.get_possible_moves()
best_move = moves[0]
best_score = -2
for move in moves:
clone = game_state.get_next_state(move)
score = min_play(clone)
if score > best_score:
best_move = move
best_score = score
return best_move
game = GameState(['X',1,2,
3,'O',5,
6,7,8])
print(minimax(game))
My evals was always returning 0, and one of the winning combinations was messed up. New evals:
def evals:
for combo in [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]:
if game_state.board[0] == 'X' and game_state.board[1] == 'X' and game_state.board[2] == 'X':
return 1
elif game_state.board[0] == 'O' and game_state.board[1] == 'O' and game_state.board[2] == 'O':
return -1
return 0
I also modified it so the index isn't in every empty slot. View the full code at https://github.com/retep-mathwizard/pyai/blob/master/minimax_ttt

Poker game/ PYTHON : How do I have the big/small blinds rotate every turn

Poker game in python:
NEWB here. How do I have the big/small blinds rotate every turn.I call this function in my main. Any help is appreciated.
Code:
poker table function:
def post_blinds(self,smallblind,bigblind):
self.smallblind = smallblind
self.bigblind = bigblind
x=0
for player in self.players:
if player == self.players[x+1]:
player.stack = player.stack - smallblind
if player == self.players[x+2]:
player.stack = player.stack - bigblind
x += 1
print(x)
def main():
players = (Player("Player 1",200), Player("Player 2",200),Player("Player 3",200),Player("Player 4",200),Player("Player 5",200),Player("Player 6",200))
table = Table(players)
table.post_blinds(1,2) #Post Blinds
table.deal_cards() #Deal 2 cards to each player
You set dealer pos to 0 by x = 0
And I presume you set x = x + 1 for the next hand.
But x being created inside your function will be recreated at every call and will always value 0.
You should use a variable from self.
Like self.dealerPos
And self.dealerPos have to be initialized somewhere else like in a initGame function
If you don't want dealerPos to become invalid,
Instead of
self.dealerPos = self.dealerPos + 1
Use
self.dealerPos = (self.dealerPos + 1)%self.nbPlayer
Following your questions, you want a basic idea of how to manage the game.
So here it is.
def init_game(self):
self.dealer_Pos = 0
def update_dealer_button(self):
self.dealer_Pos = (self.dealer_Pos + 1)% len(self.players)
def post_blinds(self,smallblind,bigblind):
self.smallblind = smallblind
self.bigblind = bigblind
for player in self.players:
if player == self.players[(self.dealer_Pos + 1)% len(self.players)]:
player.stack = player.stack - smallblind
if player == self.players[(self.dealer_Pos + 2)% len(self.players)]:
player.stack = player.stack
def main():
players = (Player("Player 1",200), Player("Player 2",200),Player("Player 3",200),Player("Player 4",200),Player("Player 5",200),Player("Player 6",200))
table = Table(players) #Create table
table.init_game() #Init dealer button and other future values
gameOver = False
while gameOver == False:
table.post_blinds(1,2) #Post Blinds
table.deal_cards() #Deal 2 cards to each player
#all other game steps
#analysing if game is over. If it is, set gameOver = True
#if game is not over move the dealer button and play again
update_dealer_button()

Categories

Resources