用Python搞點事
文字介面貪食蛇
講者: 楊平
SIRLA
https://slides.com/sirla_potato/curses_snake/fullscreen
https://slides.com/sirla_potato/curses_snake/live
大綱
- 課程介紹
- curses套件
- 遊戲程式邏輯
- 實作
課程介紹
本日目標
能學到什麼
- curses套件
- 貪食蛇遊戲程式設計
curses套件
pip install windows-curses
curses? 詛咒?
才不是
curses 是 cursor optimization 的雙關語
是一個用來製作TUI(Text User Interface)的套件
curses套件
import curses
curses.initscr() # 初始化視窗
win = curses.newwin(20, 60, 0, 0) # 設定視窗大小(nlines, ncols, x, y)
win.keypad(True) # 讓curses可以讀到方向鍵
curses.noecho() # 讓使用者輸入的字元不會顯示在終端機上
curses.curs_set(False) # 讓光標不會跳出
win.border(0) # 使用default樣式繪製邊框
# 如果按下esc則跳出程式
key = None
while key != 27:
key = win.getch() # 取得使用者輸入字元
curses.endwin()
curses套件
基本設定
# ...
win.addstr(0, 27, ' Hello! ') # (nlines, ncols, str)
key = None
while key != 27:
key = win.getch()
win.addch(10, 50, key) # (nlines, ncols, str)
curses.endwin()
curses套件
在視窗上顯示字元
遊戲程式邏輯
遊戲基本架構
- 初始化
- 主程式(無限迴圈)
- 使用者輸入
- 計算座標
- 碰撞判斷
- 顯示結果
- 結束遊戲
移動
每次移動的僅有最前端
POP
[0, 3]
[0, 2]
[0, 1]
[0, 4]
[0, 5]
POP
[1, 5]
POP
[2, 5]
POP
吃食物
POP
[0, 3]
[0, 2]
[0, 1]
[0, 4]
[0, 5]
POP
[1, 5]
POP
[2, 5]
POP
[3, 5]
[4, 5]
POP
穿牆
POP
[1, 8]
[1, 7]
[1, 6]
[1, 9]
[1, 10]
POP
[1, 6]
POP
[1, 7]
POP
[1, 8]
POP
實作
完整程式碼
https://gist.github.com/NetJagaimo/58cfc5eb013539e8cb99b98fbd44f796
修改自: https://gist.github.com/sanchitgangwar/2158089
注意cmd的視窗大小要比你遊戲的win還大,不然會出不來喔
初始化
import curses
from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
from random import randint
curses.initscr() # 初始化視窗
win = curses.newwin(20, 60, 0, 0) # 設定視窗大小(nlines, ncols, x, y)
win.keypad(True) # 讓curses可以讀到方向鍵
curses.noecho() # 讓使用者輸入的字元不會顯示在終端機上
curses.curs_set(False) # 讓光標不會跳出
win.border(0) # 使用default樣式繪製邊框
key = KEY_RIGHT
score = 0
snake = [[4,10], [4,9], [4,8]] # 初始化貪食蛇
food = [10,20] # 第一顆食物的位置
win.addstr(0, 27, ' SNAKE ') # 程式title
win.addch(food[0], food[1], '*') # 將食物顯示出來
主程式-使用者輸入
# **初始化**
while key != 27: # while esc沒有被按下
win.addstr(0, 2, 'Score : ' + str(score) + ' ') # 印出分數
win.timeout(140)
prevKey = key # 前一個按下的鍵
event = win.getch() # 如果使用者有按下按鍵就不會是-1
if event != -1:
key = event
if key not in [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, 27]: # 確認為有效輸入
key = prevKey
主程式-計算座標
# **初始化**
while key != 27:
# **使用者輸入**
# 計算貪食蛇頭部新座標
snake.insert(0, [snake[0][0] + (key == KEY_DOWN and 1) + (key == KEY_UP and -1), \
snake[0][1] + (key == KEY_LEFT and -1) + (key == KEY_RIGHT and 1)])
# 如果碰到邊界則讓它到另一邊
if snake[0][0] == 0: snake[0][0] = 18
if snake[0][1] == 0: snake[0][1] = 58
if snake[0][0] == 19: snake[0][0] = 1
if snake[0][1] == 59: snake[0][1] = 1
# 如果碰到自己則結束遊戲
if snake[0] in snake[1:]:
break
主程式-碰撞判斷&顯示結果
# **初始化**
while key != 27:
# **使用者輸入**
# **計算座標**
# 如果碰到自己
if snake[0] in snake[1:]:
break
if snake[0] == food: # 吃到食物時
food = []
score += 1
while food == []:
food = [randint(1, 18), randint(1, 58)] # 出現下一個食物
if food in snake: food = []
win.addch(food[0], food[1], '*')
else:
last = snake.pop() # 如果沒吃到食物則將最後一個pop掉
win.addch(last[0], last[1], ' ') # pop掉的座標顯示為空白
win.addch(snake[0][0], snake[0][1], '#')
結束遊戲
# **初始化**
while key != 27:
# **使用者輸入**
# **計算座標**
# **碰撞判斷&顯示結果**
curses.endwin()
print("\nScore - " + str(score))
Thank for listening
填個問卷,讓我們更好
按讚粉專,獲得最新消息!
用Python搞點事3-文字介面貪食蛇
By Sam Yang
用Python搞點事3-文字介面貪食蛇
- 803