|
| 1 | +""" |
| 2 | +Online Shared Gomoku Game |
| 3 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 4 | +All online players are divided into two roles (black and white) and play same Gomoku game together. |
| 5 | +
|
| 6 | +:demo_host:`Demo </gomoku_game>`, `Source code <https://github.com/wang0618/PyWebIO/blob/dev/demos/gomoku_game.py>`_ |
| 7 | +""" |
| 8 | +import pywebio, time |
| 9 | +from pywebio.output import * |
| 10 | +from pywebio.session import * |
| 11 | + |
| 12 | +chessboard_size = 15 |
| 13 | +# -1 -> none, 0 -> black, 1 -> white |
| 14 | +chessboard = [ |
| 15 | + [-1] * chessboard_size |
| 16 | + for _ in range(chessboard_size) |
| 17 | +] |
| 18 | + |
| 19 | +def winner(): # return winner piece, return None if no winner |
| 20 | + for x in range(2, chessboard_size - 2): |
| 21 | + for y in range(2, chessboard_size - 2): |
| 22 | + # check if (x,y) is the win center |
| 23 | + if chessboard[x][y] != -1 and any([ |
| 24 | + all(chessboard[x][y] == chessboard[m][n] for m, n in [(x - 2, y), (x - 1, y), (x + 1, y), (x + 2, y)]), |
| 25 | + all(chessboard[x][y] == chessboard[m][n] for m, n in [(x, y - 2), (x, y - 1), (x, y + 1), (x, y + 2)]), |
| 26 | + all(chessboard[x][y] == chessboard[m][n] for m, n in [(x - 2, y - 2), (x - 1, y - 1), (x + 1, y + 1), (x + 2, y + 2)]), |
| 27 | + all(chessboard[x][y] == chessboard[m][n] for m, n in [(x - 2, y + 2), (x - 1, y + 1), (x + 1, y - 1), (x + 2, y - 2)]), |
| 28 | + ]): |
| 29 | + return ['⚫', '⚪'][chessboard[x][y]] |
| 30 | + |
| 31 | +session_id = 0 # auto incremented id for each session |
| 32 | +current_turn = 0 # 0 for black, 1 for white |
| 33 | +player_count = [0, 0] # count of player for two roles |
| 34 | +def main(): |
| 35 | + """Online Shared Gomoku Game |
| 36 | +
|
| 37 | + All online players are divided into two roles (black and white) and share this game.""" |
| 38 | + global session_id, current_turn, chessboard |
| 39 | + if winner(): # The current game is over, reset game |
| 40 | + chessboard = [[-1] * chessboard_size for _ in range(chessboard_size)] |
| 41 | + current_turn = 0 |
| 42 | + |
| 43 | + my_turn = session_id % 2 |
| 44 | + my_chess = ['⚫', '⚪'][my_turn] |
| 45 | + session_id += 1 |
| 46 | + player_count[my_turn] += 1 |
| 47 | + |
| 48 | + @defer_call |
| 49 | + def player_exit(): |
| 50 | + player_count[my_turn] -= 1 |
| 51 | + |
| 52 | + set_env(output_animation=False) |
| 53 | + put_html("""<style> table th, table td { padding: 0px !important;} button {padding: .75rem!important; margin:0!important} </style>""") # Custom styles to make the board more beautiful |
| 54 | + |
| 55 | + put_markdown(f"""# Online Shared Gomoku Game |
| 56 | + All online players are divided into two roles (black and white) and share this game. You can open this page in multiple tabs of your browser to simulate multiple users. |
| 57 | + This application uses less than 100 lines of code, the source code is [here](https://github.com/wang0618/PyWebIO/blob/dev/demos/gomoku_game.py) |
| 58 | + Currently online player: {player_count[0]} for ⚫, {player_count[1]} for ⚪. |
| 59 | + Your role is {my_chess}. |
| 60 | + """, lstrip=True) |
| 61 | + |
| 62 | + def set_chess(pos): |
| 63 | + global current_turn |
| 64 | + if current_turn != my_turn: |
| 65 | + toast("It's not your turn!!", color='error') |
| 66 | + return |
| 67 | + x, y = pos |
| 68 | + chessboard[x][y] = my_turn |
| 69 | + current_turn = (current_turn + 1) % 2 |
| 70 | + |
| 71 | + @use_scope('chessboard', clear=True) |
| 72 | + def show_chessboard(): |
| 73 | + table = [ |
| 74 | + [ |
| 75 | + put_buttons([dict(label=' ', value=(x, y), color='light')], onclick=set_chess) if cell == -1 else [' ⚫', ' ⚪'][cell] |
| 76 | + for y, cell in enumerate(row) |
| 77 | + ] |
| 78 | + for x, row in enumerate(chessboard) |
| 79 | + ] |
| 80 | + put_table(table) |
| 81 | + |
| 82 | + show_chessboard() |
| 83 | + while not winner(): |
| 84 | + with use_scope('msg', clear=True): |
| 85 | + current_turn_copy = current_turn |
| 86 | + if current_turn_copy == my_turn: |
| 87 | + put_text("It's your turn!") |
| 88 | + else: |
| 89 | + put_row([put_text("Your opponent's turn, waiting... "), put_loading().style('width:1.5em; height:1.5em')], size='auto 1fr') |
| 90 | + while current_turn == current_turn_copy: # wait for next move |
| 91 | + time.sleep(0.2) |
| 92 | + show_chessboard() |
| 93 | + with use_scope('msg', clear=True): |
| 94 | + put_text('Game over. The winner is %s!\nRefresh page to start a new round.' % winner()) |
| 95 | + |
| 96 | + |
| 97 | +if __name__ == '__main__': |
| 98 | + pywebio.start_server(main, debug=True, port=8080, cdn=False) |
0 commit comments