Merge pull request 'Full refactor' (#1) from develop into master
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
47
.editorconfig
Normal file
47
.editorconfig
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# EditorConfig is awesome: http://EditorConfig.org
|
||||||
|
|
||||||
|
# Top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Global settings
|
||||||
|
# By default everything should be 4 spaces
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# Ruby
|
||||||
|
[*.{rb,ru}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Yaml and Json
|
||||||
|
[*.{yaml,yml,json}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Terraform
|
||||||
|
[*.tf]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Html, Css, Js, Ts
|
||||||
|
[*.{js,jsx,ts,tsx,css,scss,saas,html,htm}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# INI and cfg, ensure 4 TABS
|
||||||
|
[*.{conf,cfg,ini}]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# Markdown specific
|
||||||
|
[*.{md,markdown}]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
76
.gitignore
vendored
Normal file
76
.gitignore
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# mReschke Python .gitignore file standard
|
||||||
|
# Latest Version https://git.mreschke.net/-/snippets/4
|
||||||
|
# mReschke 2020-11-17
|
||||||
|
|
||||||
|
# NOTES:
|
||||||
|
# Folders should be denoted with a trailing /
|
||||||
|
# /env/ denotes only the root level ./env folder be ignored
|
||||||
|
# env/ denotes ANY env folder be ignored, even in ./some/deep/folder/env
|
||||||
|
# Sames goes for files
|
||||||
|
|
||||||
|
# OS Files
|
||||||
|
.DS_Store
|
||||||
|
._.DS_Store
|
||||||
|
._.TemporaryItems
|
||||||
|
.AppleDouble
|
||||||
|
Thumbs.db
|
||||||
|
.nfs*
|
||||||
|
.swp
|
||||||
|
|
||||||
|
# OS Folders
|
||||||
|
#
|
||||||
|
|
||||||
|
# IDE Files
|
||||||
|
#
|
||||||
|
|
||||||
|
# IDE Folders
|
||||||
|
/.idea/
|
||||||
|
/.vscode/
|
||||||
|
|
||||||
|
# Python Files
|
||||||
|
/.venv
|
||||||
|
/.env
|
||||||
|
/.coverage
|
||||||
|
*.pyc
|
||||||
|
*.py[cod]
|
||||||
|
*.egg
|
||||||
|
.Python
|
||||||
|
/.installed.cfg
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Python Folders
|
||||||
|
/instance/
|
||||||
|
/venv/
|
||||||
|
/env/
|
||||||
|
/htmlcov/
|
||||||
|
/html/
|
||||||
|
/sdist/
|
||||||
|
/dist/
|
||||||
|
/build/
|
||||||
|
*.egg-info/
|
||||||
|
eggs/
|
||||||
|
develop-eggs/
|
||||||
|
__pycache__/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Django Files
|
||||||
|
#
|
||||||
|
|
||||||
|
# Django Folders
|
||||||
|
/static/
|
||||||
|
|
||||||
|
# JavaScript Files
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# Javascript Folders
|
||||||
|
/node_modules/
|
||||||
|
|
||||||
|
# Other Files
|
||||||
|
/:memory
|
||||||
|
|
||||||
|
# Other Folders
|
||||||
|
/.vagrant/
|
||||||
448
snake.py
448
snake.py
@@ -1,185 +1,319 @@
|
|||||||
import curses
|
import curses
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
def main(stdscr, start_length, speed):
|
|
||||||
# Setup curses
|
|
||||||
curses.curs_set(0) # Hide cursor
|
|
||||||
stdscr.nodelay(1) # Non-blocking getch
|
|
||||||
|
|
||||||
w = 100
|
class Game:
|
||||||
if speed == 1: w = 250
|
|
||||||
if speed == 2: w = 225
|
|
||||||
if speed == 3: w = 200
|
|
||||||
if speed == 4: w = 175
|
|
||||||
if speed == 5: w = 150
|
|
||||||
if speed == 6: w = 125
|
|
||||||
if speed == 7: w = 100
|
|
||||||
if speed == 8: w = 75
|
|
||||||
if speed == 9: w = 50
|
|
||||||
if speed == 10: w = 25
|
|
||||||
|
|
||||||
stdscr.timeout(w) # Wait 100ms for input
|
def __init__(self, stdscr):
|
||||||
# if speed = 50 then timeout = 100
|
# Get curses standard screen
|
||||||
# if speed = 100 then timeout = 50
|
self.stdscr = stdscr
|
||||||
# if speed = 0 then timeout = 1000
|
|
||||||
|
|
||||||
# Snake and food characters
|
# Defaults
|
||||||
head_char = '█'
|
self.snake_length = 3
|
||||||
#head_char = '■'
|
self.snake_speed = 7
|
||||||
#head_char = '0'
|
|
||||||
#head_char_up = '▄'
|
|
||||||
#head_char_down = '▀'
|
|
||||||
head_char_up = head_char_down = head_char
|
|
||||||
body_char = '▓'
|
|
||||||
#body_char = 'Φ'
|
|
||||||
#body_char = '■'
|
|
||||||
#body_char = 'O'
|
|
||||||
#body_char = '░'
|
|
||||||
#body_char = '■'
|
|
||||||
#food_char = '💗'
|
|
||||||
food_char = '█'
|
|
||||||
#food_char = '▓'
|
|
||||||
#food_char = '▒'
|
|
||||||
|
|
||||||
# Setup colors
|
# Snake and food characters
|
||||||
curses.start_color()
|
# ASCII Table: https://theasciicode.com.ar/
|
||||||
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) # Snake
|
self.head_char = '█'
|
||||||
curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) # Food
|
#head_char = '■'
|
||||||
curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_BLACK) # Score/Text
|
#head_char = '0'
|
||||||
stdscr.bkgd(' ', curses.color_pair(3))
|
#head_char_up = '▄'
|
||||||
|
#head_char_down = '▀'
|
||||||
|
self.body_char = '▓'
|
||||||
|
#body_char = 'Φ'
|
||||||
|
#body_char = '■'
|
||||||
|
#body_char = 'O'
|
||||||
|
#body_char = '░'
|
||||||
|
#body_char = '■'
|
||||||
|
#food_char = '💗'
|
||||||
|
self.food_char = '█'
|
||||||
|
#food_char = '▓'
|
||||||
|
#food_char = '▒'
|
||||||
|
|
||||||
# Game constants
|
|
||||||
h, w = stdscr.getmaxyx()
|
|
||||||
# Ensure window is large enough
|
|
||||||
if h < 10 or w < 20:
|
|
||||||
stdscr.addstr(0, 0, "Terminal window too small!")
|
|
||||||
stdscr.refresh()
|
|
||||||
time.sleep(2)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Initial snake: list of [y, x]
|
def load(self):
|
||||||
# Check if snake fits horizontally
|
|
||||||
if start_length > w - 2:
|
|
||||||
stdscr.addstr(h // 2, (w - len(f"Length {start_length} too long for width {w}!")) // 2, f"Length {start_length} too long for width {w}!", curses.color_pair(3))
|
|
||||||
stdscr.refresh()
|
|
||||||
time.sleep(2)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Start the head at x=start_length so the tail ends at x=1
|
# Setup colors
|
||||||
snake = [[h // 2, start_length - i] for i in range(start_length)]
|
curses.start_color()
|
||||||
|
self.colors = {
|
||||||
|
'green': 1,
|
||||||
|
'red': 2,
|
||||||
|
'white': 3
|
||||||
|
}
|
||||||
|
curses.init_pair(self.colors['green'], curses.COLOR_GREEN, curses.COLOR_BLACK) # Snake
|
||||||
|
curses.init_pair(self.colors['red'], curses.COLOR_RED, curses.COLOR_BLACK) # Food
|
||||||
|
curses.init_pair(self.colors['white'], curses.COLOR_WHITE, curses.COLOR_BLACK) # Score/Text
|
||||||
|
self.stdscr.bkgd(' ', curses.color_pair(self.colors['white']))
|
||||||
|
|
||||||
|
# Get terminal (screen) height and width
|
||||||
|
self.screen_height, self.screen_width = self.stdscr.getmaxyx()
|
||||||
|
|
||||||
|
# Show selcome page
|
||||||
|
self.load_welcome()
|
||||||
|
|
||||||
|
# Ask for snake length
|
||||||
|
self.snake_length = self.ask_question(f"Snake Length (1 to {self.screen_width - 5}, Default {self.snake_length}): ", int, 3, 3, self.screen_width - 5)
|
||||||
|
|
||||||
|
# Ask for snake speed
|
||||||
|
self.snake_speed = self.ask_question(f"Snake Speed (1 to 10, Default {self.snake_speed}): ", int, 7, 1, 10)
|
||||||
|
|
||||||
|
# Debug Inputs
|
||||||
|
#self.print_center(f"Length: {self.snake_length}, Speed: {self.snake_speed}, Width: {self.screen_width}, Height: {self.screen_height}")
|
||||||
|
#time.sleep(2)
|
||||||
|
|
||||||
|
# Start Game!!!
|
||||||
|
self.start_game()
|
||||||
|
|
||||||
|
|
||||||
|
def start_game(self):
|
||||||
|
# Hide cursor
|
||||||
|
self.hide_cursor()
|
||||||
|
|
||||||
|
# Non-blocking getch (get character)
|
||||||
|
self.stdscr.nodelay(1)
|
||||||
|
|
||||||
|
# Calculate snake speed
|
||||||
|
wait_for_input_ms = {
|
||||||
|
1: 250,
|
||||||
|
2: 225,
|
||||||
|
3: 200,
|
||||||
|
4: 175,
|
||||||
|
5: 150,
|
||||||
|
6: 125,
|
||||||
|
7: 100,
|
||||||
|
8: 75,
|
||||||
|
9: 50,
|
||||||
|
10: 25
|
||||||
|
}
|
||||||
|
# if self.snake_speed == 1: wait_for_input_ms = 250
|
||||||
|
# if self.snake_speed == 2: wait_for_input_ms = 225
|
||||||
|
# if self.snake_speed == 3: wait_for_input_ms = 200
|
||||||
|
# if self.snake_speed == 4: wait_for_input_ms = 175
|
||||||
|
# if self.snake_speed == 5: wait_for_input_ms = 150
|
||||||
|
# if self.snake_speed == 6: wait_for_input_ms = 125
|
||||||
|
# if self.snake_speed == 7: wait_for_input_ms = 100
|
||||||
|
# if self.snake_speed == 8: wait_for_input_ms = 75
|
||||||
|
# if self.snake_speed == 9: wait_for_input_ms = 50
|
||||||
|
# if self.snake_speed == 10: wait_for_input_ms = 25
|
||||||
|
self.stdscr.timeout(wait_for_input_ms[self.snake_speed])
|
||||||
|
|
||||||
|
# Ensure window is large enough
|
||||||
|
if self.screen_height < 10 or self.screen_width < 20:
|
||||||
|
self.print_center("Terminal window is too small!")
|
||||||
|
time.sleep(2)
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# Start the head at x=self.snake_length so the tail ends at x=1
|
||||||
|
snake = [[self.screen_height // 2, self.snake_length - i] for i in range(self.snake_length)]
|
||||||
|
|
||||||
|
# Initial food
|
||||||
|
def get_new_food():
|
||||||
|
while True:
|
||||||
|
nf = [random.randint(1, self.screen_height - 2), random.randint(1, self.screen_width - 2)]
|
||||||
|
if nf not in snake:
|
||||||
|
return nf
|
||||||
|
|
||||||
|
food = get_new_food()
|
||||||
|
|
||||||
|
# Initial direction
|
||||||
|
key = curses.KEY_RIGHT
|
||||||
|
score = self.snake_length
|
||||||
|
|
||||||
# Initial food
|
|
||||||
def get_new_food():
|
|
||||||
while True:
|
while True:
|
||||||
nf = [random.randint(1, h - 2), random.randint(1, w - 2)]
|
next_key = self.stdscr.getch()
|
||||||
if nf not in snake:
|
# If no key is pressed, next_key is -1
|
||||||
return nf
|
# Update direction if it's a valid arrow key and not opposite to current
|
||||||
|
if next_key != -1:
|
||||||
|
# DOWN
|
||||||
|
if next_key == curses.KEY_DOWN and key != curses.KEY_UP:
|
||||||
|
key = next_key
|
||||||
|
# UP
|
||||||
|
elif next_key == curses.KEY_UP and key != curses.KEY_DOWN:
|
||||||
|
key = next_key
|
||||||
|
# LEFT
|
||||||
|
elif next_key == curses.KEY_LEFT and key != curses.KEY_RIGHT:
|
||||||
|
key = next_key
|
||||||
|
# RIGHT
|
||||||
|
elif next_key == curses.KEY_RIGHT and key != curses.KEY_LEFT:
|
||||||
|
key = next_key
|
||||||
|
# (P)ause
|
||||||
|
elif next_key == ord('p'):
|
||||||
|
previous_key = key
|
||||||
|
self.print_center("Game Paused. Press P to Resume.")
|
||||||
|
while True:
|
||||||
|
key = self.stdscr.getch()
|
||||||
|
if key == ord('p'):
|
||||||
|
break
|
||||||
|
key = previous_key
|
||||||
|
continue
|
||||||
|
# (R)estart
|
||||||
|
elif next_key == ord('r'):
|
||||||
|
self.start_game()
|
||||||
|
return
|
||||||
|
# (Q)uit
|
||||||
|
elif next_key == ord('q'):
|
||||||
|
break
|
||||||
|
|
||||||
food = get_new_food()
|
# Calculate new head
|
||||||
|
head = snake[0]
|
||||||
|
if key == curses.KEY_DOWN:
|
||||||
|
new_head = [head[0] + 1, head[1]]
|
||||||
|
elif key == curses.KEY_UP:
|
||||||
|
new_head = [head[0] - 1, head[1]]
|
||||||
|
elif key == curses.KEY_LEFT:
|
||||||
|
new_head = [head[0], head[1] - 1]
|
||||||
|
elif key == curses.KEY_RIGHT:
|
||||||
|
new_head = [head[0], head[1] + 1]
|
||||||
|
else:
|
||||||
|
new_head = [head[0], head[1]]
|
||||||
|
pass
|
||||||
|
# Should not happen
|
||||||
|
#exit('yyyyy')
|
||||||
|
#new_head = head
|
||||||
|
|
||||||
# Initial direction
|
# Check collisions
|
||||||
key = curses.KEY_RIGHT
|
if (new_head[0] in [0, self.screen_height - 1] or
|
||||||
score = start_len
|
new_head[1] in [0, self.screen_width - 1] or
|
||||||
|
new_head in snake):
|
||||||
hc = head_char
|
# Crashed into something, show quit screen
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
next_key = stdscr.getch()
|
|
||||||
# If no key is pressed, next_key is -1
|
|
||||||
# Update direction if it's a valid arrow key and not opposite to current
|
|
||||||
if next_key != -1:
|
|
||||||
if next_key == curses.KEY_DOWN and key != curses.KEY_UP:
|
|
||||||
key = next_key
|
|
||||||
hc = head_char_down
|
|
||||||
elif next_key == curses.KEY_UP and key != curses.KEY_DOWN:
|
|
||||||
key = next_key
|
|
||||||
hc = head_char_up
|
|
||||||
elif next_key == curses.KEY_LEFT and key != curses.KEY_RIGHT:
|
|
||||||
key = next_key
|
|
||||||
hc = head_char
|
|
||||||
elif next_key == curses.KEY_RIGHT and key != curses.KEY_LEFT:
|
|
||||||
key = next_key
|
|
||||||
hc = head_char
|
|
||||||
elif next_key == ord('q'): # Allow quit
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# Calculate new head
|
snake.insert(0, new_head)
|
||||||
head = snake[0]
|
|
||||||
if key == curses.KEY_DOWN:
|
|
||||||
new_head = [head[0] + 1, head[1]]
|
|
||||||
elif key == curses.KEY_UP:
|
|
||||||
new_head = [head[0] - 1, head[1]]
|
|
||||||
elif key == curses.KEY_LEFT:
|
|
||||||
new_head = [head[0], head[1] - 1]
|
|
||||||
elif key == curses.KEY_RIGHT:
|
|
||||||
new_head = [head[0], head[1] + 1]
|
|
||||||
else:
|
|
||||||
# Should not happen
|
|
||||||
new_head = head
|
|
||||||
|
|
||||||
# Check collisions
|
# Check if snake ate food
|
||||||
if (new_head[0] in [0, h - 1] or
|
if snake[0] == food:
|
||||||
new_head[1] in [0, w - 1] or
|
score += 1
|
||||||
new_head in snake):
|
food = get_new_food()
|
||||||
key = stdscr.getch()
|
else:
|
||||||
break
|
snake.pop() # Remove tail
|
||||||
|
|
||||||
snake.insert(0, new_head)
|
# Draw everything
|
||||||
|
self.clear_screen()
|
||||||
|
self.stdscr.attron(curses.color_pair(3))
|
||||||
|
self.stdscr.border(0)
|
||||||
|
self.stdscr.attroff(curses.color_pair(3))
|
||||||
|
|
||||||
# Check if snake ate food
|
# Draw snake
|
||||||
if snake[0] == food:
|
for i, (y, x) in enumerate(snake):
|
||||||
score += 1
|
char = self.head_char if i == 0 else self.body_char
|
||||||
food = get_new_food()
|
self.stdscr.addch(y, x, char, curses.color_pair(1))
|
||||||
else:
|
|
||||||
snake.pop() # Remove tail
|
|
||||||
|
|
||||||
# Draw everything
|
# Draw food
|
||||||
stdscr.clear()
|
self.stdscr.addch(food[0], food[1], self.food_char, curses.color_pair(2))
|
||||||
stdscr.attron(curses.color_pair(3))
|
|
||||||
stdscr.border(0)
|
|
||||||
stdscr.attroff(curses.color_pair(3))
|
|
||||||
|
|
||||||
# Draw snake
|
# Draw score
|
||||||
for i, (y, x) in enumerate(snake):
|
self.stdscr.addstr(0, 2, f' Length: {score} @ {self.snake_speed}MPH ({self.screen_width}x{self.screen_height}) ', curses.color_pair(3))
|
||||||
char = hc if i == 0 else body_char
|
|
||||||
stdscr.addch(y, x, char, curses.color_pair(1))
|
|
||||||
|
|
||||||
# Draw food
|
self.refresh_screen()
|
||||||
stdscr.addch(food[0], food[1], food_char, curses.color_pair(2))
|
|
||||||
|
|
||||||
# Draw score
|
# Game Over screen
|
||||||
stdscr.addstr(0, 2, f' Length: {score} @ {speed}MPH ({w}x{h}) ', curses.color_pair(3))
|
self.print_center(f"GAME OVER! SCORE: {score}", 0, self.colors['red'])
|
||||||
|
self.print_center(f"(R)estart, or (Q)uit", 2, self.colors['green'])
|
||||||
|
self.stdscr.nodelay(0)
|
||||||
|
while True:
|
||||||
|
key = self.stdscr.getch()
|
||||||
|
if key == ord('r'):
|
||||||
|
self.start_game()
|
||||||
|
return
|
||||||
|
elif key == ord('q'):
|
||||||
|
# Game over, exit app!
|
||||||
|
exit()
|
||||||
|
|
||||||
stdscr.refresh()
|
|
||||||
|
|
||||||
# Game Over screen
|
def print_center(self, value, y_offset = 0, color = 3):
|
||||||
#stdscr.clear()
|
# Calculate center position
|
||||||
msg = f"GAME OVER! SCORE: {score}"
|
y = self.screen_height // 2
|
||||||
stdscr.addstr(h // 2, (w - len(msg)) // 2, msg, curses.color_pair(3))
|
x = (self.screen_width - len(value)) // 2
|
||||||
stdscr.addstr(h // 2 + 1, (w - 18) // 2, "Press Q to exit", curses.color_pair(3))
|
if x < 0: x = 1
|
||||||
stdscr.nodelay(0)
|
self.stdscr.addstr(int(y + y_offset), int(x), value, curses.color_pair(color))
|
||||||
key = stdscr.getch()
|
self.refresh_screen()
|
||||||
while key != ord('q'):
|
|
||||||
key = stdscr.getch()
|
|
||||||
exit('bye')
|
def ask_question(self, question: str, value_type: Any, value_default: Any, value_min: int, value_max: int) -> Any:
|
||||||
|
# Make the cursor visible
|
||||||
|
curses.curs_set(1)
|
||||||
|
|
||||||
|
# Calculate center position of prompt
|
||||||
|
y = self.screen_height // 2
|
||||||
|
x = (self.screen_width - len(question)) // 2
|
||||||
|
if x < 0: x = 1
|
||||||
|
|
||||||
|
# Display question and wait for input + ENTER key to finish
|
||||||
|
self.clear_screen()
|
||||||
|
self.stdscr.addstr(y, x, question)
|
||||||
|
self.refresh_screen()
|
||||||
|
curses.noecho()
|
||||||
|
curses.cbreak()
|
||||||
|
|
||||||
|
# Wait for answer with ENTER key to end input
|
||||||
|
answer = ""
|
||||||
|
while True:
|
||||||
|
key = self.stdscr.getch()
|
||||||
|
|
||||||
|
# Check if the Enter key (ASCII 10 or 13) was pressed
|
||||||
|
if key == curses.KEY_ENTER or key in [10, 13]:
|
||||||
|
break
|
||||||
|
# Handle backspace
|
||||||
|
elif key == curses.KEY_BACKSPACE or key == 127:
|
||||||
|
if len(answer) > 0:
|
||||||
|
answer = answer[:-1]
|
||||||
|
# Erase the character from the screen
|
||||||
|
self.stdscr.addch('\b')
|
||||||
|
self.stdscr.addch(' ')
|
||||||
|
self.stdscr.addch('\b')
|
||||||
|
# Handle regular characters (check for printable ASCII range if needed)
|
||||||
|
elif 32 <= key <= 126:
|
||||||
|
answer += chr(key)
|
||||||
|
self.stdscr.addch(key) # Manually echo the character
|
||||||
|
|
||||||
|
self.refresh_screen()
|
||||||
|
|
||||||
|
# Validate input
|
||||||
|
if value_type == int:
|
||||||
|
try:
|
||||||
|
answer = int(answer)
|
||||||
|
except Exception as e:
|
||||||
|
answer = value_default
|
||||||
|
if answer < value_min or answer > value_max:
|
||||||
|
# Invalid integer, ask again
|
||||||
|
self.print_center(f"ERROR: Must be an integer between {value_min} and {value_max}", 2, self.colors['red'])
|
||||||
|
time.sleep(2)
|
||||||
|
self.ask_question(question, value_type, value_min, value_max)
|
||||||
|
|
||||||
|
return answer
|
||||||
|
|
||||||
|
|
||||||
|
def load_welcome(self):
|
||||||
|
self.hide_cursor()
|
||||||
|
self.clear_screen()
|
||||||
|
self.print_center("█▓▒░ Welcome to Curses Python!!! ░▒▓█", 0, self.colors['red'])
|
||||||
|
self.print_center("by mReschke Productions", 2, self.colors['green'])
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
|
||||||
|
def hide_cursor(self):
|
||||||
|
curses.curs_set(0)
|
||||||
|
|
||||||
|
|
||||||
|
def show_cursor(self):
|
||||||
|
curses.curs_set(1)
|
||||||
|
|
||||||
|
|
||||||
|
def clear_screen(self):
|
||||||
|
self.stdscr.clear()
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_screen(self):
|
||||||
|
self.stdscr.refresh()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main(stdscr):
|
||||||
|
game = Game(stdscr)
|
||||||
|
game.load()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
game = curses.wrapper(main)
|
||||||
start_len = input("Enter starting snake length (default 3): ")
|
|
||||||
start_len = int(start_len) if start_len.strip() else 3
|
|
||||||
if start_len < 1:
|
|
||||||
start_len = 3
|
|
||||||
except ValueError:
|
|
||||||
start_len = 3
|
|
||||||
|
|
||||||
try:
|
|
||||||
speed = input("Enter snake speed (1 to 10, default 7): ")
|
|
||||||
speed = int(speed) if speed.strip() else 7
|
|
||||||
if speed > 10: speed = 10
|
|
||||||
if speed < 1: speed = 1
|
|
||||||
except ValueError:
|
|
||||||
speed = 7
|
|
||||||
|
|
||||||
curses.wrapper(main, start_len, speed)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user