# connect 4_2
---
## 上次程式碼
```python=
import numpy as np
import sys
import math
ROW=6
COL=7
def create_board(): #創建棋盤
board = np.zeros((ROW, COL))
return board
def drop_piece(board, row, col, piece):#把玩家指定的空格填起來
board[row][col] = piece
def is_valid_location(board, col):#確認目前還是空的位子
return board[ROW-1][col] == 0
def get_next_open_row(board, col):
for r in range(ROW):
if board[r][col] == 0:
return r
def print_board(board):#用來改變陣列方向
print(np.flip(board, axis=0))#flip就是翻轉陣列
def winning_move(board, piece):#判斷是否有人達成獲勝條件
#檢查所有橫線
for c in range(COL-3):
for r in range(ROW):
if board[r][c] == piece and board[r][c+1] == piece and board[r][c+2] == piece and board[r][c+3] == piece:
return True
#檢查所有直線
for c in range(COL):
for r in range(ROW-3):
if board[r][c] == piece and board[r+1][c] == piece and board[r+2][c] == piece and board[r+3][c] == piece:
return True
#檢查所有斜線
#斜率為正
for c in range(COL-3):
for r in range(ROW-3):
if board[r][c] == piece and board[r+1][c+1] == piece and board[r+2][c+2] == piece and board[r+3][c+3] == piece:
return True
board = create_board()
print_board(board)
turn = 0#用來判斷現在是輪到玩家1還是2
game_over = False
while not game_over:#若有玩家贏了用來跳出遊戲
#問玩家1
if turn == 0:
col = int(input("玩家1請選一個數字(0 ~ 6)"))
if is_valid_location(board, col):
row = get_next_open_row(board, col)
drop_piece(board, row, col, 1)
if winning_move(board,1):
print("恭喜玩家1獲勝!!!")
game_over=True
break
#問玩家2
else:
col = int(input("玩家2請選一個數字(0 ~ 6)"))
if is_valid_location(board, col):
row = get_next_open_row(board, col)
drop_piece(board, row, col, 2)
if winning_move(board,2):
print("恭喜玩家2獲勝!!!")
game_over=True
break
print_board(board)#程式有沒有寫錯
turn+=1
turn%=2
```
---
## 斜率為負
- 相反的若要判斷斜率為負,則要尋找$(i,j)、(i-1,j+1)、(i-2,j+2)、(i-3,j+3)$這四個點是不是都一樣
```python=
for c in range(COL-3):
for r in range(3, ROW):
if board[r][c] == piece and board[r-1][c+1] == piece and board[r-2][c+2] == piece and board[r-3][c+3] == piece:
return True
```
---
## 製作成pygame
---
## 引入函式庫
```python
import pygame
import numpy as np
import sys
import math
```
- 在終端機中輸入 pip install pygame
---
## 設定顏色
```python
BLUE = (0, 0, 255)#RGB值
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
```
---
## 設定視窗大小
```python
SQUARESIZE = 100#遊戲介面每格的大小
width = COL *SQUARESIZE#遊戲介面的寬
height = (ROW+1) * SQUARESIZE#遊戲介面的長
size = (width, height)
```
---
## 設定棋子大小
```python
RADIUS = int(SQUARESIZE/2 - 5)#圓的半徑
```
---
## 設定視窗大小
```python
screen = pygame.display.set_mode(size)
```
---
## 設定棋盤和棋子
---
- 要在遊戲視窗中繪製圖形需要用到pygame裡面的draw函式
```python
pygame.draw.形狀(位置, 顏色, (x座標, y座標, 大小))
```
```python
def draw_board(board):
for c in range(COL):
for r in range(ROW):
pygame.draw.rect(screen, BLUE, (c*SQUARESIZE), (r*SQUARESIZE+SQUARESIZE), SQUARESIZE, SQUARESIZE)#藍色棋盤
pygame.draw.circle(screen, BLACK, (int(c*SQUARESIZE+SQUARESIZE/2), int(r*SQUARESIZE+SQUARESIZE+SQUARESIZE/2)), RADIUS)#黑色空格
```
```python
for c in range(COL):
for r in range(ROW):
if board[r][c] == 1:
pygame.draw.circle(screen, RED, (int(c*SQUARESIZE+SQUARESIZE/2), height-int(r*SQUARESIZE+SQUARESIZE/2)), RADIUS)#玩家1球的顏色
elif board[r][c] == 2:
pygame.draw.circle(screen, YELLOW, (int(c*SQUARESIZE+SQUARESIZE/2), height-int(r*SQUARESIZE+SQUARESIZE/2)), RADIUS)#玩家2球的顏色
pygame.display.update()
```
---
## 初始化pygame
```python
pygame.init()
```
---
## 顯示視窗
```python
draw_board(board)
pygame.display.update()
```
---
## 設定字體和大小
```python
myfont = pygame.font.SysFont("monospace", 75)
```
---
## 主要循環
---
## 製作棋盤和棋子
---
### 棋盤
```python
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEMOTION:
pygame.draw.rect(screen, BLACK, (0, 0, width, SQUARESIZE))
posx = event.pos[0]
pygame.display.update()
```
---
### 棋子
```python
if turn == 0:
pygame.draw.circle(screen, RED, (posx, int(SQUARESIZE/2)), RADIUS)#玩家1的棋子
else:
pygame.draw.circle(screen, YELLOW, (posx, int(SQUARESIZE/2)), RADIUS)#玩家2的棋子
```
---
### 設定滑鼠按下時放置棋子
```python
if event.type == pygame.MOUSEBUTTONDOWN:
```
---
### 玩家選擇位置
#### 原本
```python
col = int(input("玩家1請選一個數字(0 ~ 6)"))
```
#### 修改後
```python
posx = event.pos[0]
col = int(math.floor(posx/SQUARESIZE))
```
---
### 獲勝字樣
#### 原本
```python
print("恭喜玩家1獲勝!!!")
```
#### 修改後
```python
label = myfont.render("Player 1 wins!!!", 1, RED)
screen.blit(label, (40, 10))
```
---
### 更新棋盤
- 每次放完棋子後都要更新一次棋盤和棋子
```python
print_board(board)
draw_board(board)
```
---
### 結束遊戲
```python
if game_over:
pygame.time.wait(3000)
```
---
## 完整程式碼
```python=
import numpy as np
import pygame
import sys
import math
BLUE = (0, 0, 255)#RGB值
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
ROW = 6#行數
COL = 7#列數
def create_board(): #創建棋盤
board = np.zeros((ROW, COL))
return board
def drop_piece(board, row, col, piece):#把玩家指定的空格填起來
board[row][col] = piece
def is_valid_location(board, col):#確認目前還是空的位子
return board[ROW-1][col] == 0
def get_next_open_row(board, col):
for r in range(ROW):
if board[r][col] == 0:
return r
def print_board(board):#用來改變陣列方向
print(np.flip(board, axis=0))#flip就是翻轉陣列
def winning_move(board, piece):#判斷是否有人達成獲勝條件
#檢查所有橫線
for c in range(COL-3):
for r in range(ROW):
if board[r][c] == piece and board[r][c+1] == piece and board[r][c+2] == piece and board[r][c+3] == piece:
return True
#檢查所有直線
for c in range(COL):
for r in range(ROW-3):
if board[r][c] == piece and board[r+1][c] == piece and board[r+2][c] == piece and board[r+3][c] == piece:
return True
#檢查所有斜線
#斜率為正
for c in range(COL-3):
for r in range(ROW-3):
if board[r][c] == piece and board[r+1][c+1] == piece and board[r+2][c+2] == piece and board[r+3][c+3] == piece:
return True
#斜率為負
for c in range(COL-3):
for r in range(3, ROW):
if board[r][c] == piece and board[r-1][c+1] == piece and board[r-2][c+2] == piece and board[r-3][c+3] == piece:
return True
def draw_board(board):
for c in range(COL):
for r in range(ROW):
pygame.draw.rect(screen, BLUE, (c*SQUARESIZE, r*SQUARESIZE+SQUARESIZE, SQUARESIZE, SQUARESIZE))#藍色棋盤
pygame.draw.circle(screen, BLACK, (int(c*SQUARESIZE+SQUARESIZE/2), int(r*SQUARESIZE+SQUARESIZE+SQUARESIZE/2)), RADIUS)#黑色空格
for c in range(COL):
for r in range(ROW):
if board[r][c] == 1:
pygame.draw.circle(screen, RED, (int(c*SQUARESIZE+SQUARESIZE/2), height-int(r*SQUARESIZE+SQUARESIZE/2)), RADIUS)#玩家1球的顏色
elif board[r][c] == 2:
pygame.draw.circle(screen, YELLOW, (int(c*SQUARESIZE+SQUARESIZE/2), height-int(r*SQUARESIZE+SQUARESIZE/2)), RADIUS)#玩家2球的顏色
pygame.display.update()
board = create_board()
print_board(board)
turn = 0#用來判斷現在是輪到玩家1還是2
game_over = False
pygame.init()
SQUARESIZE = 100#遊戲介面每格的大小
width = COL *SQUARESIZE#遊戲介面的寬
height = (ROW+1) * SQUARESIZE#遊戲介面的長
size = (width, height)
RADIUS = int(SQUARESIZE/2 - 5)#圓的半徑
screen = pygame.display.set_mode(size)
draw_board(board)
pygame.display.update()
myfont = pygame.font.SysFont("monospace", 75)
while not game_over:#若有玩家贏了就跳出遊戲
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEMOTION:
pygame.draw.rect(screen, BLACK, (0, 0, width, SQUARESIZE))
posx = event.pos[0]
if turn == 0:
pygame.draw.circle(screen, RED, (posx, int(SQUARESIZE/2)), RADIUS)#玩家1的棋子
else:
pygame.draw.circle(screen, YELLOW, (posx, int(SQUARESIZE/2)), RADIUS)#玩家2的棋子
pygame.display.update()
if event.type == pygame.MOUSEBUTTONDOWN:
#print(event.pos)
#問玩家1要第幾列
if turn == 0:
posx = event.pos[0]
col = int(math.floor(posx/SQUARESIZE))
if is_valid_location(board, col):
row = get_next_open_row(board, col)
drop_piece(board, row, col, 1)
if winning_move(board, 1):
label = myfont.render("Player 1 wins!!!", 1, RED)
screen.blit(label, (40, 10))
game_over = True
#問玩家2要第幾列
else:
posx = event.pos[0]
col = int(math.floor(posx/SQUARESIZE))
if is_valid_location(board, col):
row = get_next_open_row(board, col)
drop_piece(board, row, col, 2)
if winning_move(board, 2):
label = myfont.render("Player 2 wins!!!", 1, YELLOW)
screen.blit(label, (40, 10))
game_over = True
print_board(board)
draw_board(board)
turn += 1
turn %= 2
if game_over:
pygame.time.wait(3000)
```
{"metaMigratedAt":"2023-06-17T22:46:00.374Z","metaMigratedFrom":"YAML","title":"connect 4_2","breaks":true,"slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"4d8ac2d3-29c7-4a8e-a906-e7cdf0999b25\",\"add\":2,\"del\":2},{\"id\":\"b405d87d-0698-478c-9009-9939bd969d2c\",\"add\":15,\"del\":15},{\"id\":\"83f5b3e0-d6bd-4eaf-bceb-fc6a8dfdeecf\",\"add\":10218,\"del\":456}]","description":"相反的若要判斷斜率為負,則要尋找(i,j)、(i-1,j+1)、(i-2,j+2)、(i-3,j+3)這四個點是不是都一樣"}